2010-04-22 12 views
23

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?
+2

¡Incluso podría usar int64_t estándar! –

+0

@ 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. –

+0

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 –

Respuesta

34

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.

+1

No se optimizará a menos que compile para x64, independientemente del procesador que tenga. –

+0

Er, sí, eso es lo que quise decir. Larga noche ... – Blindy

+0

¡Hubiera sido cierto en C# sin embargo! – Blindy

5

¿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.

3

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.

0

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;.

Cuestiones relacionadas