gpt4 book ai didi

assembly - 为什么 ESP 被 0xFFFFFFF0 屏蔽?

转载 作者:行者123 更新时间:2023-12-04 11:30:20 25 4
gpt4 key购买 nike

我反汇编了一个程序。我在开头看到一个 AND使用 ESP 的说明和 0xFFFFFFF0 .

这个面具的意义是什么?是对齐问题吗?

它是 32 位 x86 的 ELF 可执行文件。

最佳答案

i386 Linux 的 gcc 默认为 -mpreferred-stack-boundary=4 (meaning 24 = 16 byte alignment) . (其他非 Linux 系统也使用 ELF 可执行文件,但它们也具有相同的堆栈对齐默认值和 SysV ABI。)

与叮当不同, gcc 不假设堆栈将在进入 main 时对齐。 ,所以它使用 AND指令屏蔽堆栈指针的低位。这是在堆栈上保留足够填充以到达下一个对齐边界的最便宜的方法。

堆栈对齐与您会看到调用另一个函数的函数在堆栈上保留一些不用于任何内容的空间的原因相同:

extern int bar(void);
int foo(int x) { return x+bar(); }

gcc 5.3 -O3
sub esp, 12 # align the stack for another call
call bar
add eax, DWORD PTR [esp+16] # add our arg (from the stack) to bar()'s return value (in eax)
add esp, 12
ret

See this on the Godbolt compiler explorer ,您可以在其中尝试不同的编译器和选项。
-mincoming-stack-boundary=3 (或更少)导致堆栈对齐样板被添加到每个函数(不仅仅是主函数)。 -mstackrealign-mno-stackrealignfoo() 没有影响或 main() ,带或不带小 -mincoming-stack-boundary .基于 the documentation in the gcc manual ,我认为它会启用或禁用 main 以外的函数或 main 的对齐内容。

32bit x86 SysV ABI过去只保证 4 字节堆栈对齐,但调用约定现在保证 %esp 的 16 字节对齐。之前 call操作说明。

Section 2.2.2 The Stack Frame

... In other words, the value (%esp + 4) is always a multiple of 16 when control is transferred to the function entry point. (32 when a 32-byte ymm vector is passed by value)



所以gcc的 -mpreferred-stack-boundary=4不仅仅是一个好主意,它还是法律(在像 Linux 这样的系统上,包含这种更强大保证的更新 ABI 版本是官方标准)。这使得除 main 以外的其他函数都是安全的。在使用对齐的 SSE 存储/加载到堆栈之前省略该对齐步骤。这些指令(如 movaps )将在未对齐的地址上出错。因此,对齐是正确性所必需的,而不仅仅是性能。
AND这些天实际上不需要指导

32 位 ABI 的当前版本确实保证了一个新的- execve ed 32 位进程将以 %esp 开头16 字节对齐。 (第 2.3.1 节初始堆栈和寄存器状态,请参阅有关 %esp 本身的初始状态的要点,而不是堆栈内容。)

这意味着 gcc 在 main 开始时对齐堆栈的行为现在已经过时了,假设调用 main 的 CRT 启动代码。不会错位堆栈。

clang 确实假设堆栈在 main 的开头对齐,就像 64 位 gcc 一样。

16B 对齐从一开始就是 x86-64 SysV ABI 的一部分,后来没有添加,因此它始终是一个安全的假设,并且没有旧内核在进程启动时不提供。

tag wiki 有指向其他 ABI 的链接,等等。

关于assembly - 为什么 ESP 被 0xFFFFFFF0 屏蔽?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37967710/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com