栈字节对齐问题

expl0it 2007-03-11 02:17:59
如果,各定义一个50字节和100字节的字符数组,在这种情况下,实际分配多少栈空间呢?答案是0x8+0x40+0x70,即184字节。
下面动手验证一下:

# vi test4.c
int main()
{
char str1[50];
char str2[100];
return 0;
}
# mdb test4
Loading modules: [ libc.so.1 ]
> main::dis
main: pushl %ebp
main+1: movl %esp,%ebp
main+3: subl $0xb8,%esp ; 为两个字符数组分配栈空间,同时保证16字节对齐
main+9: andl $0xf0,%esp
main+0xc: movl $0,%eax
main+0x11: subl %eax,%esp
main+0x13: movl $0,%eax
main+0x18: leave
main+0x19: ret
> 0xb8=D ; 16进制换算10进制
184
> 0x40+0x70+0x8=X ; 表达式计算,结果指定为16进制
b8
>
gcc默认的编译是要16字节栈对齐的,问上面实际分配的栈空间怎么算出来的?
...全文
1036 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
BufferedImage 2012-04-08
  • 打赏
  • 举报
回复
int main()
{
char str1[50];
char str2[100];
return 0;
}

//////为什么在windows下为 152字节。。
1: void main(){
00401010 push ebp
00401011 mov ebp,esp
00401013 sub esp,0D8h
00401019 push ebx
0040101A push esi
0040101B push edi
0040101C lea edi,[ebp-0D8h]
00401022 mov ecx,36h
00401027 mov eax,0CCCCCCCCh
0040102C rep stos dword ptr [edi]
2: char str1[100];
3: char str2[50];
4:
5:
6:
7: }
0040102E pop edi
0040102F pop esi
00401030 pop ebx
00401031 mov esp,ebp
00401033 pop ebp
00401034 ret
insulted 2008-11-04
  • 打赏
  • 举报
回复
谢谢R9R9R9能在19个月后做如此详尽的解释!
非常感谢!
R9R9R9 2008-11-04
  • 打赏
  • 举报
回复
时间过的真快,一晃1年零7个月就这样过了。
R9R9R9 2008-11-04
  • 打赏
  • 举报
回复
这里假设在进入main函数之前,栈是16字节对齐的话. 假设地址是100000(0x20)
| | <- 100000
| |
| |
| |
| |
| |
| |

在调用main函数的时候,要把main函数的返回地址压入stack中,还要把EBP压入进入,而这两个都是指针,在32位机上都是4个字节(1000),即push这两个值之后,ESP的值就是11000(0x20 - 0x08 = 0x18),这时候栈地址(ESP)最末4位二进制位是不是就是1000了?所以就再sub 8个字节,保证之后使用的ESP还是16字节对齐的。
__________100000 (ESP)
| EIP |
| EBP |__________011000
| |
| |__________010000
| |
| |
| |
insulted 2008-11-04
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 insulted 的回复:]
网上搜到这个老帖,发现lz尚未结贴,我将其顶起来!

1楼解释的第一部分:0x8,没有理解,希望那个高人能够将其解释一下,谢谢!
[/Quote]
call main函数的时候,需要把eip和ebp压入堆栈,此时栈地址(esp)最末4位二进制位必定是1000,esp-8则恰好使后4位地址二进制位为0000。所以这里为分配了0x8个字节,是为保证栈16字节对齐的。

为什么说:“此时栈地址(esp)最末4位二进制位必定是1000,”
然后又说:“esp-8则恰好使后4位地址二进制位为0000。”,更不知道在说什么了。

希望n人来说说看!期待。。。。
insulted 2008-11-04
  • 打赏
  • 举报
回复
网上搜到这个老帖,发现lz尚未结贴,我将其顶起来!

1楼解释的第一部分:0x8,没有理解,希望那个高人能够将其解释一下,谢谢!
R9R9R9 2007-04-04
  • 打赏
  • 举报
回复
0x40+0x70+0x8=0xb8

这里分为三个部分:
1: 0x8
这里假设在进入main函数之前,栈是16字节对齐的话.
call main函数的时候,需要把eip和ebp压入堆栈,此时栈地址(esp)最末4位二进制位必定是1000,esp-8则恰好使后4位地址二进制位为0000。所以这里为分配了0x8个字节,是为保证栈16字节对齐的。

2: 0x40
由于你定义了一个char str1[50];如果直接分配50个字节,那么将破坏栈16字节对齐规则,所以我们得分配一个同时满足空间需要而且保持16字节栈对齐的,最接近的就是0x40(0x30<50<0x40)。

3: 0x70
如2所说的,最接近的就是0x70(0x60<100<0x70)。



当然这里只是针对:gcc默认的编译是要16字节栈对齐的而言的

65,179

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧