gpt4 book ai didi

assembly - 我可以从堆栈的中间弹出吗?

转载 作者:行者123 更新时间:2023-12-04 14:23:55 26 4
gpt4 key购买 nike

在 x86 汇编语言中:

我假设我有一个正常的功能序言,阅读

push ebp
mov ebp,esp

我知道我可以通过访问内存目标操作数来读取或写入寄存器,假设我想要第一个参数。我会做
mov eax,[ebp +8]

得到 f.e.来自堆栈的整数参数。

那么为什么我不直接使用堆栈指针呢?
add  esp,8              ; point ESP at the data we want
pop eax
sub esp,12 ; restore ESP to its original position

这会导致错误吗?这在任何情况下都使用吗?

我当然知道第一个操作的大小较小,因为它只有一个操作码,即 mov而不是三个,但这不是问题的重点。

(编者注: mov eax, [ebp+8] 是 x86 机器码中的 3 字节指令。 add/ sub esp,imm8 每个是 3 个字节, pop eax 是 1 个字节。 mov eax, [esp+8]是 4 字节指令:与 16 位寻址模式不同,ESP 可以是基址寄存器。但它确实需要一个 SIB 字节来对其进行编码。
这些都是 single-uop instructions on modern CPU ,不包括额外的堆栈同步 uops。)

为什么这样做是不好的做法?

最佳答案

您可以与 ESP 合作直接作为指针。
但是,如果发生任何插入或弹出,则 ESP 将变成移动目标,使您的计算更加困难。

出于这个原因,我们将堆栈指针的副本放在 EBP 中,因此我们不必担心 ESP 更改。

但是,如果您不打算更改堆栈指针,那么使用 ESP 完全没问题。而不是 EBP .
如果你真的改变了 ESP您当然可以相应地更改 ESP 的偏移量。

enter image description here
警告
你永远不应该这样做:

add  esp,8
mov ecx,[esp-4] //never access data outside the actual stack.
pop eax
sub esp,12

请记住,中断可能随时发生。
中断将假定堆栈指针以下的任何内容都可以更改。如果您手动增加堆栈指针,然后访问它下面的数据,就好像它仍在堆栈中一样,您可能会发现那里的数据已被中断处理程序 (Oops) 替换。

规则:ESP 以北的任何东西都是安全的,ESP 以南的任何东西都被标记为死亡
这就是例程创建 stack frame 的原因.通过降低堆栈指针(记住堆栈向下增长),内存区域受到保护,因为它现在位于堆栈内。
堆栈的语义意味着任何高于 ESP 的数据都是安全的,而低于 ESP 的任何数据都是公平游戏。

如果你违反了这两个原则中的任何一个
A - 使用非固定 ESP 作为基指针,或
B - 在 ESP 下访问数据。
您将面临 A:损坏其他人的数据或 B:自己处理损坏的数据的风​​险。

Is this bad practise?

add esp,8 //equivalent to pop anyreg, pop anyreg
pop eax //pop from the (new) top of the stack.
sub esp,12 //reset the stack back to where is was.



是的!这不好

如果中断发生在 sub esp,12 之前存储在这一位堆栈空间中的 3 个整数将被更改,从而导致您的应用程序中的数据损坏。

请改用以下代码。
mov eax,[esp+8]

这段代码是 A:安全,B:更快,C:不破坏标志寄存器,D:更短,E:编码更少的字节。

关于添加/订阅的说明
如果你在 FLAGS 中有一些有用的东西,你可以使用 LEA 来避免破坏它。代替。如果没有, add/ sub至少一样快(例如,在某些主流 CPU 上的更多执行端口上运行,而 LEA 只能在 Ryzen 和 Haswell 及更高版本上的 4 个整数 ALU 执行单元中的 2 个上运行)。两种方式都没有代码大小优势。
lea esp,[esp+8] == add esp,8 (but without altering the flags).  

lea edx, [esp+8] ; copy-and-add replacing mov + add is very useful

当 LEA 可以替换 2 个或更多其他指令时,一定要使用 LEA,但不仅仅是替换添加/订阅,除非您有用于保留 FLAGS 的用途。

关于assembly - 我可以从堆栈的中间弹出吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42991537/

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