我写了一个小程序来理解堆栈的结构。
#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
和buffer2
之间的区别如何10
。
此外,%ebp与9
之间的buffer1
有何不同?
这到底发生了什么?
注意:
我正在使用英特尔处理器,Ubuntu 12.04,32bit并使用
gcc -o stack -g -fno-stack-protector -O0 main.c
构建。
答案 0 :(得分:0)
这是我的疑问,当所有内容以多个单词大小分配时,buffer1和buffer2之间的区别如何是0x10。
首先,更正:buffer1
和buffer2
之间的差异为10
,而不是0x10
(16
)。
其次,并非所有都是以多个单词分配的。 总帧大小可以被至少8整除,以保持堆栈与doubles
正确对齐,但各个局部变量只能根据其对齐要求进行对齐是(字符和字符缓冲区为1
)。