问题
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 1it 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
fsandgssegment registers but not thecs,ds,es,ssregisters (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 fsandpop gsjust 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