我正在阅读我的教科书,它有交换功能的代码:
在C:
int exchange(int *xp, int y) {
int x = *xp;
*xp = y;
return x;
}
在x86带注释的程序集中:
// xp is at %ebp + 8, y at %ebp + 12
movl 8(%ebp), %edx // get xp
movl (%edx), %eax // get x at xp
movl 12(%ebp), %ecx // get y
movl %ecx, (%edx) // store y at xp
因此,根据我的理解,如果int * xp指向地址A处的int I,则汇编代码的第一行将A存储在%edx处。然后它在第二行被取消引用并存储在%eax。
如果这是真的,我想知道为什么第1行的“8(%ebp)”没有取消引用指针,将int存储在%edx而不是地址A中?这不是括号在汇编中做的吗?
或者这是否意味着当指针被推入堆栈时,指针的地址被推上而不是它所持有的值,因此8(%ebp)技术上保持& xp?
只是想澄清我的理解是否正确。
答案 0 :(得分:5)
xp
是一个指针。它有一个四字节值。该值由调用函数压入堆栈。您未显示的函数序言在ebp
中设置了基指针。 xp
的值存储在相对于该基指针的偏移量8处。
因此,第一行代码取消引用基本指针,如括号所示,偏移量为8,以检索xp
的值(这是一个指向的地址)一个int)并将其放入edx
。
第二行代码使用edx
中的地址来检索int
的值,并将该值放入eax
。请注意,函数返回值将是eax
中的值。
第三行取消引用基址指针,偏移量为12,以获得y
的值。
第四行使用edx
中的地址将y
放在xp
指向的位置。
答案 1 :(得分:2)
%bp
是堆栈基指针,在我可以访问堆栈上的任何内容之前必须将其引用。所以movl
8(%bp),%edx`获取当前堆栈帧中偏移量8的值。
这个值是一个指针,因此我们必须取消引用它才能访问其内容,无论是读取还是写入。
OTOH,y
是一个int,所以要获得它只是movl 12(%ebp), %ecx
并且不需要进一步的actoin。
所以movl %ecx, (%edx)
是正确的:将ecx
中存储的值放到edx
指向的内存中。