2011-05-29 35 views
7

Estoy buscando una breve descripción del uso de un ensamblador en la producción de código de máquina.¿Cómo funciona un ensamblador?

Así que sé que el ensamblaje es una traducción 1: 1 del código de máquina. Pero me confundo sobre el código objeto y los enlazadores y cómo se colocan en él.

No necesito una respuesta compleja que un simple uno hará finas Tanto un ensamblador y un compilador traduce archivos de origen

+3

En realidad no necesariamente 1: 1 –

Respuesta

11

en archivos de objeto.

Los archivos de objeto son efectivamente un paso intermedio antes de la salida ejecutable final (generada por el enlazador).

El vinculador toma los archivos de objeto y las bibliotecas especificadas (que son paquetes de archivos de objeto) y resuelve los registros de reubicación (o 'corrección').

Estos registros de reubicación se realizan cuando el compilador/ensamblador no conoce la dirección de una función o variable utilizada en el código fuente, y genera una referencia para ello por nombre, que puede ser resuelta por el vinculador.

Por ejemplo, supongamos que desea un programa para imprimir un mensaje a la pantalla, separado en dos archivos de origen, y que desea ensamblarlos por separado y unirlas (ejemplo usando Linux x86-64 llamadas al sistema) -

main.asm:

bits 64 
section .text 
extern do_message 
global _start 
_start: 
    call do_message 
    mov rax, 1 
    int 0x80 

message.asm:

bits 64 
section .text 
global do_message 
do_message: 
    mov rdi, message 
    mov rcx, dword -1 
    xor rax, rax 
    repnz scasb 
    sub rdi, message 
    mov rax, 4 
    mov rbx, 1 
    mov rcx, message 
    mov rdx, rdi 
    int 0x80 
    ret 

section .data 
message: db "hello world",10,0 

Si el montaje de estos y buscar a la salida del fichero objeto de main.asm (por ejemplo, objdump -d main.o), se le no Por ejemplo, 'call do_message' tiene una dirección de 00 00 00 00, que no es válida.

0000000000000000 <_start>: 
    0: e8 00 00 00 00   callq 5 <_start+0x5> 
    5: 48 c7 c0 01 00 00 00 mov $0x1,%rax 
    c: cd 80     int $0x80 

embargo, un registro de reubicación se hace para los 4 bytes de la dirección:

$ objdump -r main.o 
main.o:  file format elf64-x86-64 
RELOCATION RECORDS FOR [.text]: 
OFFSET   TYPE    VALUE 
0000000000000001 R_X86_64_PC32  do_message+0xfffffffffffffffc 
000000000000000d R_X86_64_32  .data 

el desplazamiento es '1' y el tipo es 'R_X86_64_PC32' que le dice al enlazador para resolver esta referencia y coloque la dirección resuelta en el desplazamiento especificado.

Cuando se vincula el programa final con 'ld -o programa main.o message.o', las deslocalizaciones se resuelven, y si no se resuelve nada, se queda con un ejecutable.

Cuando estamos objdump -d 'el ejecutable, podemos ver la dirección resuelta:

00000000004000f0 <_start>: 
    4000f0: e8 0b 00 00 00   callq 400100 <do_message> 
    4000f5: 48 c7 c0 01 00 00 00 mov $0x1,%rax 
    4000fc: cd 80     int $0x80 

El mismo tipo de reubicaciones se utilizan para las variables, así como funciones. El mismo proceso ocurre cuando vincula su programa con múltiples bibliotecas grandes, como libc - usted define una función llamada 'main' a la cual libc tiene una referencia externa - entonces libc se inicia antes de su programa y llama a su función 'main' cuando ejecutas el ejecutable

+0

asm -> objeto -> vinculación ... buen ejemplo. –

+0

¿podría explicar por qué el desplazamiento en el archivo objeto es uno y cómo se calcula? Lo siento si es una pregunta estúpida. – gavlaaaaaaaa

+1

@gavlaaaaaaaa: el desplazamiento de la referencia de reubicación do_message en main.o es 1 porque el código comienza en 0, y el desplazamiento 0 es el código de operación 'e8' que es la instrucción 'callq', el desplazamiento 1 es el inicio de los siguientes 32 -bit value que es el operando para la instrucción 'callq'. – matja

1

explicación simple:

Una vez que el lenguaje ensamblador se ensambla en código objeto, el enlazador se utiliza para convertir el código objeto en un archivo ejecutable de comandos que el ordenador puede entender y ejecutar.El código máquina generado puede ser interpretado por el controlador de la CPU.

Cuestiones relacionadas