如何在 EDX:EAX 中打印乘法结果

问题描述 投票:0回答:1

汇编中32位数相乘时,结果放在EDX:EAX组合中。结果的上半部分进入 EDX,下半部分进入 EAX。如果 EDX 和 EAX 都有两部分结果,我如何使用 Irvine32 位库将这些值打印到屏幕上?查看示例代码和注释:

.386
.model flat, stdcall
.stack 4096
ExitProcess proto, dwExitCode:dword
include Irvine32.inc

.data
    num1 dword 1000000
    num2 dword 1000000
    temp dword ?
    full_result qword ?
.code
main proc
    mov eax, num1
    mul num2 ;Result will be put in EDX:EAX (Upper half of number and Lower half of number)
    ;EDX has the value 232 in decimal. 000000E8 in hex
    ;EAX has the value 3567587328 in decimal. D4A51000 in hex
    ;When you put these numbers togather, you get 000000E8D4A51000 in hex. 
    ;When you convert these numbers back to its decimal representation, we get the correct value of 1000000000000

    ;How to display the result into the screen using Irvine32 library (not 64)
    mov temp, eax
    mov eax, edx ;Put the upper half of result in eax
    call WriteDec ;Write the value in eax
    mov eax, temp ;Put the lower half of result in eax
    call WriteDec

    ;This will prints out 2323567587328 instead of 1000000000000

invoke ExitProcess, 0
main endp
end main

有没有办法将这个数字 2323567587328 转换成不同的形式,以便我可以正确显示上半部分和下半部分? (打包 BCD 等。)

如果无法以某种方式格式化此数字,以便我可以在两个不同的寄存器中拥有 1000000000000,请告诉我如何将此值分配给

full_result
qword 类型变量。

assembly masm irvine32
1个回答
0
投票
mov eax, num1
mul num2

这个

mul
指令在 EDX:EAX 中产生一个 unsigned 64 位产品。
接下来的代码将 EDX:EAX 中保存的 unsigned 64 位数字转换为其十进制表示形式。然后可以使用 Irvine 的
WriteString
函数输出一个字符串。

EDX:EAX中保存的unsigned 64位数字的转换

在 x86 上,需要级联 2 个除法来将 EDX:EAX 中的 64 位值除以 10.
第一除法除以高股息(用 0 扩展)产生高商。第二个除法除以低股息(用第一个除法的余数扩展)产生低商。这是我们保存在堆栈中的第二部分的剩余部分。

为了检查 EDX:EAX 中的 qword 是否为零,我在临时寄存器中对两半进行了或运算。

我没有计算数字,需要寄存器,而是选择在堆栈上放置一个哨兵。因为这个哨兵得到一个值 (10),任何数字都不可能有 ([0,9]),所以它很好地允许确定存储循环何时必须停止。

.data
    num1   dword 1000000
    num2   dword 1000000
    Buffer byte 32 dup(0)
.code
main proc
    mov     eax, num1
    mul     num2

    mov     edi, OFFSET Buffer ; Begin of the buffer
    mov     ebx, 10        ; CONST
    push    ebx            ; Sentinel
.a: mov     ecx, eax       ; Temporarily store LowDividend in ECX
    mov     eax, edx       ; First divide the HighDividend
    xor     edx, edx       ; Setup for division EDX:EAX / EBX
    div     ebx            ; -> EAX is HighQuotient, Remainder is re-used
    xchg    eax, ecx       ; Temporarily move it to ECX restoring LowDividend
    div     ebx            ; -> EAX is LowQuotient, Remainder EDX=[0,9]
    push    edx            ; (1) Save remainder for now
    mov     edx, ecx       ; Build true 64-bit quotient in EDX:EAX
    or      ecx, eax       ; Is the true 64-bit quotient zero?
    jnz     .a             ; No, use as next dividend

    pop     eax            ; (1a) First pop (Is digit for sure)
.b: add     eax, "0"       ; Turn into character [0,9] -> ["0","9"]
    stosb                  ; Store in buffer
    pop     eax            ; (1b) All remaining pops
    cmp     eax, ebx       ; Was it the sentinel?
    jb      .b             ; Not yet
    mov     BYTE PTR [edi], 0 ; Irvine32 requires zero-termination

    mov     edx, OFFSET Buffer
    call    WriteString

EDX:EAX中保存的signed 64位数字的转换

程序如下:

首先通过测试符号位来判断有符号数是否为负数
如果是,则将数字取反并输出一个“-”字符。

该片段的其余部分与无符号数相同。

    mov     edi, OFFSET Buffer ; Begin of the buffer
    test    edx, edx       ; Sign bit is bit 31 of high dword
    jns     .u             ; It's a positive number
    neg     edx            ; |
    neg     eax            ; | Negate EDX:EAX
    sbb     edx, 0         ; |
    mov     BYTE PTR [edi], "-"
    inc     edi
.u: mov     ebx, 10        ; CONST
    push    ebx            ; Sentinel
.a:
    ...

以上代码片段基于我的16位问答DOS显示数字。你也可以阅读它以获得一些额外的解释......

© www.soinside.com 2019 - 2024. All rights reserved.