32位汇编语言学习笔记(5)--特殊的算术操作

来源:互联网 发布:哪个电子狗软件好用 编辑:程序博客网 时间:2024/05/30 04:06


imull Sedx:eax = eax * Sedx表示64位的高32位,eax表示低32位),有符号64位乘法。

mull Sedx:eax = eax * S,无符号64位乘法。

cltdeax寄存器中的数,按照符号位扩展到edx,转为8个字节。

idivl Sedx =edx:eax mod Seax =edx:eax / S,有符号除法。

divl Sedx =edx:eax mod Seax =edx:eax / S,无符号除法。

 一对寄存器edx:eax组成64位的四字。

 示例:

long long mul_64(long long a, long long b)

{

   long long c = a*b;

   return c;

}

gcc -O1 -S -m32 mul_64.c

mul_64:

       pushl  %ebp

       movl   %esp, %ebp

       subl   $12, %esp //栈指针下移12个字节。

       movl   %ebx, (%esp) //保存ebx

       movl   %esi, 4(%esp) //保存esi

       movl   %edi, 8(%esp) //保存edi

       movl   8(%ebp), %ecx

       movl   12(%ebp), %ebx//ebx:ecx用于保存64位整数a

       movl   16(%ebp), %eax

       movl   20(%ebp), %edx//edx:eax用于保存64位整数b

       movl   %edx, %esi //b的高位32位装入esi

       imull  %ecx, %esi //a的低32位与b的高32位相乘,结果放到esi中。

       movl   %ebx, %edi //a的高位32位装入edi

       imull  %eax, %edi //a的高32位与b的低32位相乘,结果放到edi中。

       addl   %edi, %esi //两个中间结果相加,放到esi中。

       mull   %ecx //a的低32位与b的低32位相乘,结果放到edx:eax中。

       addl   %edx, %esi //把上条指令计算结果的高32位,与edi保存的中间结果相加。

       movl   %esi, %edx//把计算结果保存回edx中。

       movl   (%esp), %ebx //恢复ebx

       movl   4(%esp), %esi //恢复esi

       movl   8(%esp), %edi //恢复edi

       movl   %ebp, %esp

       popl   %ebp

       ret

对算法的解释:

a = (a1* 2^32 + a2)

b = (b1*2^32 + b2)

假设a1b1都不为0,两个高32位乘必然大于2^64,会溢出,所以忽略。

因此乘法只计算a1*b2 + b1*a2,如果这个结果溢出,也不用关心。

如果没有溢出,那么结果应该保存在高32位,与a2*b2结果求和。

int div_32(long a, long b)

{

   long c = a / b;

   return c;

}

gcc -O1 -S -m32 div.c

div_32:

       pushl  %ebp

       movl   %esp, %ebp

       movl   8(%ebp), %edx //a装入到edx

       movl   %edx, %eax //复制aeax

       sarl   $31, %edx //算术右移31位,相当于edx都用符号位填充了。

       idivl  12(%ebp) //a/b = eax a modb = edx

       popl   %ebp

       ret
0 0