【发布时间】: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?
【问题讨论】:
-
64 位寄存器有一个异常。访问前 32 位总是会将前 32 位清零。我开始的时候也有同样的问题:)。
标签: assembly bit-manipulation x86-64 instructions instruction-set