2

我写了一个小程序来了解堆栈的结构。

#include <stdio.h>

void function(int a, int b, int c) {
    char buffer1[5];
    char buffer2[10];

    int *ret = buffer1 + 13;
    (*ret) += 8;
}

int main() {
    int x = 0;
    function(1,2,3);
    x = 1;
    printf("x = %d\n",x);
    return 0;
}

到目前为止,我已经了解到堆栈遵循以下模式

    ------------------
    |    arguments   |  High
    ------------------
    | return address |
    ------------------
    |       ebp      |
    ------------------
    |     buffer1    |
    ------------------
    |     buffer2    |  Low
    ------------------

我还了解到,如果我们分配 5 个字节的数据,程序会分配 8 个字节(因为它必须是字长的倍数)。

函数的汇编代码转储function

0x08048414 <+0>:    push   %ebp
0x08048415 <+1>:    mov    %esp,%ebp
0x08048417 <+3>:    sub    $0x20,%esp
0x0804841a <+6>:    lea    -0x9(%ebp),%eax
0x0804841d <+9>:    add    $0xd,%eax
0x08048420 <+12>:   mov    %eax,-0x4(%ebp)
0x08048423 <+15>:   mov    -0x4(%ebp),%eax
0x08048426 <+18>:   mov    (%eax),%eax
0x08048428 <+20>:   lea    0x8(%eax),%edx
0x0804842b <+23>:   mov    -0x4(%ebp),%eax
0x0804842e <+26>:   mov    %edx,(%eax)
0x08048430 <+28>:   leave  
0x08048431 <+29>:   ret    

汇编程序转储结束。

现在我在 gdb 下运行程序,我得到了,

(gdb) x/x $ebp
    0xbffff318: 0xbffff348
(gdb) x/x buffer1
    0xbffff30f: 0xfc73e461
(gdb) x/x buffer2
    0xbffff305: 0x0108049f

这是我的疑问,当一切都以字长的倍数分配时,buffer1和之间的区别怎么可能buffer210

还有9%ebp 和buffer1

这里到底发生了什么?

注意

  • 考虑堆栈从高到低增长
  • 字长 = 4
  • 我正在使用英特尔处理器、Ubuntu 12.04、32 位并使用

    gcc -o stack -g -fno-stack-protector -O0 main.c

建造。

4

1 回答 1

0

这是我的疑问,当所有内容都以字大小的倍数分配时,buffer1 和 buffer2 之间的差异怎么可能是 0x10。

buffer1首先,更正一下:和之间的区别buffer210,而不是0x10(即16)。

其次,并非所有内容都以多个单词分配。总帧大小至少可以被 8 整除以保持堆栈正确对齐doubles,但各个局部变量将仅按其对齐要求(即1字符和字符缓冲区)对齐。

于 2013-08-31T05:20:53.550 回答