1

我试图理解以下函数的反汇编代码。

void func(char *string) {
    printf("the string is %s\n",string);
}

反汇编代码如下。

1) 0x080483e4 <+0>:     push   %ebp  
2) 0x080483e5 <+1>:     mov    %esp,%ebp  
3) 0x080483e7 <+3>:     sub    $0x18,%esp  
4) 0x080483ea <+6>:     mov    $0x80484f0,%eax  
5) 0x080483ef <+11>:    mov    0x8(%ebp),%edx  
6) 0x080483f2 <+14>:    mov    %edx,0x4(%esp)  
7) 0x080483f6 <+18>:    mov    %eax,(%esp)  
8) 0x080483f9 <+21>:    call   0x8048300 <printf@plt>

谁能告诉我第 4-7 行是什么意思(不是字面解释)。另外为什么在第 3 行的堆栈上分配了 24 个字节?

4

2 回答 2

6

基本上这里发生了什么:

4) 0x080483ea <+6> : mov $0x80484f0,%eax

将地址加载"the string is %s\n"eax.

5) 0x080483ef <+11>: mov 0x8(%ebp),%edx

将论点string移入edx.

6) 0x080483f2 <+14>: mov %edx,0x4(%esp)

edx将or的值压string入堆栈,的第二个参数printf

7) 0x080483f6 <+18>: mov %eax,(%esp)

eax将or的值压"the string is %s\n"入堆栈,第一个参数是printf,然后它会调用printf

sub $0x18,%esp没有必要,因为该函数没有局部变量,gcc 似乎喜欢腾出额外的空间,但老实说我不知道​​为什么。

于 2013-08-25T11:23:58.767 回答
1

堆栈是一个连续的内存区域,从较高的地址开始,到esp. 每当你需要你的堆栈增长时,你从esp. 每个函数都可以在堆栈上有一个框架。它是函数拥有的堆栈的一部分,并在完成后负责清理。这意味着,当函数启动时,它会减少esp以创建它的框架。当它结束时,它会增加它。ebp通常指向帧的开头。

最初,该函数压ebp入堆栈,以便在函数结束时存储它,设置esp = ebp为标记其帧的开始并分配 28 个字节。为什么是28?用于对齐。它已经为ebp. 4 + 28 = 32。

第 4-7 行将准备对 的调用printf。它期望它的参数在调用者的框架上。当我们阅读时,我们从调用者的框架mov 0x8(%ebp), %edx中获取我们的论点。也会这样做。char* stringprintf

请注意,您的程序集缺少清除堆栈并返回给调用者leave的说明。ret

于 2013-08-25T11:43:55.843 回答