NASM返回如下错误:"在64位模式下不支持指令"而且我无法弄清楚要做什么。
主题说明是pop ecx
和push ecx
说明。我可以使用什么代替它们,还是有其他方法来解决这个问题?
答案 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
,无论汇编程序选择的是什么宽度。
fs
和gs
段注册但不 cs
,ds
,es
,{{ 1}}寄存器(在64位模式下不重要,只能用mov
读取,而不是ss
,释放那些推/弹操作码以备将来使用)。
作为一个例外,段寄存器要么 0 -extended或者在16位移动的情况下被压入堆栈(即堆栈中的其他48位未被修改);这不是一个很大的问题,因为push
和pop 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位弹出或以其他方式纠正它。
66h
)和存储器引用(push ax
); 8位寄存器不能在任何模式下被推送(除了作为更宽寄存器的一部分),并且32位在64位模式下不可用even with a REX.W=0
prefix。< / p>