64 位模式不支持 32 位 PUSH 和 POP 指令 [英] 64-bit mode does not support 32-bit PUSH and POP instructions
问题描述
NASM 返回如下错误:64 位模式不支持指令"
(或使用 YASM,操作数 1 的大小无效
)
NASM returns an error like: "instruction not supported in 64-bit mode"
(Or with YASM, invalid size for operand 1
)
主题指令为pop ecx
和push ecx
.
我可以用什么来代替它们,或者有其他方法可以解决这个问题吗?
The subject instructions are pop ecx
and push ecx
.
What can I use instead of them or is there an other way to fix this issue?
推荐答案
总体思路是您通常推送和弹出完整寄存器,即 64 位模式下的 64 位寄存器.push
的默认操作数大小为 64 位,32 位操作数大小不可用.执行每条PUSH指令在 x64 上推送 8 个字节的倍数?(是的,除非您专门使用 16 位推送,但 32 位不可用).
The general idea is that you normally push and pop full registers, i.e. 64-bit registers in 64-bit mode. push
's default operand-size is 64-bit, and 32-bit operand-size is not available. Does each PUSH instruction push a multiple of 8 bytes on x64? (yes, unless you specifically use a 16-bit push, but 32-bit isn't available).
不能在 64 位模式下压入 32 位寄存器;相反,您可以推送和弹出包含您想要的 32 位值的整个 64 位寄存器,因此使用 push rax
而不是 push eax
.内存引用也是如此——你可以push qword ptr[rax]
,但不能push dword ptr[rax]
.
You cannot push a 32 bit register in 64 bit mode; instead, you can push and pop the whole 64 bit register that contains a 32-bit value you want, so that's push rax
instead of push eax
. The same holds for memory references - you can push qword ptr[rax]
, but not push dword ptr[rax]
.
但是:即使在 64 位模式下,您仍然可以推送:
But: even in 64 bit mode you can still push:
8 或 32 位立即数符号扩展为 64;这通常由您的汇编程序自动处理作为优化(如果您执行
push 1
,它将使用最紧凑的编码对其进行编码,即6A01
,即带有 imm8 操作数).总是64 位推送,除非您明确指定push word 1
,无论汇编程序选择什么宽度.
8 or 32 bit immediates sign extended to 64; this is generally handled automatically by your assembler as an optimization (if you do
push 1
it will encode it with the most compact encoding, which will be6A01
, i.e. with an imm8 operand). It's always a 64-bit push unless you explicitly specifypush word 1
, regardless of what width of immediate the assembler picks.
fs
和 gs
段注册但不是cs
、ds
、es
、ss
寄存器(在 64 位模式下不重要,只能使用 mov
,而不是 push
,释放那些推送/弹出操作码以备将来使用).
the fs
and gs
segment registers but not the cs
, ds
, es
, ss
registers (which aren't important in 64-bit mode, and can only be read with mov
, not push
, freeing up those push/pop opcode for potential future use).
作为一个例外,段寄存器要么被零扩展,要么通过 16 位移动压入堆栈(即堆栈上的其他 48 位保持不变);这并不是什么大问题,因为 pop fs
和 pop gs
只是丢弃这些额外的位.
As an exception, segment registers are either zero-extended or pushed on the stack with a 16-bit move (i.e. the other 48 bit on the stack are left unmodified); this isn't really much of a problem, since pop fs
and pop gs
just discard these extra bits.
您可以使用 push low32
/mov dword [rsp+4], high32
模拟 push imm64
.或者用 mov r64, imm64
/push r64
;mov
来注册(不是内存)是唯一可以采用 64 位立即数的 x86-64 指令.
You can emulate a push imm64
with push low32
/ mov dword [rsp+4], high32
. Or with mov r64, imm64
/ push r64
; mov
to register (not memory) is the only x86-64 instruction that can take a 64-bit immediate.
使用 16 位操作数大小(66h
前缀),您可以执行 16 位推送,将 RSP 调整为 2 而不是 8.但通常不要这样做,因为它会堆栈未对齐,直到您执行 16 位弹出或以其他方式纠正它.
With 16-bit operand-size (a 66h
prefix), you can do a 16-bit push which adjusts RSP by 2 instead of 8. But normally don't do this because it will misalign the stack until you do a 16-bit pop or otherwise correct it.
- 16 位寄存器(
push ax
)和内存引用(push word ptr[rax]
); - 8 位符号扩展或 16 位立即数.
推字123
- 16 bit registers (
push ax
) and memory references (push word ptr[rax]
); - 8-bit sign-extended or 16 bit immediates.
push word 123
8 位寄存器在任何模式下都不能推送(除了作为更宽寄存器的一部分),32 位推送/弹出在 64 位模式下不可用,即使使用 REX.W=0
前缀.
8-bit registers can't be pushed in any mode (except as part of a wider register), and 32-bit push/pop aren't available in 64-bit mode, even with a REX.W=0
prefix.
这篇关于64 位模式不支持 32 位 PUSH 和 POP 指令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!