wwwwww931121 发表于 2020-12-10 17:00

为什么C编译后在栈底预留8个字节?

本帖最后由 wwwwww931121 于 2020-12-21 22:18 编辑

第一个变量不是紧邻ebp,而是和ebp之间空了8个字节。

Windows 7 SP1 32位, 是下载官网的IE11 on win7 virtualbox虚拟机版本,编译器是MinGW 4.7.2。


在主机Win10 64位也有一样的情况,但教程上的windows xp则不会。


这个是Win7:


这个是XP:

涛之雨 发表于 2020-12-18 16:14

本帖最后由 涛之雨 于 2020-12-18 16:16 编辑

https://www.zhihu.com/question/24811279
应该是同样的原理吧


作者:liheng gong
链接:https://www.zhihu.com/question/24811279/answer/29078971
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

首先,代码中预留了2个page即8192 byte的空间,为了简单起见假设起地址范围为OFFSET + 0 ---> OFFSET +0x2000 -1,简单起见,省略掉OFFSET, 即0 - 0x1FFF ,那么
task_stack_page(p) + 8192 这个地址(即0x2000),其实已经超出了kernel栈的范围了(注意前面已经假定了kernel栈的范围是0 - 0x1FFF).   (task_stack_page宏返回的就是kernel stack的起始地址)

有了上面讨论的基础,再加上ARM栈是FD(Full Descending) 的flavor,也就是说在压栈的时候是先引用,再decrease 栈指针sp,那么显然栈底的地址不应该超出0 - 0x1FFF的地址范围,又因为
@田舍汉 提到的AAPCS里面规定public interface的stack对齐必须是8byte的,所以0x1FFF是不可以直接作为栈底指针值的,必须调整到8byte对齐的地址,那么很容易算出这个8byte对齐的地址为:
0x2000 - 8

To summarize: 栈底指针为 task_stack_page(p) + 0x2000 - 8即
task_stack_page(p) + 8192 - 8


另:
Stackoverflow上面的回答也同时印证了这个观点:
This way you can access to thread_info structure just by reading stack pointer and masking out THREAD_SIZE bits (otherwise SP initially would be on the next THREAD_SIZE block).static inline struct thread_info *current_thread_info(void)
{
register unsigned long sp asm ("sp");
return (struct thread_info *)(sp & ~(THREAD_SIZE - 1));
}
Eight bytes come from the ARM calling convention that SP needs to be 8-byte aligned.
页: [1]
查看完整版本: 为什么C编译后在栈底预留8个字节?