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

时间:2017-04-16 09:29:52

标签: assembly nasm x86-64

NASM返回如下错误:"在64位模式下不支持指令"而且我无法弄清楚要做什么。

主题说明是pop ecxpush ecx说明。我可以使用什么代替它们,还是有其他方法来解决这个问题?

1 个答案:

答案 0 :(得分:14)

一般的想法是你通常推送和弹出完整的寄存器,即64位模式下的64位寄存器。 push的默认操作数大小为64位,32位操作数大小不可用。 Does each PUSH instruction push a multiple of 8 bytes on x64?(是的,除非您专门使用16位推送,但32位不可用)。

您无法在64位模式下推送32位寄存器;相反,您可以按下并弹出包含所需32位值的整个64位寄存器,以便push rax代替push eax。内存引用也是如此 - 您可以push qword ptr[rax],但不能push dword ptr[rax]

但是:即使在64位模式下,你仍然可以推送:

  • 8或32位立即将符号扩展为64;这通常由汇编程序自动处理为优化(如果你push 1,它将使用最紧凑的编码对其进行编码,编码为6A01,即使用 imm8 操作数)。它是always a 64-bit push unless you explicitly specify push word 1,无论汇编程序选择的是什么宽度。

  • fsgs段注册但不 csdses,{{ 1}}寄存器(在64位模式下不重要,只能用mov读取,而不是ss,释放那些推/弹操作码以备将来使用)。

    作为一个例外,段寄存器要么 0 -extended或者在16位移动的情况下被压入堆栈(即堆栈中的其他48位未被修改);这不是一个很大的问题,因为pushpop fs只是丢弃这些额外的位。

您可以使用pop gs / push imm64模仿push low32。或者使用mov dword [rsp+4], high32 / mov r64, imm64; push r64注册(不是内存)是唯一可以立即采用64位的x86-64指令。

使用16位操作数大小(mov前缀),您可以进行16位推送,将RSP调整为2而不是8。但通常不会这样做,因为它会不对齐堆栈,直到你进行16位弹出或以其他方式纠正它。

  • 16位寄存器(66h)和存储器引用(push ax);
  • 8位符号扩展或16位立即。

8位寄存器不能在任何模式下被推送(除了作为更宽寄存器的一部分),并且32位在64位模式下不可用even with a REX.W=0 prefix。< / p>