我可以先执行“ PUSH”指令使用其他指令执行的相同任务吗?

问题描述 投票:1回答:1

[在我看来,目前我们拥有“推”之类的指令的唯一原因是用单个指令替换多个MOV和算术指令。

是否有任何“ PUSH”无法通过更原始的指令来完成?

“ PUSH”是否只是一个可编译为多个机器代码指令的助记符?

assembly x86 nasm instruction-set opcode
1个回答
2
投票

推是真实的机器指令(https://www.felixcloutier.com/x86/push不是只是汇编宏/伪指令。例如,push rax的单字节编码为0x50

但是,您可以使用其他指令,例如sub rsp, 8 /和mov存储来模拟它。 (这对于x86这样的CISC机器来说是正常的!)参见What is the function of the push / pop instructions used on registers in x86 assembly?

要精确地模拟它(不带修改标志),请使用LEA而不是ADD / SUB。

  lea   rsp, [rsp-8]
  mov   qword [rsp], 123      ; push 123 in 64-bit mode

他们的任何东西都不能通过更原始的指令来完成吗?

没有什么超出效率的。

单个指令是原子性的。中断-它们要么发生,要么不发生。这通常是完全不相关的;中断通常不查看被中断的代码的堆栈/寄存器内容。

PUSH可以在机器代码的单个字节中完成操作以压入单个寄存器,在2个字节中立即完成操作。多指令序列要大得多。 8086的ISA的架构师非常注重使小代码成为可能,所以是的[[用一条短的指令代替几条较长的指令是完全正常的。]我们有not而不是必须使用xor reg, -1,还有inc而不是add reg, 1。 (尽管它们都具有不同的FLAGS语义,不使标志保持不变而INC / DEC不使CF保持不变。)更不用说所有x86的其他特殊情况的编码,例如xchg-with- [e / r的1字节编码。 ]斧头。参见https://codegolf.stackexchange.com/questions/132981/tips-for-golfing-in-x86-x64-machine-code也有效率:由于堆栈引擎通过诸如push / pop和call / ret之类的指令处理堆栈指针的隐式使用,因此在Pentium-M和更高版本的CPU上,PUSH解码为单个uop(在融合域中)。 2条单独的指令当然会解码为至少2 oups。 (除了特殊情况下的test / cmp + JCC的宏融合)。

[在古老的P5 Pentium上,用单独的ALU和mov指令模拟推入实际上是一个胜利-在PPro CPU不知道如何将复杂的CISC指令分解为单独的uops之前,复杂的指令无法在P5的双指令中配对-有序管道。 (请参见Agner Fog's microarch guide。)这里的主要好处是能够混入可能配对的其他指令,并且只执行一个大的sub,然后只执行mov存储,而不是对堆栈指针进行多次更改。 >

这也适用于堆栈引擎之前的早期P6系列。例如,带有-march=pentium3的GCC倾向于避免使用push,而只是对ESP做较大的调整。

© www.soinside.com 2019 - 2024. All rights reserved.