可以使用其他指令执行“ PUSH”指令的操作吗?

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

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

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

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

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

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

但是是的,您可以使用其他指令,例如sub rsp, 8mov存储来模拟它。 (这对于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”无法通过更原始的指令来完成?

除了效率和代码大小外没有什么重要的。

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

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之类的指令处理堆栈指针的隐式使用,因此PUSH在Pentium-M和更高版本的CPU上解码为单个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.