зачем использовать 32-битный регистр, если тип данных 64-битный? - PullRequest
1 голос
/ 09 июля 2020

Я читал учебник, в котором есть упражнение, которое генерирует ассемблерный код на основе 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?

1 Ответ

5 голосов
/ 09 июля 2020

Ответ находится в Разделе 3.4.1.1 Руководства разработчика программного обеспечения для архитектур Intel 64 и IA-32, том 1 (Basi c Architecture), в котором говорится:

В 64-битном режиме размер операнда определяет количество допустимых битов в целевом регистре общего назначения:

  • 64-битные операнды генерируют 64-битный результат в целевом регистре общего назначения.
  • 32-битные операнды генерируют 32-битный результат с расширением нулями до 64-битного результата в целевом регистре общего назначения.
  • 8-битные и 16-битные операнды генерируют 8-битные или 16-битные бит результат. Старшие 56 или 48 битов (соответственно) целевого регистра общего назначения не изменяются в результате операции. Если результат 8-битной или 16-битной операции предназначен для вычисления 64-битного адреса, явно расширьте регистр знаками до полных 64-бит.

См. Второй bullet.

Вы можете понять, почему это так, прочитав: Почему инструкции x86-64 в 32-битных регистрах обнуляют верхнюю часть полного 64-битного регистра?

...