Hola mundo Ensamblador x86
No es tan fácil como parece, o tal vez si …
Este programa en Ensamblador que se analizara, esta escrito en el ensamblador NASM con sintaxis Intel, para un microprocesador de la familia X86 y se ejecutara en el sistema operativo Gnu/Linux. Todo lo anteriormente dicho, es importante especificar debido a que la forma de escribir el programa y ejecutarlo cambiara en mayor o menor medida si alguno de estos aspectos fuese distinto.
SYS_SALIDA equ 1section .data
msg db "Hola, Mundo!!!",0x0a
len equ $ - msg ;longitud de msgsection .text
global _start ;para el linker
_start: ;marca la entrada
mov eax, 4 ;llamada al sistema (sys_write)
mov ebx, 1 ;descripción de archivo (stdout)
mov ecx, msg ;msg a escribir
mov edx, len ;longitud del mensaje
int 0x80 ;llama al sistema de interrupcionesfin: mov eax, SYS_SALIDA ;llamada al sistema (sys_exit)
int 0x80
Las directivas son comandos que interpreta el programa de ensamblado, este programa se encuentra constituido por las directivas que se mencionan a continuación.
Segmentos de memoria
En el lenguaje ensamblador es necesario especificar que instrucciones se guardaran en la memoria correspondiente a los datos y que otros se almacenaran en la memoria de código, para esto se utilizan los segmentos. En NASM los segmentos se especifican mediante la directiva section, de esta forma:
- section .data
Define el grupo de declaraciones inicializadas, ubicadas en el segmento de datos de la memoria principal. - section .text
Define el grupo de instrucciones a ser ejecutadas, ubicadas en el segmento de código de la memoria principal. - section .bss
Define el grupo de declaraciones no inicializadas, ubicadas de forma adyacente al segmento de datos de la memoria principal. bss es una abreviatura de ’block started by simbol’
Etiquetas
Su función es facilitar al programador la tarea de hacer referencia a una dirección de memoria, ya sea del segmento de datos o de código, mediante un símbolo o nombre. De esta manera se tienen dos tipos de etiquetas:
Para hacer referencia a una posición de código dentro del programa.
SYS_SALIDA equ 1section .data
msg db "Hola, Mundo!!!",0x0a
len equ $ - msg ;longitud de msgsection .text
global _start ;para el linker
_start: ;marca la entrada
mov eax, 4 ;llamada al sistema (sys_write)
mov ebx, 1 ;descripción de archivo (stdout)
mov ecx, msg ;msg a escribir
mov edx, len ;longitud del mensaje
int 0x80 ;llama al sistema de interrupcionesfin: mov eax, SYS_SALIDA ;llamada al sistema (sys_exit)
int 0x80
Para hacer referencia a las variables y constantes del programa.
SYS_SALIDA equ 1section .data
msg db "Hola, Mundo!!!",0x0a
len equ $ - msg ;longitud de msgsection .text
global _start ;para el linker
_start: ;marca la entrada
mov eax, 4 ;llamada al sistema (sys_write)
mov ebx, 1 ;descripción de archivo (stdout)
mov ecx, msg ;msg a escribir
mov edx, len ;longitud del mensaje
int 0x80 ;llama al sistema de interrupcionesfin: mov eax, SYS_SALIDA ;llamada al sistema (sys_exit)
int 0x80
La etiqueta _start: dentro del segmento de código es una etiqueta especial y sirve para indicarle al ensamblador donde es que comienza el programa, por lo que es necesaria la directiva global _start para que esta etiqueta presente un alcance externo; es similar a la función que cumple el main en los lenguajes de alto nivel.
Definición de datos
Las directivas usadas para especificar los datos del programa, se declaran mediante:
· Un nombre, el cual sigue las mismas reglas que la etiqueta de una posición de código con la excepción del uso del carácter dos puntos (:).
· Una instrucción de asignación de espacio en memoria, por ejemplo: DB (Define Byte): Se utiliza para asignar un byte (8 bits) de almacenamiento a cada uno de los datos declarados con esta directiva. En la mayoría de los lenguajes de programación de alto nivel, esta misma cantidad de memoria es utilizada para almacenar los tipos de datos char, debido a que los caracteres en su representación decimal solo llegan hasta el 255
· y el valor o valores a almacenar en la memoria separados por comas.
SYS_SALIDA equ 1section .data
msg db "Hola, Mundo!!!",0x0a
len equ $ - msg ;longitud de msgsection .text
global _start ;para el linker
_start: ;marca la entrada
mov eax, 4 ;llamada al sistema (sys_write)
mov ebx, 1 ;descripción de archivo (stdout)
mov ecx, msg ;msg a escribir
mov edx, len ;longitud del mensaje
int 0x80 ;llama al sistema de interrupcionesfin: mov eax, SYS_SALIDA ;llamada al sistema (sys_exit)
int 0x80
En combinación a la declaración de constantes, NASM permite realizar un par de pseudo operaciones para el cálculo de direcciones de memoria mediante dos constantes especiales $ y $$.
$ : Hace referencia a la dirección de memoria actual.
letrero db “texto”
tamanio EQU $- letrero
;al restar la dirección de memoria ubicada al final
;del mensaje “texto” ($) y la dirección de memoria donde este
;mismo comienza mediante su nombre ‘letrero’, la variable
;tamanio almacena la longitud del contenido de la variable
;’letrero’ en bytes (5 bytes)
Interrupciones
En ensamblador para realizar cualquier acción con el hardware , ya sea imprimir en pantalla o leer datos desde el teclado se necesita la intervención del sistema operativo ,al menos en los sistemas modernos asi ocurre, para lograr esto es necesario invocar la acción del sistema con un valor de interrupción el cual variara dependiendo del sistema operativo donde el programa se ejecutara, además de esto los datos que se le pasaran serán distintos, por lo que este ejemplo funciona en el sistema operativo Gnu/Linux, pero no en cualquier otro como por ejemplo Windows.
SYS_SALIDA equ 1section .data
msg db "Hola, Mundo!!!",0x0a
len equ $ - msg ;longitud de msgsection .text
global _start ;para el linker
_start: ;marca la entrada
mov eax, 4 ;llamada al sistema (sys_write)
mov ebx, 1 ;descripción de archivo (stdout)
mov ecx, msg ;msg a escribir
mov edx, len ;longitud del mensaje
int 0x80 ;llama al sistema de interrupcionesfin: mov eax, SYS_SALIDA ;llamada al sistema (sys_exit)
int 0x80
Para finalizar ensamblaremos, ligaremos y ejecutaremos el programa.
nasm -f elf hola_mundo.asm
#crea el archivo hola_mundo.old -m -o elf_i386 hola_mundo hola_mundo.o
#crea el archivo ejecutable hola_mundo./hola_mundo
#ejecuta nuestro programa
Si ha disfrutado de este artículo y siente que ha aprendido algo valioso, por favor compártalo.