使用命令' x / 20x $ esp'在GDB中,堆栈如何工作?

时间:2015-01-28 02:15:21

标签: c linux ubuntu assembly gdb

我在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;
}    

这是主要

的反汇编
0x08048433 <+0>:    push   %ebp
0x08048434 <+1>:    mov    %esp,%ebp
0x08048436 <+3>:    and    $0xfffffff0,%esp
0x08048439 <+6>:    sub    $0x20,%esp
0x0804843c <+9>:    movl   $0x1,0x14(%esp)
0x08048444 <+17>:   movl   $0x2,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   $0x8048510,(%esp)
0x08048473 <+64>:   call   0x80482f0 <printf@plt>
0x08048478 <+69>:   mov    $0x0,%eax
0x0804847d <+74>:   leave  
0x0804847e <+75>:   ret    

然后我在第12行设置断点并分析堆栈 &#39; x / 20x $ esp&#39;

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

那么为什么声明&#39; movl $ 0x1,0x14(%esp)&#39;将1移动到堆栈中的第二个地址?具体来说,这个堆栈是如何递增(或递减,因为堆栈增长?)来放置&#39; 1&#39;在&#39; $ eip&#39;之后的地址中注册

教程也很好,因为我可能错过了这些信息。 谢谢!

- 汤姆

1 个答案:

答案 0 :(得分:2)

汇编指令movl $0x1,0x14(%esp)将32位整数值1移动到位于寄存器ESP指向的地址之后20个字节的4个字节中。在你的内存转储中,这是从0xbffff284开始的四个字节,这是第二行的第二个32位值。

此指令不会更改ESP的值。它既不增加也不减少。 ESP中的值先前由0x08048439sub $0x20,%esp处的指示更改。该指令在堆栈上为函数使用的局部变量保留32个字节,以及函数调用的传出参数。变量n1n2sum分别位于地址0xbffff2840xbffff2880xbffff28c

在程序中的任何位置,EIP后面的地址都没有存储。我认为你实际上意味着其他的东西,但我不知道是什么。