将两个 32 位数字相乘并将 64 位结果打印为十进制 NASM 程序集

multiplying two 32-Bit Numbers and printing the 64 bit result as decimal NASM assembly

我在使用 NASM 程序集时遇到问题。

我不知道如何将 2 个数字相乘并将它们打印到屏幕上。

问题是我们只能使用一个只打印32位长度数字的函数;不是 64 位长度的数字。

所以我的问题可能是数学问题,我想我需要使用霍纳的方法来得到小数;就像我在下面指出的那样。

如果我有

AF / A = 11 remaining 5 
11 / A = 1 remaining 7
1 / A = 0 remaining 1

-> 175 是正确的结果

但是当我在这里把它分成两个寄存器时,每个 4 字节就像一个例子

A | F    A / A = 1 remaining 0 and F / A = 1 remaining 5
         1 / A = 0 remaining 1

->150 这是错误的

这是我的汇编代码

mov eax, [Zahl1]
mul dword [Zahl2]
mov [High], edx


;---- low-----
mov ebx, 10
loopbegin:
;dividing by 10
xor edx, edx
div ebx

;counting
inc dword [counter]

;saving the number 
push edx
cmp eax, 0
jne loopbegin

mov ebx, 10
; --- high ----
mov eax, [High]
highloop:
xor edx, edx
div ebx

inc dword [counter]

push edx
cmp eax, 0
jne highloop

<note> 这里遵循从堆栈打印数字的循环

你不能只转换+打印两半,因为高半部分的位代表整个64位数字中的4294967296 * hi

4294967296 不是 10 的幂,因此高半部分的位会影响小数点的低位。如果您以 2 的幂为基数打印,例如十六进制或八进制,您的方法会起作用,因为除以基数只是一个移位:即低十六进制数字仅由低 4 位确定。但是低位十进制数取决于所有64个二进制位。


相反,您需要进行 64 位除以 10。这需要多个 div 指令,因为如果商溢出 32 位,div r32 (64b / 32b => 32b) 会出错。 有关扩展精度除法 的工作代码,请参阅Assembler 64b division。 (但不要将 xchg 与内存一起使用;而是使用一些额外的寄存器)。

(div 在现代 CPU 上很慢而 mul 非常快;可能值得进行扩展精度乘法以获得 64b * 64b => 128b 乘法的高半部分a fixed-point multiplicative inverse 除以 10 更快。)


此外,您不需要 push 数字,也不需要内存中的计数器。只需为从缓冲区末尾开始的指针使用一个额外的寄存器。周边代码的写法见How do I print an integer in Assembly Level Programming without printf from the c library?,只需用两条div指令将内层循环中的32位除法替换为扩展精度即可。