Pregunta

El artículo de Wikipedia sobre la Asamblea X86 dice que "el programador no puede acceder directamente al registro de IP".

Directamente significa con instrucciones como mov y agregar.

¿Por que no? Cuál es la razón detrás de esto? ¿Cuáles son las restricciones técnicas?

¿Fue útil?

Solución

No puede acceder a él directamente porque no hay un caso de uso legítimo. Tener algún cambio de instrucción arbitraria eip Daría una predicción de ramas muy difícil, y probablemente abriría una gran cantidad de problemas de seguridad.

Puedes editar eip usando jmp, call o ret. Simplemente no puedes leer directamente o escribir a eip Usando operaciones normales

Ajuste eip a un registro es tan simple como jmp eax. TAMBIÉN PUEDES HACER push eax; ret, que empuja el valor de eax a la pila y luego regresa (es decir, aparece y salta). La tercera opción es call eax que hace una llamada a la dirección en EAX.

La lectura se puede hacer así:

call get_eip
  get_eip:
pop eax ; eax now contains the address of this instruction

Otros consejos

Ese habría sido un diseño posible para X86. El brazo hace Exponga su contador de programa para leer/escribir como R15. Sin embargo, eso es inusual.

Permite un prólogo/epílogo de funciones muy compactos, junto con la capacidad de presionar o explotar múltiples registros con una sola instrucción: push {r5, lr} en la entrada y pop {r5, pc} regresar. (Presentar el valor guardado del registro de enlaces en el contador del programa).

Sin embargo, hace que las implementaciones de ARM de alto perfil / fuera de orden sean menos convenientes, y se eliminó para AARCH64.


Asi que es posible, pero usa uno de los registros. ARM de 32 bits tiene 16 registros enteros (incluida la PC), por lo que un número de registro toma 4 bits para codificar en el código de la máquina ARM. Otro registro casi siempre está atado como el puntero de la pila, por lo que ARM tiene 14 registros enteros de uso general. (LR se puede guardar en la pila, por lo que puede ser y se usa como un registro de propósito general dentro de los cuerpos de funciones).

La mayor parte del X86 moderno se hereda desde 8086. Fue diseñado con una codificación de instrucciones de longitud variable bastante compacta, y solo 8 registros, que requieren solo 3 bits para cada registro SRC y DST en el código de la máquina.

En el 8086 original, no eran muy de propósito general, y el direccionamiento relativo de SP no es posible en el modo de 16 bits, por lo que esencialmente 2 registros (SP y BP) están vinculados a las cosas de la pila. Esto deja solo 6 registros de propósito algo general, y que uno de ellos sea la PC en lugar de uso general sería una gran reducción en los registros disponibles, aumentando en gran medida la cantidad de derrame/recarga en el código típico.


AMD64 agregó R8-R15 y el modo de direccionamiento relativo a RIP. lea rsi, [rip+whatever], y modos de direccionamiento relativo a RIP para acceso directo a datos y constantes estáticas, es todo lo que necesita para un código eficiente independiente de la posición. Las instrucciones indirectas de JMP son totalmente suficientes para escribir para RIP.

Realmente no hay nada que obtener al permitir que se usen instrucciones arbitrarias para leer o escribir la PC, ya que siempre puede hacer lo mismo con un registro entero y un salto indirecto. Sería una desventaja casi pura que el R15 de X86-64 sea lo mismo que RIP, especialmente para el rendimiento de la arquitectura como objetivo compilador. (Las cosas extrañas escritas a mano de ASM ya eran algo poco común para el 2000, cuando se diseñó AMD64).

Por lo tanto, AMD64 es realmente la primera vez que X86 podría haber ganado plausiblemente un mostrador de programa completamente expuesto como el brazo, pero había muchas buenas razones para no hacer eso.

Creo que significaban que no se puede acceder al registro de IP directamente de la misma manera que se accede a los otros registros. Los programadores definitivamente pueden escribir en IP, por ejemplo, emitiendo una instrucción de salto.

jmp establecerá el EIP Registrarse.

Este código establecerá EIP en 00401000:

mov eax, 00401000
jmp eax ;set Eip to 00401000

Y por conseguir EIP

call GetEIP
.
.
GetEIP:
mov eax, [esp]
ret
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top