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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了将两个32位数相乘并将64位结果打印为十进制NASM程序集相关的知识,希望对你有一定的参考价值。

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

我无法弄清楚如何将2个数字相乘并将它们打印到屏幕上。

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

所以我的问题可能是数学,我想我需要用Horner的方法得到十进制数;我在下面说明。

如果我有

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 remaing 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

这里是循环打印堆栈中的数字

答案

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

4294967296不是10的幂,因此高半位中的位会影响低十进制数。如果你使用2或2的幂来打印,比如十六进制或八进制,你的方法就可以工作,因为除以基数只是一个移位:即低十六进制数字仅由低4位决定。但是低十进制数取决于所有64位二进制位。


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

div很慢,mul在现代CPU上速度非常快;可能值得进行扩展精度乘法以获得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位除法。

以上是关于将两个32位数相乘并将64位结果打印为十进制NASM程序集的主要内容,如果未能解决你的问题,请参考以下文章

C# checked和unchecked详解

如果机器有 64 位字,则将两个 129 字数相乘需要多少位?

NASM ctypes SIMD - 如何访问返回到ctypes的128位数组?

怎么计算二进制数的运算

Python位运算符

Python位运算符