Подтвердить что ты не робот

__int64 на 32-битной машине?

Я только что попробовал что-то в MSVC 2010 на моей 32-битной машине и выяснил, что могу использовать __int64 в своих программах, которые действительно работают!

  • Как это возможно?
4b9b3361

Ответ 1

То же самое 32-разрядная арифметика работала на 16-разрядных системах.

В этом случае он использует 2 32-разрядных адреса памяти для формирования 64-битного числа вместе. Добавление/подстановка легко, вы делаете это по частям, только полученный получает перенос от нижней части к более высокой части. Для умножения/деления это сложнее (т.е. больше инструкций).

Он явно медленный, довольно медленный, чем 32-разрядная арифметика для умножения, но если вам это нужно, это там для вас. И когда вы переходите на 64-разрядный компилятор processor, он автоматически оптимизируется для одной инструкции с большим размером слова.

В Visual Studio 2010 Professional реализация 64-разрядного умножения на 32-разрядном процессоре, скомпилированном в режиме выпуска, составляет:

_allmul PROC NEAR

A       EQU     [esp + 4]       ; stack address of a
B       EQU     [esp + 12]      ; stack address of b

        mov     eax,HIWORD(A)
        mov     ecx,HIWORD(B)
        or      ecx,eax         ;test for both hiwords zero.
        mov     ecx,LOWORD(B)
        jnz     short hard      ;both are zero, just mult ALO and BLO

        mov     eax,LOWORD(A)
        mul     ecx

        ret     16              ; callee restores the stack

hard:
        push    ebx

A2      EQU     [esp + 8]       ; stack address of a
B2      EQU     [esp + 16]      ; stack address of b

        mul     ecx             ;eax has AHI, ecx has BLO, so AHI * BLO
        mov     ebx,eax         ;save result

        mov     eax,LOWORD(A2)
        mul     dword ptr HIWORD(B2) ;ALO * BHI
        add     ebx,eax         ;ebx = ((ALO * BHI) + (AHI * BLO))

        mov     eax,LOWORD(A2)  ;ecx = BLO
        mul     ecx             ;so edx:eax = ALO*BLO
        add     edx,ebx         ;now edx has all the LO*HI stuff

        pop     ebx

        ret     16              ; callee restores the stack

Как вы можете видеть, это LOT медленнее обычного умножения.

Ответ 2

Почему вы считаете это неожиданным? Там ничего не мешает компилятору поддерживать 64-, 128- или более-битные целые типы на 32-битной машине. Компилятор может даже поддерживать 57- и 91-битные типы, если это так. На практике поддержка 2-разрядной целочисленной арифметики на N-разрядной машине является относительно простой задачей, поскольку набор команд типичной машины часто разработан с учетом такого рода функций.

Ответ 3

32 бита - это всего лишь собственный размер машинного слова, то есть они могут обрабатываться за один раз, это не означает, что большие элементы не могут обрабатываться вообще, их просто нужно обрабатывать как отдельные 32-битные единиц в несколько шагов, так же, как они могут быть меньше машинного слова, и в этом случае будет обрабатываться только часть полного машинного слова.

Ответ 4

Это работает, потому что 64-битные целочисленные типы данных часть спецификации языка.

Компилятор для языка ДОЛЖЕН позволить вам работать с 64-битными целыми числами (и, конечно же, получить правильные результаты).

Ваша программа должна работать (и работать точно так же), ориентируетесь ли вы на 64-разрядную, 32-разрядную, 16-разрядную или 8-разрядную машину (независимо от того, что разрешает компилятор).

Тот, кто написал компилятор, должен был сделать все необходимое, чтобы каждый поддерживаемый тип данных работал на каждом целевом типе процессора.

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

Как?

Очевидно, что прием кода, который командует 16-разрядными арифметическими операциями и переводит его в машинный код, который работает на 16-разрядном (или выше) процессоре, является "легкой" работой для компилятора, почти прямого перевода. Z = X + Y может перевести на mov a,(X); add a,(Y); mov (Z),a;.

И наоборот, принятие кода, который командует 64-разрядными арифметическими операциями и переводит его в машинный код, который работает на 32-разрядном (или более низком) процессоре, является более сложным. У компилятора больше работы, работая на 32-битных фрагментах каждого операнда за раз. Есть еще несколько способов сделать это.

В результате машинный код может использовать несколько инструкций inline (более крупный код, более быстрое выполнение). Z = X + Y может перевести на mov a,(X); adc a,(Y); mov (Z),a; mov a,CARRY; adc a,(X+1); adc a,(Y+1); mov (Z+1),a;.

Полученный машинный код может вызывать расширенные арифметические подпрограммы (меньший код, более медленное выполнение). Z = X + Y может перевести на mov a,X; call GET64; mov a,Y; call ADD64; mov a,Z; call STORE64;.