标题实际上是我的第二个问题。 当我学习CSAPP第2版第3章时出现了2个问题。有2个相对简单的文件。这是第一个:
// 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.
现在我的问题出现了:
价值3&amp; 1已经存储在M [%esp + 4]&amp; M [%esp],分别。在调用 sum 之后,没有指令改变存储在%esp中的值。但是在 sum 中,第一条指令检索M [%esp + 8],实际上是3(我使用GDB设置断点并检查该值),而M [%esp + 4]存储价值1.怎么样?后来我设置了两个断点:
(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
为什么会发生这种情况?
答案 0 :(得分:1)
为什么在本书描述的时候调用函数sum时没有任何保存%ebp或移动%esp?
您可能已启用省略帧指针的选项,很可能使用-Ox编译器选项。您可以强制GCC使用-fno-omit-frame-pointer GCC命令行参数保留它:
https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#index-O
但总和之内,第一条指令检索M [%esp + 8],实际上是3,而M [%esp + 4]存储值1.为什么?
调用指令将eip寄存器推送到堆栈并移动esp。您在32位模式下编译它,因此偏移量为4个字节。