我可以先执行“ PUSH”指令使用其他指令执行的相同任务吗?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我可以先执行“ PUSH”指令使用其他指令执行的相同任务吗?相关的知识,希望对你有一定的参考价值。
[在我看来,目前我们拥有“推”之类的指令的唯一原因是用单个指令替换多个MOV和算术指令。
是否有任何“ PUSH”无法通过更原始的指令来完成?
“ PUSH”是否只是一个可编译为多个机器代码指令的助记符?
推是真实的机器指令(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做较大的调整。
以上是关于我可以先执行“ PUSH”指令使用其他指令执行的相同任务吗?的主要内容,如果未能解决你的问题,请参考以下文章