Acabo de probar algo en MSVC 2010 en mi máquina de 32 bits aquí y descubrí que puedo usar __int64 en mis programas, ¡lo que realmente funciona!__int64 en una máquina de 32 bits?
- ¿Cómo es eso posible?
Acabo de probar algo en MSVC 2010 en mi máquina de 32 bits aquí y descubrí que puedo usar __int64 en mis programas, ¡lo que realmente funciona!__int64 en una máquina de 32 bits?
De la misma manera la aritmética de 32 bits funcionó en sistemas de 16 bits.
En este caso, usa 2 direcciones de memoria de 32 bits para formar un número de 64 bits. La suma/substracción es fácil, lo haces por partes, el único problema es llevar el remanente de la parte inferior a la parte superior. Para la multiplicación/división, es más difícil (es decir, más instrucciones).
Es obviamente lento, bastante más lento que la aritmética de 32 bits para la multiplicación, pero si lo necesita, está ahí para usted. Y cuando se actualiza a un compilador del procesador
de 64 bits
, se optimiza automáticamente a una instrucción con el tamaño de palabra más grande.
La aplicación Visual Studio 2010 Profesional de la multiplicación de 64 bits en un procesador de 32 bits, compilado en modo de lanzamiento, es:
_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
Como se puede ver, es mucho más lenta que la multiplicación normal.
¿Por qué le parece sorprendente? No hay nada que evite que el compilador admita tipos enteros de 64, 128 o más bits en una máquina de 32 bits. El compilador incluso puede admitir tipos de 57 y 91 bits, si así lo desea. En la práctica, admitir la aritmética de enteros de 2N bit en una máquina de N bits es una tarea relativamente fácil, ya que el conjunto de instrucciones de una máquina típica a menudo se diseña teniendo en cuenta este tipo de funcionalidad.
32 bits son simplemente el tamaño nativo de una palabra máquina, lo que significa que se pueden procesar de una sola vez, no significa que los elementos más grandes no se pueden procesar en absoluto, solo se deben procesar por separado. unidades de bit en varios pasos, de la misma manera que pueden ser más pequeñas que una palabra de máquina, en cuyo caso simplemente se procesará una porción de la palabra de la máquina completa.
Funciona porque los tipos de datos enteros de 64 bits son parte de la especificación de idioma.
Un compilador para el lenguaje DEBE permitirte trabajar con enteros de 64 bits (y obtener resultados correctos, por supuesto).
Su programa debe funcionar (y funcionar exactamente igual), tanto si se dirige a una máquina de 64 bits, 32 bits, 16 bits u 8 bits (lo que permita el compilador).
El que escribió el compilador se vio obligado a hacer que haga lo que sea necesario hacer cada apoyado el trabajo de tipo de datos en cada apuntado tipo de procesador.
El soporte de los tipos de datos potencialmente "superiores" ha sido solucionado, para que usted no tenga que hacerlo usted mismo.
¿Cómo?
Obviamente, aceptar un código que ordene operaciones aritméticas de 16 bits y traducirlo a código máquina que se ejecuta en un procesador de 16 bits (o superior) es trabajo "fácil" para un compilador, casi una traducción directa. Z = X + Y
podría traducir a mov a,(X); add a,(Y); mov (Z),a;
.
Por el contrario, aceptar código que ordena operaciones aritméticas de 64 bits y traducirlo a código de máquina que se ejecuta en un procesador de 32 bits (o inferior) es más complejo. El compilador tiene más trabajo por hacer, operando en piezas de 32 bits de cada operando a la vez. Hay más formas de hacerlo.
El código de máquina resultante podría utilizar múltiples instrucciones en línea (código más grande, ejecución más rápida). Z = X + Y
podría traducir a mov a,(X); adc a,(Y); mov (Z),a; mov a,CARRY; adc a,(X+1); adc a,(Y+1); mov (Z+1),a;
.
El código máquina resultante podría llamar a subrutinas aritméticas extendidas (código más pequeño, ejecución más lenta). Z = X + Y
podría traducir a mov a,X; call GET64; mov a,Y; call ADD64; mov a,Z; call STORE64;
.
¡Incluso podría usar int64_t estándar! –
@ el.pescado: 'int64_t' es solo estándar en C99; actualmente no es parte del estándar C++, pero se agregará en el próximo C++ 0x. –
En la práctica, su máquina de 32 bits (es decir,> Pentium) tiene compatibilidad nativa de 64 bits, también tiene 36 bits de espacio de direcciones. Solo son las ventanas las que eligen limitarlo a 32 bits –