前言
这个问题出自我的汇编语言期末大作业的一道题的其中一个步骤。原题是这样的:
以10进制显示无符号数乘法的积。包含一个参数,即乘法操作数的位数: 8, 16, 32.(不做乘法操作,仅显示结果)
想把这道题做出来,可以将整数转换成字符串,再输出这个字符串。当乘法操作数的位数为8或者16的时候,这个问题很(直)好(接)解(调)决(库)。但是当乘法操作数的位数为32时,这种情况不好处理。难点在于,32位汇编没有办法直接(意思是只用一条指令)对64位整数进行运算。
在x86平台下,使用MUL指令对32位操作数进行无符号数乘法运算,其乘积的高32位存放在EDX寄存器中,低32位存放在EAX寄存器。即EDX:EAX共同表示一个64位整数。
那么,现在的问题是:(在32位x86汇编环境下,)怎么将64位整数转换为字符串?
本文的算法稍作修改,也适用于在64位汇编下将128位整数转换为字符串。
整数转换为字符串的一般方法
在刚学C/C++的时候,我们也许会做过这么一道习题:求一个数的各位数之和。这道题的核心代码只有区区几行,非常简单:
int
这段代码稍加改造,就可以把一个数转成字符串:
char
对于64位整数,我们也是采取这样的思路进行转换。 但是如果对64位整数直接整除和取余,会存在运算结果溢出的问题。下面我们先来看看推导一下整除和取余后的结果会是怎样的。汇编的最终实现在下下一部分。
对64位整数进行整除和取余的公式推导
设64位整数x的高32位为H,低32位为L,可以将x写成
由于除数为10,我们把
(2)(3)(4)代入(1)式得
展开,得
下面我们计算x/10和x%10:
整理得:
由(2)式,得
观察上式,可以发现x整除10后,新的高32位
现在计算x%10。观察x的展开式,显然有
64位整数转换为字符串的汇编实现
根据上一部分推导的公式,我们先用C语言给出算法描述:
unsigned
最终x86汇编代码如下:
.data
constFactor DWORD 429496729
constDec DWORD 10
intH DWORD 0
intL DWORD 0
r1 DWORD 0
r2 DWORD 0
q DWORD 0
buffer BYTE 30 DUP(0)
.code
pushad
mov esi,0
mov intH,edx
mov intL,eax
.WHILE int>0
;计算edx/10的商和余数,并将商赋值给intH
mov eax,intH
mov ebx,constDec
mov edx,0
div ebx
mov intH,eax
mov r1,edx
;计算eax/10的商和余数
mov eax,intL
mov ebx,constDec
mov edx,0
div ebx
mov r2,edx
mov q,eax
;计算(6*r1+r2)/10的商和余数
mov eax,r1
mov ebx,6
mul ebx ;这里可以用移位和加法实现,不想写了
add eax,r2
mov ebx,constDec
mov edx,0
div ebx
;余数用来输出10进制
mov buffer[esi],dl
add buffer[esi],48
inc esi
;商存在ecx
mov ecx,eax
;计算intL
mov eax,constFactor
mov ebx,r1
mul ebx
add eax,q
add eax,ecx
mov intL,eax
.ENDW
;esi表示字符串长度
popad
后记
我做这个题的时候,我认识的许多人都不能很完美的解答出来。查阅了CSDN的博客,再经过自己的思考和推导,才把它做出来。最后,我《汇编语言程序设计》这门课取得了绩点5.0的好成绩。