问题
NASM returns an error like: "instruction not supported in 64-bit mode" and I couldn't figure out what to do.
The subject instruction is pop ecx
and push ecx
instructions. What can I use instead of them or is there an other way to fix this issue?
回答1:
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).
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]
.
But: even in 64 bit mode you can still push:
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 specify push word 1, regardless of what width of immediate the assembler picks.the
fs
andgs
segment registers but not thecs
,ds
,es
,ss
registers (which aren't important in 64-bit mode, and can only be read with mov, notpush
, freeing up those push/pop opcode for potential future use).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
andpop gs
just discard these extra bits.
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.
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 bit registers (
push ax
) and memory references (push word ptr[rax]
); - 8-bit sign-extended or 16 bit immediates.
8-bit registers can't be pushed in any mode (except as part of a wider register), and 32-bit isn't available in 64-bit mode, even with a REX.W=0 prefix.
来源:https://stackoverflow.com/questions/43435764/64-bit-mode-do-not-support-push-and-pop-instructions