2015-10-05 150 views
-2

以下代码计算x和y的乘积并将结果存储在内存中。数据类型ll_t被定义为 等于long long。在32位机器上实现64位算术 - 汇编代码

GCC产生执行计算以下组件的代码:

typedef long long ll_t; 

void store_prod(ll_t *dest, int x, ll_t y) 
{ 
*dest = x*y; 
} 

DEST在的%ebp + 8,X在的%ebp + 12,Y在的%ebp + 16

1 movl 16(%ebp), %esi 
2 movl 12(%ebp), %eax 
3 movl %eax, %edx 
4 sarl $31, %edx 
5 movl 20(%ebp), %ecx 
6 imull %eax, %ecx 
7 movl %edx, %ebx 
8 imull %esi, %ebx 
9 addl %ebx, %ecx 
10 mull %esi 
11 leal (%ecx,%edx), %edx 
12 movl 8(%ebp), %ecx 
13 movl %eax, (%ecx) 
14 movl %edx, 4(%ecx) 

此代码使用三次乘法来实现在32位机器上实现64位算术运算所需的多精度算法 。描述用于计算产品的算法,并注释汇编代码以显示其如何实现您的算法。

问题:第5行是做什么的?它注册ecx有什么价值? 第11行也做了什么?

+0

如果您的偏移量为8,12,16和20,那么它们都是32位。 64位操作数会有8个字节的偏移量。 – stark

+0

@stark错误。 'dest'是一个指针,所以4个字节。 'x'确实是32位。 'y'是64位,从+16开始,低dword,+ 20高dword。 – Jester

+0

[LEA指令的目的是什么?](http://stackoverflow.com/q/1658294/995714),[MOV和LEA有什么区别](http://stackoverflow.com/q/1699748/ 995714) –

回答

2

第5行:它将一些局部变量的值复制到ECX。由于我们缺少原始功能代码的一部分,因此此列表中的值未知。

第11行:它相当于:EDX = EDX + ECX。 LEA指令用于计算内存值的EA并将该EA存储到目标寄存器,因此可用于快速执行加法和常数乘法。

+1

第5行复制'y'操作数的高位字。 – Jester

+0

所以添加了这个功能。但即时通讯仍然不确定eax(x)在下一行(第6行)中的乘数。 – user2800591

+2

这是一个愚蠢的方式做一个32 * 64乘以64位扩展到64位和64 * 64。 – Jester