2008-09-24 10 views
6

Decidí enseñarme el lenguaje ensamblador.¿Por qué no puedo cambiar el valor de un registro de segmento? (MASM)

Me he dado 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é ofrece?

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

+2

¿Cuál es el error? – Blorgbeard

+0

¿Bajo un sistema operativo o independiente? 16 modo protegido real o de 32 bits? ¿Qué código no compiló? Ejemplo mínimo de 16 bits con efectos observables: https://github.com/cirosantilli/x86-bare-metal-examples/blob/d4aae6183b98564819107b44a77641979c35d2c3/segment_registers.S –

Respuesta

8

Dijiste que estabas interesado en saber por qué, así que:

En modo real, un segmento es una "ventana" a 64 K de 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 la 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 debe señalarse que la arquitectura permite montones de segmentos. Pero yo sepa, cuando se trata de los sistemas operativos de la corriente principal x86, registros de segmentos sirven sólo unos pocos propósitos:

  • Los mecanismos de seguridad, tales como el mantenimiento de los procesos del espacio de usuario de dañar a otra o el sistema operativo
  • tratar con múltiples/procesadores multi-core
  • Almacenamiento local de subprocesos: como optimización, algunos sistemas operativos (incluidos Linux y Windows) usan registros de segmento 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 desperdiciar 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á.

Aparte de un segmento por subproceso para TLS, en realidad solo se utilizan unos pocos segmentos (multiplicado por el número de procesadores) y solo por el sistema operativo. Los programas de aplicación pueden completamente ignorar 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.

+1

¿Está seguro de que no puede cargar un registro de segmento con un valor inmediato en x86? Estoy mirando Intel Architectures Software Developer Manual (325462, Volumenes combinados) y en la página 1002 se habla de una instrucción MOV con un código de operación de 0x8E, que aparentemente mueve un 'r/m16' en un registro de segmento. – amn

2

¿Está escribiendo ejecutables de Windows?

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

Reference:

modelo de memoria también es drásticamente diferente de los viejos días del mundo de 16 bits. Debajo de Win32, no necesitamos preocuparse más por el modelo de memoria o el segmento . Solo hay un modelo de memoria : modelo de memoria plana. No hay más segmentos 64K. La memoria es un espacio continuo grande de 4 GB. Eso también significa que no tiene para jugar con registros de segmentos. Usted puede usar cualquier registro de segmento a dirección cualquier punto en el espacio de memoria. Eso es una GRAN ayuda para los programadores. Esto es lo que hace que el montaje de Win32 programación tan fácil como C.

+3

Eso está claro * incorrecto *. Varios registros de segmentos se utilizan para el almacenamiento local de subprocesos y el manejo de excepciones. –

+0

I (¿obviamente?) Significaba, "utilizado para su propósito original, por programas de espacio de usuario". OP se refería a la documentación desactualizada. – Blorgbeard

Cuestiones relacionadas