为什么数据类型是 64 位时要使用 32 位寄存器?
why use 32-bit register when the data type is 64-bit?
我正在阅读一本教科书,其中有一个基于 C 代码生成汇编代码的练习:
C代码:
long arith(long x, long y, long z)
{
long t1 = x ^ y;
long t2 = z * 48;
long t3 = t1 & 0x0F0F0F0F;
long t4 = t2 - t3;
return t4;
}
汇编代码:
//x in %rdi, y in %rsi, z in %rdx
arith:
xorq %rsi, %rdi //t1 = x ^ y
leaq (%rdx,%rdx,2), %rax //3*z
salq , %rax //t2 = 16 * (3*z) = 48*z
andl 2645135, %edi //t3 = t1 & 0x0F0F0F0F
subq %rdi, %rax //Return t2 - t3
ret
我对这段汇编代码感到困惑:
andl 2645135, %edi //t3 = t1 & 0x0F0F0F0F
为什么我们不使用:
andq 2645135, %rdi
问题是,假设t1
的所有位都是1,那么对于原始C代码long t3 = t1 & 0x0F0F0F0F;
,t3
的高32位将是0。但是如果我们使用andl
指令,只对%edi
进行操作,%rdi
的高32位仍然是1,所以这确实改变了t4
在long t4 = t2 - t3;
其中 t3
的高 32 位都是 1 但它们应该是 0?
答案在 Intel 64 和 IA-32 架构软件开发人员手册第 1 卷(基本架构)的第 3.4.1.1 节中指出:
When in 64-bit mode, operand size determines the number of valid bits in the destination general-purpose register:
- 64-bit operands generate a 64-bit result in the destination general-purpose register.
- 32-bit operands generate a 32-bit result, zero-extended to a 64-bit result in the destination general-purpose register.
- 8-bit and 16-bit operands generate an 8-bit or 16-bit result. The upper 56 bits or 48 bits (respectively) of the destination general-purpose register are not modified by the operation. If the result of an 8-bit or 16-bit operation is intended for 64-bit address calculation, explicitly sign-extend the register to the full 64-bits.
参见第二个项目符号。
您可以通过阅读以下内容来了解为什么会这样:Why do x86-64 instructions on 32-bit registers zero the upper part of the full 64-bit register?
我正在阅读一本教科书,其中有一个基于 C 代码生成汇编代码的练习:
C代码:
long arith(long x, long y, long z)
{
long t1 = x ^ y;
long t2 = z * 48;
long t3 = t1 & 0x0F0F0F0F;
long t4 = t2 - t3;
return t4;
}
汇编代码:
//x in %rdi, y in %rsi, z in %rdx
arith:
xorq %rsi, %rdi //t1 = x ^ y
leaq (%rdx,%rdx,2), %rax //3*z
salq , %rax //t2 = 16 * (3*z) = 48*z
andl 2645135, %edi //t3 = t1 & 0x0F0F0F0F
subq %rdi, %rax //Return t2 - t3
ret
我对这段汇编代码感到困惑:
andl 2645135, %edi //t3 = t1 & 0x0F0F0F0F
为什么我们不使用:
andq 2645135, %rdi
问题是,假设t1
的所有位都是1,那么对于原始C代码long t3 = t1 & 0x0F0F0F0F;
,t3
的高32位将是0。但是如果我们使用andl
指令,只对%edi
进行操作,%rdi
的高32位仍然是1,所以这确实改变了t4
在long t4 = t2 - t3;
其中 t3
的高 32 位都是 1 但它们应该是 0?
答案在 Intel 64 和 IA-32 架构软件开发人员手册第 1 卷(基本架构)的第 3.4.1.1 节中指出:
When in 64-bit mode, operand size determines the number of valid bits in the destination general-purpose register:
- 64-bit operands generate a 64-bit result in the destination general-purpose register.
- 32-bit operands generate a 32-bit result, zero-extended to a 64-bit result in the destination general-purpose register.
- 8-bit and 16-bit operands generate an 8-bit or 16-bit result. The upper 56 bits or 48 bits (respectively) of the destination general-purpose register are not modified by the operation. If the result of an 8-bit or 16-bit operation is intended for 64-bit address calculation, explicitly sign-extend the register to the full 64-bits.
参见第二个项目符号。
您可以通过阅读以下内容来了解为什么会这样:Why do x86-64 instructions on 32-bit registers zero the upper part of the full 64-bit register?