gpt4 book ai didi

assembly - x86 程序集 : Pop a value without storing it

转载 作者:行者123 更新时间:2023-12-04 13:56:48 24 4
gpt4 key购买 nike

在 x86 程序集中,是否可以从堆栈中删除一个值而不存储它?类似 pop word null 的东西?我显然可以使用 add esp,4 ,但也许我错过了一个漂亮而干净的 cisc 助记符?

最佳答案

add esp,4/add rsp,8是正常/惯用/干净的方式。不需要特殊的方式,因为堆栈并不神奇或特殊(至少在这方面不是);它只是寄存器中的一个指针,其中包含一些隐式使用它的指令。 (对于内核堆栈,中断异步使用它,因此软件无法实现内核红区,即使它想要......)

除此之外,在函数末尾清理整个堆栈帧的神奇 CISC 方法是 leave = mov esp, ebp/pop ebp (或 16 位或 64 位等价物)。不像 enter ,它在现代 CPU 上足够快,可以在实践中使用,但在 Intel CPU 上仍然是 3 uop 指令。 ( http://agner.org/optimize/ )。但是leave如果您使用 ebp 使用额外的指令制作堆栈帧,则仅在第一时间有效。/rbp首先。 (通常您不会这样做,除非您需要保留可变数量的堆栈空间,例如在循环中使用 push 来创建数组,或等效于 C99 VLA 或 alloca 。或者对于初学者代码使访问本地更容易,或者在 16 位模式下 SP 不能用于寻址模式。)

清理 stack-args 的神奇 CISC 方法是供被调用者使用 ret imm16 (花费 1 个额外的 uop)来弹出 args,创建一个调用约定,其中被调用者清理堆栈。在 caller-pops 调用约定中,无法使用这种形式的 ret ,但您可以简单地保留堆栈偏移量并使用 mov为下一个函数调用存储参数而不是 push (如果函数根本需要任何堆栈参数;寄存器参数调用约定通常更有效。)

所以神奇的 CISC 方式在现代 CPU 上没有性能优势,只有很小的代码大小。

您可能会使用以下两个原因 pop reg而不是 add esp,4 :

  • 代码大小:pop r32/r64是一个 1 字节的指令,而 add esp,4 是 3 个字节或 add rsp,8 的 4 个字节.
  • 性能:当您使用 esp 时,英特尔的堆栈引擎必须插入额外的堆栈同步 uops/rsp在堆栈指令(push/pop/call/ret)之后显式。所以在 call 之后(返回 ret ),它节省了一个 uop 来使用 pop而不是 add esp,4在你之前ret在函数的最后。

    AMD 的堆栈引擎不需要额外的堆栈同步 uop,但仍会生成 push/pop 单 uop 指令。与较旧的 Intel/AMD CPU 不同,push/pop 成本高于普通 CPU mov加载/存储,需要一个单独的 uop 来修改堆栈指针。并在堆栈指针上创建数据依赖项。

  • Why does this function push RAX to the stack as the first operation?有关性能的更多详细信息。

    如果您正在寻找美感,那么您可以很好地缩进,格式化和注释您的代码,但超出 如果美学胜过优化,您在选择 x86 asm 时选择了错误的语言 .

    当然,如果你需要将堆栈调整超过 1 个寄存器宽度,肯定使用 add如果您不需要 pop 的数据会加载。或者,如果您需要将其调整为 +128 字节,请使用 sub esp, -128 , 因为 -128可编码为符号扩展 imm8,但 +128 不是。

    或者也许使用 lea esp, [esp+4] ,就像 gcc 对 -mtune=atom 所做的那样. (对于有序原子,而不是silvermont)。就像我说的,如果你想要干净,你不应该选择 x86 asm。

    您几乎总能找到到 pop 的死寄存器。进入 .如果你需要在弹出一些你真正想要弹出的寄存器之前将 E/RSP 调整一个堆栈槽,你总是可以弹出相同的寄存器两次。

    在极少数情况下,7 (x86-32) 或 15 (x86-64) 非堆栈寄存器均不可用 pop目的地,此优化不可用,您应该简单地使用传统的 add . 不值得花费额外的说明来实现 pop ;这将超过使用 pop 的次要好处.

    请注意 pop Sreg (段寄存器)仍然消耗常规的“堆栈宽度”(32 位或 64 位,取决于模式),而不是 16 位寄存器仅消耗 16 位。 But only pop ds/es/ss are single-byte. pop fs/gs are 2 bytes each .因此,如果您正在优化代码大小, pop gsadd esp,4 小 1 个字节,但要慢得多。 (或比 add rsp,8 小 2 个字节)。

    关于assembly - x86 程序集 : Pop a value without storing it,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48705427/

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