2017-05-24 45 views
1

标题实际上是我的第二个问题。 当我学习CSAPP第2版第3章时,出现了两个问题。有两个相对简单的文件。这里的第一个:为什么%esp被更改为imexpliccitly?

// code.c 
    int accum = 0; 

    int sum(int x, int y) 
    { 
     int  t = x + y; 
     accum += t; 
     return t; 
    } 

第二个:

// main.c 
    int main() { 
     return sum(1, 3); 
    } 

我用gcc编译它们,这本书以下。为了得到一个32位程序,我添加了一个选项-m32(我的是64位的Ubuntu):

$ gcc -m32 -O1 -O prog code.c main.c 

事情是好的可达这么远。但是当我使用GDB反汇编时,它真的让我困惑。我得到了以下结果相冲突以什么书说:

(gdb) disas sum 
    Dump of assembler code for function sum: 
     0x080483ed <+0>: mov 0x8(%esp),%eax 
     0x080483f1 <+4>: add 0x4(%esp),%eax 
     0x080483f5 <+8>: add %eax,0x804a020 
     0x080483fb <+14>: ret  
    End of assembler dump. 
    (gdb) disas main 
    Dump of assembler code for function main: 
     0x080483fc <+0>: push %ebp 
     0x080483fd <+1>: mov %esp,%ebp 
     0x080483ff <+3>: and $0xfffffff0,%esp 
     0x08048402 <+6>: sub $0x10,%esp 
     0x08048405 <+9>: movl $0x3,0x4(%esp) 
     0x0804840d <+17>: movl $0x1,(%esp) 
     0x08048414 <+24>: call 0x80483ed <sum> 
     0x08048419 <+29>: leave 
     0x0804841a <+30>: ret  
    End of assembler dump. 

现在,这里是我的问题:

  1. 为什么没有任何保存的%ebp或调用函数时ESP动态%按照书中介绍的总和?或者是总和由编译器内联?
  2. 值3 & 1已经分别存储在M [%esp + 4] & M [%esp]中。在调用之和之后,没有指令改变存储在%esp中的值。但在总和中,第一条指令检索M [%esp + 8],实际上是3(我使用GDB &检查了该值来设置断点),而M [%esp + 4]存储值1。怎么来的?后来我设置断点2:

    (gdb) break *0x08048414 
    (gdb) break sum 
    

随后发现存储在%ESP值在这两个断点是不同的我:

 Breakpoint 6, 0x08048414 in main() 
    (gdb) print $esp 
    $8 = (void *) 0xffffd020 
    (gdb) continue 
    Continuing. 

    Breakpoint 5, 0x080483ed in sum() 
    (gdb) print $esp 
    $9 = (void *) 0xffffd01c 

为什么会出现这种情况?

+1

'push','pop','call','ret'怎么样? – tkausl

+0

这个代码编译成功很奇怪,因为'sum()'没有在'main.c'中定义。这是你编译的实际代码吗? –

+0

@LiranFunaro我认为与C和坏的编译器设置它只会警告“未定义,我会假设它返回int,实际上需要这些参数” –

回答

1

为什么在本书描述中调用函数sum时没有任何保存%ebp或移动%esp?

您可能已经启用了省略帧指针的选项,最有可能使用-Ox编译器选项。可以强制GCC仍保持其与-fno-省略帧指针GCC命令行参数:

https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#index-O

但总和的内部,所述第一指令检索M [%ESP + 8],实际上是3,而M [%esp + 4]存储值1.怎么回事?

调用指令将eip寄存器推入堆栈并移动esp。你用32位模式编译它,所以偏移量是4个字节。

相关问题