在GDB中使用命令'x/20x $esp',栈是如何工作的?
Using the command 'x/20x $esp' in GDB, how does the stack work?
我用 C 写了一个简单的程序,要在 GDB 中分析
#include <stdio.h>
int add_numbers(int n1,int n2)
{
int sum=n1+n2;
return sum;
}
int main()
{
int n1=1;
int n2=2;
int sum;
sum = add_numbers(n1,n2);
printf("The sum of 1 and 2 is %d",sum);
return 0;
}
下面是main的反汇编
0x08048433 <+0>: push %ebp
0x08048434 <+1>: mov %esp,%ebp
0x08048436 <+3>: and [=12=]xfffffff0,%esp
0x08048439 <+6>: sub [=12=]x20,%esp
0x0804843c <+9>: movl [=12=]x1,0x14(%esp)
0x08048444 <+17>: movl [=12=]x2,0x18(%esp)
0x0804844c <+25>: mov 0x18(%esp),%eax
0x08048450 <+29>: mov %eax,0x4(%esp)
0x08048454 <+33>: mov 0x14(%esp),%eax
0x08048458 <+37>: mov %eax,(%esp)
0x0804845b <+40>: call 0x804841d <add_numbers>
0x08048460 <+45>: mov %eax,0x1c(%esp)
0x08048464 <+49>: mov 0x1c(%esp),%eax
0x08048468 <+53>: mov %eax,0x4(%esp)
0x0804846c <+57>: movl [=12=]x8048510,(%esp)
0x08048473 <+64>: call 0x80482f0 <printf@plt>
0x08048478 <+69>: mov [=12=]x0,%eax
0x0804847d <+74>: leave
0x0804847e <+75>: ret
然后我在第 12 行设置断点并分析堆栈
'x/20x $esp'
0xbffff270: 0x00000001 0xbffff334 0xbffff33c 0xb7e4342d
0xbffff280: 0xb7fbb3c4 0x00000001 0x0804848b 0xb7fbb000
0xbffff290: 0x08048480 0x00000000 0x00000000 0xb7e29a83
0xbffff2a0: 0x00000001 0xbffff334 0xbffff33c 0xb7feccea
0xbffff2b0: 0x00000001 0xbffff334 0xbffff2d4 0x0804a014
那么为什么语句'movl [=27=]x1,0x14(%esp)'将1移动到栈中的第二个地址呢?具体来说,这个堆栈如何递增(或递减,因为堆栈向下增长?)以将“1”放入“$eip”寄存器后面的地址中?
教程也很好,因为我可能错过了这些信息。
谢谢!
-汤姆
汇编指令movl [=10=]x1,0x14(%esp)
将32位整数值1
移动到寄存器ESP指向的地址后20字节的4个字节中。在您的内存转储中,这将是从 0xbffff284
开始的四个字节,这是第二行的第二个 32 位值。
该指令不改变ESP的值。它既不增加也不减少。 ESP 中的值先前由 0x08048439
处的指令更改:sub [=14=]x20,%esp
。该指令在堆栈上为函数使用的局部变量以及函数调用的传出参数保留 32 字节。变量n1
、n2
、sum
分别位于地址0xbffff284
、0xbffff288
、0xbffff28c
。
在您程序的任何位置,EIP 后面的地址都不会存储任何内容。我想你实际上是指别的意思,但我不知道是什么意思。
我用 C 写了一个简单的程序,要在 GDB 中分析
#include <stdio.h>
int add_numbers(int n1,int n2)
{
int sum=n1+n2;
return sum;
}
int main()
{
int n1=1;
int n2=2;
int sum;
sum = add_numbers(n1,n2);
printf("The sum of 1 and 2 is %d",sum);
return 0;
}
下面是main的反汇编
0x08048433 <+0>: push %ebp
0x08048434 <+1>: mov %esp,%ebp
0x08048436 <+3>: and [=12=]xfffffff0,%esp
0x08048439 <+6>: sub [=12=]x20,%esp
0x0804843c <+9>: movl [=12=]x1,0x14(%esp)
0x08048444 <+17>: movl [=12=]x2,0x18(%esp)
0x0804844c <+25>: mov 0x18(%esp),%eax
0x08048450 <+29>: mov %eax,0x4(%esp)
0x08048454 <+33>: mov 0x14(%esp),%eax
0x08048458 <+37>: mov %eax,(%esp)
0x0804845b <+40>: call 0x804841d <add_numbers>
0x08048460 <+45>: mov %eax,0x1c(%esp)
0x08048464 <+49>: mov 0x1c(%esp),%eax
0x08048468 <+53>: mov %eax,0x4(%esp)
0x0804846c <+57>: movl [=12=]x8048510,(%esp)
0x08048473 <+64>: call 0x80482f0 <printf@plt>
0x08048478 <+69>: mov [=12=]x0,%eax
0x0804847d <+74>: leave
0x0804847e <+75>: ret
然后我在第 12 行设置断点并分析堆栈 'x/20x $esp'
0xbffff270: 0x00000001 0xbffff334 0xbffff33c 0xb7e4342d
0xbffff280: 0xb7fbb3c4 0x00000001 0x0804848b 0xb7fbb000
0xbffff290: 0x08048480 0x00000000 0x00000000 0xb7e29a83
0xbffff2a0: 0x00000001 0xbffff334 0xbffff33c 0xb7feccea
0xbffff2b0: 0x00000001 0xbffff334 0xbffff2d4 0x0804a014
那么为什么语句'movl [=27=]x1,0x14(%esp)'将1移动到栈中的第二个地址呢?具体来说,这个堆栈如何递增(或递减,因为堆栈向下增长?)以将“1”放入“$eip”寄存器后面的地址中?
教程也很好,因为我可能错过了这些信息。 谢谢!
-汤姆
汇编指令movl [=10=]x1,0x14(%esp)
将32位整数值1
移动到寄存器ESP指向的地址后20字节的4个字节中。在您的内存转储中,这将是从 0xbffff284
开始的四个字节,这是第二行的第二个 32 位值。
该指令不改变ESP的值。它既不增加也不减少。 ESP 中的值先前由 0x08048439
处的指令更改:sub [=14=]x20,%esp
。该指令在堆栈上为函数使用的局部变量以及函数调用的传出参数保留 32 字节。变量n1
、n2
、sum
分别位于地址0xbffff284
、0xbffff288
、0xbffff28c
。
在您程序的任何位置,EIP 后面的地址都不会存储任何内容。我想你实际上是指别的意思,但我不知道是什么意思。