Я читал учебник, в котором есть упражнение, которое генерирует ассемблерный код на основе 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;
верхние 32 бита t3
будут нули. Но если мы используем инструкцию andl
и работаем только с %edi
, верхние 32 бита %rdi
все равно будут равны 1, так что это действительно изменит значение t4
в long t4 = t2 - t3;
, где t3
. верхние 32 бита равны 1, но они должны быть 0?