64 位模式不支持 32 位 PUSH 和 POP 指令 [英] 64-bit mode does not support 32-bit PUSH and POP instructions

查看:253
本文介绍了64 位模式不支持 32 位 PUSH 和 POP 指令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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 ecxpush 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 be 6A01, 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.

fsgs 段注册但不是csdsesss 寄存器(在 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 fspop 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆