x86-64汇编中movl %eax,%rdx是否为合法指令?
movl %eax, %rdx指令合法性解答 - 核心结论:
movl %eax, %rdx是非法x86-64指令。你看到的参考答案存在笔误:它将错误指令的目的寄存器写为16位的%dx,但标注的报错原因「Destination operand incorrect size(目的操作数尺寸错误)」完全准确。 - 指令合法性判定规则:x86-64汇编中,指令后缀明确指定了操作数的位宽,
movl的后缀l代表操作数为32位长字,要求源、目的操作数的位宽必须严格匹配32位。64位寄存器(如%rdx)、16位/8位寄存器都不能作为movl的操作数,只有32位寄存器(如%edx、%eax)、32位内存地址可以作为movl的合法操作数。 - 对零扩展规则的误解澄清:你提到的「以寄存器为目标、生成4字节值的指令会将寄存器高4字节填0」是x86-64的正确设计,但该规则的适用前提是使用了合法的32位寄存器作为目的操作数。例如合法指令
movl %eax, %edx执行时,硬件会自动将%eax的32位值复制到%edx低32位,同时将%rdx(%edx对应的64位完整寄存器)的高32位清零,整个过程不需要额外的零扩展指令,这也是x86-64指令集没有设计movzlq(32位零扩展到64位传送)指令的原因——这个操作已经被32位指令的隐式行为覆盖了,不需要冗余指令。 - GCC编译结果的原因解释:你测试时看到GCC生成
movslq %eax, %rdx,是由你所写C代码的类型语义决定的,和上述规则不冲突:- 如果C代码中是将
unsigned int类型的32位无符号值转换为64位无符号整数,GCC一定会生成movl %eax, %edx这类32位传送指令,靠硬件的隐式零扩展完成转换,不会生成多余指令。 - 如果C代码中是将
int类型的32位带符号值转换为64位带符号整数,按照C语言标准要求必须执行符号扩展:将32位源值的符号位填充到64位目的值的高32位。这个操作无法通过32位mov的隐式零扩展实现(零扩展会将高32位全部填0,和负数的符号扩展结果完全不符,会产生计算错误),必须使用专门的符号扩展传送指令movslq完成。
- 如果C代码中是将
内容的提问来源于stack exchange,提问作者jeffma
相关产品推荐
相关产品推荐

