2011-01-15 23 views
7

Me preguntaba acerca de lo siguiente. Me he dado cuenta cuando escribo el lenguaje ensamblador que IA32 está diseñado de tal manera que promueve el uso de saltos relativos, es decir, salta una cantidad de desplazamiento de bytes vs el uso de saltos absolutos, es decir, cambia eip a una dirección específica en la memoria. ¿Cuál es la lógica detrás de esto?Jmp relativo vs Absoluto en la Asamblea

+0

Tenga en cuenta que en la mayoría de los casos utiliza direcciones que están actualmente disponibles, y no cualquier cosa que elija. – ruslik

Respuesta

14

La mayoría de los saltos se realizan a objetivos no muy lejanos de las instrucciones de salto. Dado que se proporcionan instrucciones de salto que toman un valor de 16 bits con signo, pueden ser menos bytes de los necesarios para un salto absoluto (generalmente 4 bytes más la instrucción en sí).

Una pequeña ventaja adicional de las ramas relativas es que no necesitan ser arregladas en el enlazador, o, para el caso, pasan por la indirección adicional necesaria en PIC (código independiente de posición).

8

Los saltos relativos hacen posible que los compiladores generen código relocable, lo que significa que el código se ejecutará en cualquier lugar de la memoria; no está vinculado a una ubicación fija. Este es el concepto crítico detrás de las bibliotecas: puede escribir el código una vez y compilarlo en un archivo objeto reubicable que puede vincularse tal cual en cualquier programa. El vinculador debe asignar direcciones absolutas solo para las funciones que son accesibles externamente (para que su propio código pueda encontrarlas); todos los saltos "internos" son relativos y no necesitan cambiar de un ejecutable a otro.

Merece la pena escribir un código en un lenguaje de alto nivel como C, haga que el compilador genere código de ensamblado (marque la opción -S en gcc), y luego lea el resultado del ensamblaje. Preste especial atención a los condicionales y bucles, como if, for y while, y verá que todos generan saltos relativos.

Aquí está un ejemplo artificial utilizando instrucciones de montaje ficticios:

// Sample C code   Address Assembly Code  Comments 

if (x < 10) {   0000  CMP x,#10   ; Compare x to 10 
    do_true_stuff();  0003  JGE +7    ; Skip 7 bytes to 000A if x>=10 
} else {     0005  SUB do_true_stuff ; x<10 
    do_false_stuff();  0008  JMP +5    ; Skip 5 bytes to 000D 
}      000A  SUB do_false_stuff ; else-branch (x>=10) 
do_more_stuff();   000D  SUB do_more_stuff ; Finished if/else 

Aquí, el compilador genera saltos relativos (JGE y JMP) para saltar sobre la rama un-ejecutado del bloque if-else. Estos saltos funcionarán sin importar en qué lugar de la memoria el vinculador ponga el código. Si fueran saltos absolutos, el vinculador necesitaría volver a calcular las direcciones cada vez que vinculara el código.

Incluso encontrará que muchas llamadas de función generarán saltos relativos, particularmente si las funciones tienen un alcance en un solo archivo. Esto no solo acelera el proceso de vinculación, sino que también hace que el código de ejecución sea más pequeño y más eficiente. Esto se debe a que las direcciones relativas están normalmente limitadas a un rango mucho más pequeño que las direcciones absolutas, lo que significa que pueden representarse en menos bytes.

Espero que ayude!

Cuestiones relacionadas