如何打印出MUL产品的输出?

时间:2014-01-19 05:39:05

标签: assembly masm

我在汇编(MASM)中使用MUL来乘以两个整数。

根据MASM指令集文档,产品存储在EDX:EAX中,EDX和EAX寄存器的组合(如果我理解正确的话)。

所以我首先尝试打印出EDX寄存器的结果,然后打印EAX寄存器以打印出整个数字。

但是当我得到的产品应该超过32位(小数点后10位)时,我得到一个奇怪的答案。

例如100000 * 100000 = 21410065408,这是错误的。 但是对于小的乘法,它可以工作。

这是汇编代码:

; MULTIPLY 
    mov eax, var1 ; var1 and var2 from user input
    mul var2 
    mov productResultEDX, edx
    mov productResultEAX, eax


; PRINT RESULT
; mov edx, OFFSET productMsg
    call WriteString
    mov eax, productResultEDX 
    call WriteDec ; prints out EAX register data
    ;mov eax, productResultEAX
    ;call WriteDec

所有变量都声明为32位DWORDS

我接近这个错误吗?

3 个答案:

答案 0 :(得分:3)

我相信你使用的是Irvine图书馆?这不能打印64位数字,至少我不记得它能够。

因此,除非您想要编写自己的64位数字打印例程,否则只需使用c函数printf,masm32将其称为crt_printf

您可以创建qword变量来存储edx:eax,也可以使用结构。

include masm32rt.inc
include msvcrt.inc
includelib msvcrt.lib

BigNum struc
    LoWord  dd  ?
    HiWord  dd  ?
BigNum ends

.data
fmtqw1      db  "100000 * 100000 = %llu",13, 10, 0
fmtqw2      db  "400030 * 500020 = %llu",13, 10, 0

.data?
myqword     dq  ?
BigNumber   BigNum <>

.code
start:

    mov     eax, 100000
    mov     ecx, 100000
    mul     ecx
    mov     dword ptr[myqword], eax
    mov     dword ptr[myqword + 4], edx
    invoke  crt_printf, offset fmtqw1, myqword

    mov     eax, 400030
    mov     ecx, 500020
    mul     ecx    
    mov     BigNumber.LoWord, eax
    mov     BigNumber.HiWord, edx
    invoke  crt_printf, offset fmtqw2, BigNumber

    inkey
    invoke  ExitProcess, 0
end start

64 bit mul results

答案 1 :(得分:1)

你正在做这个算术:100,000 * 100,000。

我们都希望答案是10,000,000,000(100亿)

现在,碰巧有十亿,十六进制,

2 540B E400

我的猜测(完全在这里猜测)是你的WriteStringWriteDec例程并不是真的意识到你可能有一个大的(64位)数字你正在尝试打印

这可能有助于澄清一些事情......

十亿,2 540B E400

其中最后32位是:540B E400

该值以十进制表示:1,410,065,408

如果您在数字2前面加上该值,则表示您的错误答案,即21,410,065,408

这是建议的测试

使用现有代码将这两个数字相乘......

286,331,153 * 15您应该得到4,294,967,295,其中一个小于4 Gig

现在将第一个数字增加1,再次进行乘法运算;即,

286,331,153 * 15您应该获得4,294,967,310(即比第一次增加15个)。

如果您的程序显示答案是115,那么您已经确定了错误。

这是发生了什么。

286,331,153 * 15也是1111,1111h * 0000,000Fh

(逗号仅供阅读使用)

产品是FFFF,FFFFH或刚刚提到的四个演出(减一)

现在,如果我们将数字增加一个,就像这样

286,331,154 * 15

我们现在有

1111,1112h * 0000,000Fh

结果为:1 0000 000E

因此,如果您的预期十进制数4,294,967,310实际显示为115,则表示您已找到错误。

答案 2 :(得分:1)

这就是我使用的。这不是最佳的! Nasm语法,可能需要对Masm进行微小改动。调整它以满足您的需求。

;    ----------------------------------------
; u64toda - converts (64 bit) integer in edx:eax
; to (comma delimited) decimal representation in
; ascii zero terminated string in buffer pointed to by edi
;--------------------------------------------
u64toda:
            pusha
            mov ebx, edx     ; stash high dword
            mov esi,0Ah      ; prepare to divide by 10
            xor ecx, ecx     ; zero the digit count
            jmp highleft     ; check is high word 0 ?
highword:
            xchg eax,ebx    ; swap high & low words
            xor edx,edx     ; zero edx for the divide!
            div esi         ; divide high word by 10
            xchg eax,ebx    ; swap 'em back
            div esi         ; divide low word including remainder
            push edx        ; remainder is our digit - save it
            inc ecx         ; count digits
highleft:
            or ebx,ebx
            jnz highword
lowleft:
            xor edx,edx          ; zero high word
            div esi              ; divide low word by 10
            push edx             ; our digit
            inc ecx              ; count it
            or eax,eax           ; 0 yet ?
            jne lowleft
            cmp ecx, byte 4      ; commas needed ?
            jl write2buf         ; nope
            xor edx,edx            ; zero high word for divide
            mov eax,ecx            ; number of digits
            mov ebx,3
            div ebx
            mov esi,edx            ; remainder = number digits before comma
            test edx,edx
            jnz write2buf        ; no remainder?
            mov esi,3             ; we can write 3 digits, then.
write2buf:
            pop eax              ; get digit back - in right order
            add al,30H           ; convert to ascii character
            stosb                ; write it to our buffer
            dec esi               ; digits before comma needed
            jnz moredigits       ; no comma needed yet
            cmp ecx,2             ; we at the end?
            jl moredigits        ; don't need comma
            mov al,','           ; write a comma
            stosb
            mov esi,03h           ; we're good for another 3 digits
moredigits:
            loop write2buf       ; write more digits - cx of 'em
            mov al,00h           ; terminate buffer with zero
            stosb
    popa
            ret
;-------------------------------------