64位模式不支持PUSH和POP指令

问题描述:

NASM返回如下错误:“在64位模式下不支持指令”,我无法弄清楚该怎么做。主题指令是弹出和推送命令。我可以使用什么来代替它们,或者有其他方法可以解决此问题吗?64位模式不支持PUSH和POP指令

最好的问候......(我使用64位系统 - 英特尔酷睿i7处理器)

+0

显示您的代码,否则问题将无效。 “寻求调试帮助的问题(”为什么不是这个代码工作?“)必须包含所需的行为,特定的问题或错误以及在问题本身中重现问题所需的最短代码。没有明确问题陈述的问题对其他读者无益' –

总体思路是,你通常推而大如当前流行词寄存器大小,所以你不能在64位模式下推送32位寄存器;相反,您可以推送并弹出整个64位寄存器,因此这是push rax而不是push eax。内存引用也是如此 - 您可以使用push qword ptr[rax],但不能使用push dword ptr[rax]

但是:即使在64位模式仍可以推:

  • 16位寄存器(push ax)和存储器的引用(push word ptr[rax]);
  • 8位,16位和32位立即数;这通常由您的汇编程序自动处理为优化(如果您使用push 1它将使用最紧凑的编码进行编码,该编码将为6A01,即imm8操作数)。
  • fsgs段寄存器但不csdsesss寄存器(其没有真正在64位模式中使用)。

在所有这些情况下,小于64位的值(如push al)在符号堆栈上被符号扩展并推送为64位值。这可以让你做一个push -16AFF),匹配pop rax - 那就像你期望的那样,它的工作原理与mov rax,-1完全一样。

作为一个例外,段寄存器或者是-扩展或推入堆栈并且进行16位移动(即堆栈上的另一个48位未被修改);这并不是什么大问题,因为pop fspop gs只是放弃这些额外的位。


最后,可以推16位或32个值(那些在上面的列表中指定)在64位模式而不它们延伸到64位 - 从而移动的只是2堆栈指针或4字节。这是用66hREX.W前缀编码的,但是,如果您不小心,可能会使您产生未对齐的堆栈。

+0

除了可以推送r/m16和r/m64而不是r/m32的事实之外,事实上可以推送imm8,imm16和imm32而不是imm64是很奇怪的太。你不能推CS,DS,ES或SS,但你可以推FS和GS。相当不一致的IMO。 –

+0

@RudyVelthuis:它*很不一致,尽管在这个疯狂中有一些方法。不能推送一个* imm64 *与其余的指令集模糊不清 - 我知道接受* imm64 *的唯一指令是'mov r64,imm64'(实际上,它是* imm64的唯一匹配*在英特尔手册中的整个指令集描述中)。除了* fs *和* gs *之外的段寄存器不再用于64位模式,所以它们不能被推送就不足为奇了。 –

+0

我明白“疯狂背后的方法”。但有时候它会让人感到困惑。特别是你可以推/ 16位而不是32位的项目。 –