(1个答案)
Does each PUSH instruction push a multiple of 8 bytes on x64?
(2个答案)
3年前关闭。
NASM返回错误,例如:“ 64位模式不支持指令”,我不知道该怎么办。
主指令是
pop ecx
和push ecx
指令。我可以用什么代替它们,或者有其他方法可以解决此问题? 最佳答案
一般的想法是,您通常压入并弹出完整的寄存器,即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
,ss
寄存器(在64位模式下并不重要,只能用mov
读取) ,而不是push
,释放那些推送/弹出操作码以备将来使用。
作为例外,段寄存器可以零扩展或以16位的移动量压入堆栈(即堆栈上的其他48位保持不变);这并不是什么大问题,因为pop fs
和pop gs
只是丢弃这些多余的位。
您可以使用push imm64
/ push low32
模拟mov dword [rsp+4], high32
。或使用mov r64, imm64
/ push r64
; mov
用来注册(不是内存)是唯一可以立即执行64位立即数的x86-64指令。
使用16位操作数大小(66h
前缀),您可以执行16位压入,将RSP调整为2而不是8。但是通常不要这样做,因为它会在您执行16之前使堆栈不对齐位弹出或以其他方式纠正它。
16位寄存器(push ax
)和存储器引用(push word ptr[rax]
);
8位符号扩展或16位立即数。
8位寄存器不能以任何模式推送(除了作为更宽寄存器的一部分),并且32位在64位模式even with a REX.W=0
prefix中不可用。
关于assembly - 64位模式不支持PUSH和POP指令,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43435764/