在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 字节。变量n1n2sum分别位于地址0xbffff2840xbffff2880xbffff28c

在您程序的任何位置,EIP 后面的地址都不会存储任何内容。我想你实际上是指别的意思,但我不知道是什么意思。