registers lea instruction assembly x86 masm

lea - x86 assembly



¿Por qué no puedo cambiar el valor de un registro de segmento?(MASM) (2)

Decidí enseñarme el lenguaje ensamblador.

Me di cuenta de que mi programa no se compilará si intento cambiar el valor de cualquier registro de segmento.

Cada artículo que he encontrado dice que, de hecho, puedo cambiar el valor de al menos 4 registros de segmentos, entonces, ¿qué da?

En realidad, solo estoy interesado en por qué en este punto, no tengo ningún propósito real al cambiar estas direcciones.


¿Estás escribiendo ejecutables de Windows?

En modo protegido (Win32), los registros de segmento ya no se usan.

Referencia :

El modelo de memoria también es drásticamente diferente de los viejos tiempos del mundo de 16 bits. Con Win32, ya no tenemos que preocuparnos por el modelo de memoria o el segmento. Solo hay un modelo de memoria: modelo de memoria plana. No hay más segmentos de 64K. La memoria es un gran espacio continuo de 4 GB. Eso también significa que no tiene que jugar con registros de segmentos. Puede usar cualquier registro de segmento para abordar cualquier punto en el espacio de memoria. Esa es una GRAN ayuda para los programadores. Esto es lo que hace que la programación en ensamblador de Win32 sea tan fácil como C.


Dijiste que estabas interesado en por qué, entonces:

En modo real, un segmento es una "ventana" de 64K a la memoria física y estas ventanas están espaciadas a 16 bytes de distancia. En el modo protegido, un segmento es una ventana a la memoria física o virtual, cuyo tamaño y ubicación viene determinado por el sistema operativo, y tiene muchas otras propiedades, incluido el nivel de privilegio que debe tener un proceso para acceder a él.

A partir de ahora, todo lo que digo se refiere al modo protegido.

Hay una tabla en la memoria llamada tabla de descriptores globales (GDT), que es donde se guarda la información sobre estos tamaños de ventana y ubicaciones y otras propiedades. También puede haber tablas de descriptores locales por proceso, y funcionan de manera similar, así que solo me concentraré en el GDT.

El valor que carga en un registro de segmento se conoce como selector de segmento . Es un índice en el GDT o LDT, con un poco de información de seguridad adicional. Naturalmente, si un programa intenta cargar un descriptor que está fuera de los límites del GDT, se produce una excepción. Además, si el proceso no tiene suficiente privilegio para acceder al segmento o si algo más no es válido, se produce una excepción.

Cuando ocurre una excepción, el núcleo la maneja. Este tipo de excepción probablemente se clasifique como una falla de segmentación. Entonces el sistema operativo mata tu programa.

Hay una advertencia final: en el conjunto de instrucciones x86, no puede cargar valores inmediatos en registros de segmentos. Debe usar un registro intermedio o un operando de memoria o POP en el registro de segmento.

MOV DS, 160 ;INVALID - won''t assemble MOV AX, 160 ;VALID - assembles, but will probably result in an MOV DS, AX ;exception, and thus the death of your program

Creo que debería señalarse que la arquitectura permite montones de segmentos. Pero AFAIK, cuando se trata de los principales sistemas operativos x86, los registros de segmentos sirven solo para algunos propósitos:

  • Mecanismos de seguridad, como evitar que los procesos espaciales del usuario se dañen entre sí o el sistema operativo
  • Tratar con procesadores múltiples / multi-core
  • Almacenamiento local de subprocesos: como optimización, algunos sistemas operativos (incluidos Linux y Windows) usan registros de segmentos para almacenamiento local de subprocesos (TLS). Como los hilos comparten el mismo espacio de direcciones, es difícil que un hilo "sepa" dónde está su región TLS sin usar una llamada al sistema o perder un registro ... pero como los registros de segmentos son prácticamente inútiles, no hay daño en "desperdiciar" ellos por el bien de TLS rápido. Tenga en cuenta que al configurar esto, un SO puede omitir los registros de segmentos y escribir directamente en los registros de caché de descriptores, que son registros "ocultos" utilizados para almacenar en caché las búsquedas GDT / LDT activadas por referencias a los registros de segmentos, en cuyo caso si lo intenta para leer de los registros de segmentos, no lo verá.

Además de un segmento por subproceso para TLS, en realidad solo se utilizan un puñado de segmentos (multiplicado por el número de procesadores) y solo por el sistema operativo. Los programas de aplicación pueden ignorar por completo los registros de segmentos.

Esto se debe al diseño del sistema operativo, no a limitaciones técnicas. Puede haber sistemas operativos integrados que requieren programas de espacio de usuario para trabajar con los registros de segmentos, aunque no conozco ninguno.