(gdb) disassemble add Dump of assembler code for function _Z3addii: 0x0000000000400596 <+0>: push %rbp 0x0000000000400597 <+1>: mov %rsp,%rbp 0x000000000040059a <+4>: mov %edi,-0x4(%rbp) 0x000000000040059d <+7>: mov %esi,-0x8(%rbp) 0x00000000004005a0 <+10>: mov -0x4(%rbp),%edx 0x00000000004005a3 <+13>: mov -0x8(%rbp),%eax 0x00000000004005a6 <+16>: add %edx,%eax 0x00000000004005a8 <+18>: pop %rbp 0x00000000004005a9 <+19>: retq End of assembler dump. (gdb)
这里可以看到Add函数和Main函数反汇编出来的代码
现在来看下rbp 和rsp 内容的变化
1 2 3 4 5 6 7 8 9 10 11
(gdb) b main Breakpoint 1 at 0x4005ae (gdb) b add Breakpoint 2 at 0x40059a (gdb) r Starting program: /root/projects/cpp/add.o Missing separate debuginfos, use: yum debuginfo-install glibc-2.28-101.el8.x86_64
Breakpoint 1, 0x00000000004005ae in main () (gdb)
BP 为基址寄存器,一般在函数中用来保存进入函数时SP的栈顶基址 SP 时栈顶指针,每次指向栈顶
在函数进入时: push bp //保存bp指针 mov sp,bp //将sp指针传给bp,此时bp指向sp的基地址。这个时候,如果该函数有参数,则[bp-4]则是该子函数的第一个参数,[bp-8]则是该子函数的第二个参数,以此类推,有多少个参数则[bp-4^n]。 ….. ….. 函数结束时: pop bp //恢复原bp的值。 ret //退出子函数
Reading symbols from add.o...done. (gdb) b main Breakpoint 1 at 0x4005b2: file add.cpp, line 9. (gdb) l 1 #include"stdio.h" 2 int add(int x,int y) 3 { 4 return x+y; 5 } 6 7 int main() 8 { 9 int p = 4; 10 int i; (gdb) 11 for(i = 1;i<3;i++) 12 { 13 p = add(i,p); 14 } 15 printf("%d\n",p); 16 return 0; 17 } (gdb) p p No symbol "p" in current context. (gdb) r Starting program: /root/projects/cpp/add.o Missing separate debuginfos, use: yum debuginfo-install glibc-2.28-101.el8.x86_64
Breakpoint 1, main () at add.cpp:9 9 int p = 4; (gdb) p p $1 = 0 (gdb) si 11 for(i = 1;i<3;i++) (gdb) disass main Dump of assembler code for function main(): 0x00000000004005aa <+0>: push %rbp 0x00000000004005ab <+1>: mov %rsp,%rbp 0x00000000004005ae <+4>: sub $0x10,%rsp 0x00000000004005b2 <+8>: movl $0x4,-0x4(%rbp) => 0x00000000004005b9 <+15>: movl $0x1,-0x8(%rbp) 0x00000000004005c0 <+22>: cmpl $0x2,-0x8(%rbp) 0x00000000004005c4 <+26>: jg 0x4005de <main()+52> 0x00000000004005c6 <+28>: mov -0x4(%rbp),%edx 0x00000000004005c9 <+31>: mov -0x8(%rbp),%eax 0x00000000004005cc <+34>: mov %edx,%esi 0x00000000004005ce <+36>: mov %eax,%edi 0x00000000004005d0 <+38>: callq 0x400596 <add(int, int)> 0x00000000004005d5 <+43>: mov %eax,-0x4(%rbp) 0x00000000004005d8 <+46>: addl $0x1,-0x8(%rbp) 0x00000000004005dc <+50>: jmp 0x4005c0 <main()+22> 0x00000000004005de <+52>: mov -0x4(%rbp),%eax 0x00000000004005e1 <+55>: mov %eax,%esi 0x00000000004005e3 <+57>: mov $0x400698,%edi 0x00000000004005e8 <+62>: mov $0x0,%eax 0x00000000004005ed <+67>: callq 0x4004a0 <printf@plt> 0x00000000004005f2 <+72>: mov $0x0,%eax 0x00000000004005f7 <+77>: leaveq 0x00000000004005f8 <+78>: retq End of assembler dump. (gdb) p $p $2 = void (gdb) p p $3 = 4 (gdb) p &p $4 = (int *) 0x7fffffffe41c (gdb) p $rbp $5 = (void *) 0x7fffffffe420 (gdb) p &i $6 = (int *) 0x7fffffffe418 (gdb)