Очень простой вопрос, я читал, что GCC поддерживает long long int type. Но как сделать математические операции с ним, когда процессор только 32 бит?
Long long int на 32-битных машинах
Ответ 1
Компилятор будет синтезировать математические операции (или использовать вызовы функций), которые используют более одной команды ЦП для выполнения операции. Например, операция добавления добавит компоненты низкого порядка (низкие слова) значений long long
и затем выполнит эту операцию и подаст ее в операцию добавления в словах высокого порядка long long
.
Итак, следующий код C:
long long a;
long long b;
long long c;
// ...
c = a + b;
может быть представлена последовательностью команд, которая выглядит примерно так:
mov eax, [a.low] ; add the low order words
add eax, [b.low]
mov edx, [a.high] ; add the high order words,
adc edx, [b.high] ; including the carry
mov [c.low], eax
mov [c.high], edx
И если вы считаете, что компиляторы для систем с 8 и 16 битами должны были делать этот тип вещей для 16 и/или 32-битных значений задолго до появления long long
.
Ответ 2
Внутренне тип представлен высоким словом и низким словом, например:
struct long
{
int32 highWord;
uint32_t lowWord;
}
Компилятор должен знать, является ли это 32-битной или 64-битной средой, а затем выбирает правильные записи числа - если это 64 бит, это можно сделать изначально, если оно 32 бит, компилятор должен позаботиться о математика между высоким/низким словом.
Если вы посмотрите в math.h, вы можете увидеть функции, используемые для этого, и использовать их самостоятельно. В дополнение, обратите внимание на разницу между мини-эндиан и big-endian (см. Wiki), использование зависит от операционной системы.
Ответ 3
Говоря о архитектуре, 32-разрядный (или 64 или любой другой), как правило, является лишь приближением того, на что способен процессор. Обычно вы ссылаетесь только на ширину указателей с этим числом, арифметика может быть совсем другой. Например, архитектура x86 имеет 32-битные указатели, большинство арифметических операций выполняется в 32-битных регистрах, но также имеет встроенную поддержку некоторых базовых 64-разрядных операций.
Также вы не должны следить за тем, чтобы стандартные стандартные типы имели определенную ширину. В частности, длинный длинный не менее 64 бит, но может быть шире. Используйте typedefs int32_t, int64_t, если вы хотите быть уверенно в отношении ширины.
Если вы хотите узнать, что делает gcc (или любой другой компилятор) с длинным долгом, вам нужно изучить спецификацию для вашей целевой платформы
Ответ 4
Это достаточно просто, чтобы просто скомпилировать и протестировать, если у вас есть доступная 32-битная система. gcc имеет флаг -S
, который включает выход ассемблера. Вот что он производит на моем 32-битном Intel:
// read two long longs from stack into eax:edx and ecx:ebx
movl 32(%esp), %eax
movl 36(%esp), %edx
movl 24(%esp), %ecx
movl 28(%esp), %ebx
// a+b
addl %ecx, %eax
adcl %ebx, %edx
// a-b
subl %ecx, %eax
sbbl %ebx, %edx
// etc
Ответ 5
Скорее всего, как класс, а не изначально. таким же образом любой компилятор может/может поддерживать любой большой набор чисел.