sistemas sistema que programa pasa operativos operativo instalo entre diferencia cual arquitectura windows assembly binary x86

windows - sistema - ¿Es válido el código de ensamblado x86 de 32 bits código de ensamblaje x86 de 64 bits?



sistema operativo de 64 bits (2)

¿Es válido todo el código de ensamblaje x86 de 32 bits código de ensamblado x86 de 64 bits?

Me he preguntado si el código ensamblador de 32 bits es un subconjunto del código ensamblador de 64 bits, es decir, ¿cada código ensamblador de 32 bits se puede ejecutar en un entorno de 64 bits?

Supongo que la respuesta es sí, porque Windows de 64 bits es capaz de ejecutar programas de 32 bits, pero luego he visto que el procesador de 64 bits admite un modo compatible de 32 bits.

De lo contrario, proporcione un pequeño ejemplo de código ensamblador de 32 bits que no sea un código ensamblador de 64 bits válido y explique cómo el procesador de 64 bits ejecuta el código ensamblador de 32 bits.


No, aunque hay una gran cantidad de solapamiento, el código ensamblador de 64 bits no es un superconjunto del código ensamblador de 32 bits y, por lo tanto, el ensamblaje de 32 bits no es en general válido en el modo de 64 bits.

Esto aplica tanto la fuente de ensamblaje mnemotécnico (que se ensambla en formato binario por un ensamblador), como el formato de código de máquina binario.

Esta pregunta cubre con cierto detalle las instrucciones que se eliminaron, pero también hay muchas formas de codificación cuyos significados se cambiaron.

Por ejemplo, Jester en los comentarios da el ejemplo de que push eax no es válido en el código de 64 bits. En base a esta referencia , puede ver que la inserción de 32 bits está marcada NE, lo que significa que no es codificable . En el modo de 64 bits, la codificación se usa para representar push rax (un impulso de 8 bytes). Entonces, la misma secuencia de bytes tiene un significado diferente en el modo de 32 bits en comparación con el de 64 bits.

En general, puede navegar por la lista de instrucciones en ese sitio y encontrar muchas que se enumeran como no válidas o no codificables en 64 bits.

De lo contrario, proporcione un pequeño ejemplo de código ensamblador de 32 bits que no sea un código ensamblador de 64 bits válido y explique cómo el procesador de 64 bits ejecuta el código ensamblador de 32 bits.

Como arriba, push eax es uno de esos ejemplos. Creo que lo que falta es que las CPU de 64 bits soportan directamente binarios de 32 bits. No lo hacen a través de la compatibilidad entre las instrucciones de 32 bits y 64 bits en el nivel de lenguaje de la máquina, sino simplemente por tener un modo de 32 bits donde los decodificadores (en particular) interpretan el flujo de instrucciones como x86 de 32 bits en lugar de x86-64, así como el llamado modo largo para ejecutar instrucciones de 64 bits. Cuando se lanzaron por primera vez esos chips de 64 bits, era común ejecutar un sistema operativo de 32 bits, lo que significa que el chip está permanentemente en este modo (nunca pasa al modo de 64 bits).

Más recientemente, es típico ejecutar un sistema operativo de 64 bits, que conoce los modos y que pondrá a la CPU en modo de 32 bits cuando el usuario inicia un proceso de 32 bits (que todavía es muy común: hasta muy recientemente mi navegador todavía era de 32 bits).

Todos los detalles y la terminología adecuada para los modos se pueden encontrar en la respuesta de Fuz, que es realmente la que debes leer.


Una CPU x86 moderna tiene tres modos de operación principales (esta descripción se simplifica):

  • En modo real, la CPU ejecuta código de 16 bits con paginación y segmentación desactivadas. Las direcciones de memoria en su código se refieren a las direcciones fisonómicas, el contenido de los registros de segmentos se desplaza y se agrega a la dirección para formar una dirección efectiva.
  • En modo protegido , la CPU ejecuta código de 16 o 32 bits dependiendo del selector de segmento en el registro CS (segmento de código). La segmentación está habilitada, la paginación puede (y normalmente está) habilitada. Los programas pueden cambiar entre 16 bit y 32 bit code saltando a un segmento apropiado. La CPU puede ingresar al modo virtual del submodelo 8086 para emular el modo real para procesos individuales desde dentro de un sistema operativo en modo protegido.
  • En modo largo, la CPU ejecuta código de 64 bits. La segmentación está en su mayoría desactivada, la paginación está habilitada. La CPU puede ingresar al modo de compatibilidad submodo para ejecutar código de modo protegido de 16 y 32 bits desde un sistema operativo escrito para modo largo. El modo de compatibilidad se ingresa dando saltos a un selector CS con los bits apropiados establecidos. El modo Virtual 8086 no está disponible.

Ahora, ¿cuál es la diferencia entre el modo de 16 bits, 32 bits y 64 bits?

Los modos de 16 y 32 bits son básicamente lo mismo, excepto por las siguientes diferencias:

  • En el modo de 16 bits, la dirección predeterminada y el ancho del operando es de 16 bits. Puede cambiarlos a 32 bits usando los prefijos 0x67 y 0x66. En el modo de 32 bits, es al revés.
  • En el modo de 16 bits, el puntero de la instrucción se trunca a 16 bits, saltando a direcciones superiores a 65536 puede dar lugar a resultados extraños.
  • AVX y cualquier instrucción codificada VEX no están disponibles en el modo de 16 bits.
  • El modo de 16 bits tiene menos modos de direccionamiento que el modo de 32 bits, aunque es posible cambiar a un modo de direccionamiento de 32 bits si surge la necesidad.

Ahora, el modo de 64 bits es algo diferente. La mayoría de las instrucciones se comportan exactamente como en el modo de 32 bits con las siguientes diferencias:

  • Hay ocho registros adicionales llamados r8, r9, ..., r15. Cada registro se puede usar como un byte, palabra, dword o registro qword. La familia de prefijos REX (0x40 a 0x4f) codifica si un operando se refiere a un registro antiguo o nuevo. Ocho registros adicionales SSE registran xmm8, xmm9, ..., xmm15 también están disponibles.
  • solo puede presionar / explotar cantidades de 64 y 16 bits (aunque no debería hacer lo último), las cantidades de 32 bits no se pueden presionar.
  • Las instrucciones de inc y dec solo byte no están disponibles, su espacio de instrucción ha sido reutilizado para los prefijos de REX. Los inc y dec dos bytes todavía están disponibles, por lo que inc reg y dec reg aún se pueden codificar.
  • existe un nuevo modo de direccionamiento relativo de puntero de instrucción.
  • El ancho de la dirección predeterminada es de 64 bits, se puede seleccionar un ancho de dirección de 32 bits a través del prefijo 0x67. El direccionamiento de 16 bits no está disponible.
  • El ancho del operando predeterminado es de 32 bits. Se puede seleccionar un ancho de 16 bits a través del prefijo 0x66, se puede seleccionar un ancho de 64 bits a través de un prefijo REX apropiado independientemente de los registros que use.
  • No es posible usar AH, BH, CH y DH en una instrucción que requiera un prefijo REX.
  • escribir en la parte baja de un registro de 64 bits borra los 32 bits superiores.
  • como la segmentación no es funcional, las anulaciones de segmentos no están disponibles, excepto las anulaciones fs y gs (0x64, 0x65) que sirven para admitir el almacenamiento local de subprocesos (TLS).
  • Además, muchas instrucciones que se ocupan específicamente de la segmentación no están disponibles. Estos son: push/pop seg (excepto push/pop fs/gs ), arpl , call far (solo la codificación 0xff es válida), les , lds , jmp far (solo la codificación 0xff es válida),
  • las instrucciones que se ocupan de la aritmética decimal no están disponibles, estas son: daa , das , aaa , aas , aam , aad ,
  • Además, las siguientes instrucciones no están disponibles: bound (poco utilizado), pusha / popa (no es útil con los registros adicionales), salc (no documentado),
  • el alias de instrucción 0x82 para 0x80 no es válido.
  • en las primeras CPU amd64, lahf y sahf no están disponibles.

¡Y eso es básicamente todo!