2013-08-26 2 views
1

Когда gcc видит умножение или деление целочисленных типов, которые не поддерживаются аппаратным обеспечением, он вызывает вызов специальной библиотечной функции.divdi3 деление используется для long long gcc on x86

http://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html#Integer-library-routines

По ссылке выше, long __divdi3 (long a, long b) используется для разделения долго. Однако здесь http://gcc.gnu.org/onlinedocs/gcc-3.3/gccint/Library-Calls.html divdi объясняется как «призыв к делению одного подписанного двойного слова». Когда первый источник имеет Клири отображение ди суффиксом -> длинные аргументы, вторые состояния divdi для двойного слова и udivdi для полного слова (сингл, верно?)

Когда я компилирую простой пример

int main(int argc, char *argv[]) { 
    long long t1, t2, tr; 

    t1 = 1; 
    t2 = 1; 
    tr = t1/t2; 

    return tr; 
} 

с gcc -Wall -O0 -m32 -march=i386 (НКУ вер. 4.7.2) dissamble показывает мне

080483cc <main>: 
    80483cc:  55      push %ebp 
    80483cd:  89 e5     mov %esp,%ebp 
    80483cf:  83 e4 f0    and $0xfffffff0,%esp 
    80483d2:  83 ec 30    sub $0x30,%esp 
    80483d5:  c7 44 24 28 01 00 00 movl $0x1,0x28(%esp) 
    80483dc:  00 
    80483dd:  c7 44 24 2c 00 00 00 movl $0x0,0x2c(%esp) 
    80483e4:  00 
    80483e5:  c7 44 24 20 01 00 00 movl $0x1,0x20(%esp) 
    80483ec:  00 
    80483ed:  c7 44 24 24 00 00 00 movl $0x0,0x24(%esp) 
    80483f4:  00 
    80483f5:  8b 44 24 20    mov 0x20(%esp),%eax 
    80483f9:  8b 54 24 24    mov 0x24(%esp),%edx 
    80483fd:  89 44 24 08    mov %eax,0x8(%esp) 
    8048401:  89 54 24 0c    mov %edx,0xc(%esp) 
    8048405:  8b 44 24 28    mov 0x28(%esp),%eax 
    8048409:  8b 54 24 2c    mov 0x2c(%esp),%edx 
    804840d:  89 04 24    mov %eax,(%esp) 
    8048410:  89 54 24 04    mov %edx,0x4(%esp) 
    8048414:  e8 17 00 00 00   call 8048430 <__divdi3> 
    8048419:  89 44 24 18    mov %eax,0x18(%esp) 
    804841d:  89 54 24 1c    mov %edx,0x1c(%esp) 
    8048421:  8b 44 24 18    mov 0x18(%esp),%eax 
    8048425:  c9      leave 
    8048426:  c3      ret 

Примечание 8048414: call 8048430 <__divdi3>.

Я не могу использовать gcc lib для моего проекта и многоплатформенность. Я надеялся не писать все функции __* для всех платформ (скорость не имеет значения), но теперь я немного смущен.

Может кто-нибудь объяснить, почему есть __divdi3 (не __divti3) звонок, сгенерированный для long long int (64-разрядная) деление?

ответ

2

Нет слова как слова. На машинах x86 слово обычно означает 16 бит. Это принято. Обычно word - это 16-разрядное или 32-разрядное число, ширина которого зависит от активированного режима (реального или защищенного).

Я думаю, что эта терминология указана, потому что linux/unix обычно работает на многих платформах. Вы можете ощущать конфликты терминных значений на других инструментах. Живой пример: gdb, который использует w для 32-битного слова и hw для 16-разрядного «полуслова».

EDIT: Существует другое имя, используемое для размера поплавков, но иногда оно также используется для целых чисел. Это:

  • s - одинарная (точность, слово?) Для четырех байт целых чисел (int)/поплавков (float)
  • d - двойная (точность) для восьми байт целых чисел (long или long long)/поплавки (double)
  • t - десять байт для целых чисел (long long)/поплавки (long double)

Это обозначение используется для всех арифметических дополнений, таких как , __divdi3, __divti3 или __mulsi3, __muldi3, __multi3 ... (и все u - без знака - варианты). Это причина для __divdi3. Полный список: on this page.

Отдел 64-разрядных номеров на 32-битных машинах использует расширенный (и бит сложный) алгоритм. Вы можете использовать принцип принципала, который вы изучили в школе.Выделение небольшого значения из большого числа будет тратить время, но вы можете разделить детали с разной степенью детализации отдельно и быстрее получить результат. Вот простой псевдокод для него (посмотрите на this answer о больших целых числах):

result = 0; 
count = 0; 
remainder = numerator; 

while(highest_bit_of_divisor_not_set) { 
    divisor = divisor << 1; 
    count++; 
} 
while(remainder != 0) { 
    if(remainder >= divisor) { 
     remainder = remainder - divisor; 
     result = result | (1 << count); 
    } 
    if(count == 0) { 
     break; 
    } 
    divisor = divisor >> 1; 
    count--; 
} 
+0

Спасибо. Я исправил сообщение. Вопрос не в алгоризме, а в согласии. Я ожидал увидеть вызов '__divti3', но там' __divdi3'. – user2718551

+0

Отредактировано, вот оно. – user35443

+0

Спасибо, но до сих пор неясно, почему '' '' '' длинные' ** или ** 'long long'. Источник, который вы даете, - это первая ссылка в сообщении. Он утверждает, что 'd' для' long', 't' для' long long', без параметров. Если может быть какая-то вариация, почему 'd' выбрано, а не' t'? – user2718551