【问题标题】:why use 32-bit register when the data type is 64-bit?当数据类型为 64 位时,为什么使用 32 位寄存器?
【发布时间】:2020-10-29 14:35:48
【问题描述】:

我正在阅读一本教科书,其中有一个基于 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 $4, %rax                 //t2 = 16 * (3*z) = 48*z
   andl $252645135, %edi         //t3 = t1 & 0x0F0F0F0F
   subq %rdi, %rax               //Return t2 - t3
   ret

我对这个汇编代码感到困惑:

andl $252645135, %edi         //t3 = t1 & 0x0F0F0F0F

我们为什么不使用:

andq $252645135, %rdi

问题是,假设t1 的所有位都是1,那么对于原始C 代码long t3 = t1 & 0x0F0F0F0F;t3 的高32 位将为0。但是如果我们使用andl指令,并且只对%edi进行操作,%rdi的高32位仍然是1s,所以这确实改变了long t4 = t2 - t3;t4的值,其中t3的高 32 位都是 1,但它们应该是 0?

【问题讨论】:

标签: assembly bit-manipulation x86-64 instructions instruction-set


【解决方案1】:

答案在 Intel 64 和 IA-32 架构软件开发人员手册第 1 卷(基本架构)的第 3.4.1.1 节中,其中指出:

在 64 位模式下,操作数大小决定了目标通用寄存器中的有效位数:

  • 64 位操作数在目标通用寄存器中生成 64 位结果。
  • 32 位操作数生成 32 位结果,在目标通用寄存器中进行零扩展为 64 位结果。
  • 8 位和 16 位操作数生成 8 位或 16 位结果。目标通用寄存器的高 56 位或 48 位(分别)不被操作修改。如果 8 位或 16 位运算的结果用于 64 位地址计算,请将寄存器显式符号扩展为完整的 64 位。

参见第二个项目符号。

您可以通过阅读了解为什么会这样:Why do x86-64 instructions on 32-bit registers zero the upper part of the full 64-bit register?

【讨论】:

    猜你喜欢
    • 2012-06-25
    • 2011-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多