Divide Signed Integer By 2 компилирует в сложный вывод сборки, а не просто сдвиг - PullRequest
0 голосов
/ 12 сентября 2018

Рассмотрим эту функцию C;

int triangle(int width, int height)
{
    return (width * height) / 2;
}

При компиляции с gcc (gcc -m32 -g -c test.c) производит следующую сборку (objdump -d -M intel -S test.o).

test.o:     file format elf32-i386


Disassembly of section .text:

00000000 <triangle>:

int triangle(int width, int height)
{
   0:   55                      push   ebp
   1:   89 e5                   mov    ebp,esp
    return (width * height) / 2;
   3:   8b 45 08                mov    eax,DWORD PTR [ebp+0x8]
   6:   0f af 45 0c             imul   eax,DWORD PTR [ebp+0xc]
   a:   89 c2                   mov    edx,eax
   c:   c1 ea 1f                shr    edx,0x1f
   f:   01 d0                   add    eax,edx
  11:   d1 f8                   sar    eax,1
  13:   5d                      pop    ebp
  14:   c3                      ret    

Я уже знаю, что, сдвигая целое число n бит вправо, делим его на 2 ^ n. Однако, согласно вышеприведенному выводу, целые числа со знаком, похоже, обрабатываются по-разному (что, конечно, имеет смысл). Если я правильно читаю вывод сборки, подпишите бит целого числа, добавленного к нему перед смещением.

Какова цель добавления знака целого бита к себе перед смещением вправо?

1 Ответ

0 голосов
/ 13 сентября 2018

Это для получения правильного результата "округления до нуля" для отрицательных чисел. Деление путем сдвига раундов в сторону отрицательной бесконечности, поэтому отрицательные числа будут иметь другой результат по сравнению с ожидаемым результатом оператора деления C.

Примером является -1: сдвиг вправо на 1 дает -1 еще, но оператор C / 2 дает 0.

Таким образом, дополнительный код является исправлением для этого эффекта. Если вам это не нужно, используйте unsigned или явное смещение (но второй вариант менее переносим).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...