Lenguaje ensamblador - Sintaxis básica

Este capítulo presenta la estructura básica, las reglas de sintaxis y las normas de escritura de los programas en ensamblador NASM, para ayudarte a comprender el esqueleto del código ensamblador.


Estructura básica de un programa ensamblador

Un programa ensamblador NASM completo generalmente consta de las siguientes partes:

Ejemplo

; Ruta del archivo: structure.asm
; Ejemplo de estructura básica de un programa NASM

section .data                       ; Sección de datos: almacena datos inicializados
    ; Aquí se definen variables y constantes
    msg db 'Hello, EJEMPLO!', 0xA
    len equ $ - msg

section .bss                        ; Sección BSS: almacena datos no inicializados
    ; Aquí se reserva espacio en memoria
    buffer resb 64                  ; Reservar un búfer de 64 bytes

section .text                       ; Sección de código: almacena instrucciones ejecutables
    global _start

_start:
    ; Aquí se escribe la lógica del programa
    mov eax, 4
    mov ebx, 1
    mov ecx, msg
    mov edx, len
    int 0x80

    mov eax, 1
    mov ebx, 0
    int 0x80
Segmento (Section)PropósitoCaracterísticas
.dataAlmacena variables globales y constantes inicializadasEl tamaño y el contenido se determinan en tiempo de compilación y se guardan en el archivo ejecutable
.bssAlmacena variables globales no inicializadasSolo asigna espacio en tiempo de ejecución y no ocupa espacio en el archivo ejecutable
.textAlmacena instrucciones de máquina ejecutablesDe solo lectura, contiene todo el código lógico del programa

Se necesitan al menos.textsegmentos para formar un programa ensamblador válido. Si no hay datos, se pueden omitir.datay.bsslos segmentos.


Formato de las sentencias en ensamblador

El formato general de cada sentencia en ensamblador es:

[标签:]   指令助记符   [操作数1 [, 操作数2 [, 操作数3]]]   [; 注释]

Descripción de cada parte:

Parte¿Es obligatorio?Descripción
Etiqueta (Label)OpcionalUn nombre simbólico que representa una dirección de memoria y termina con dos puntos
Mnemónico de instrucciónObligatorioComo mov, add, sub, etc., le indica a la CPU qué debe hacer
OperandosOpcional (algunas instrucciones no tienen operandos)El objeto de datos sobre el que opera la instrucción; puede ser un registro, una dirección de memoria o un valor inmediato
ComentarioOpcionalComienza con un punto y coma y se extiende hasta el final de la línea

Ejemplo

; Ejemplos de varios formatos de sentencias

; Solo la instrucción, sin operandos
ret                     ; Retorno de subrutina

; Instrucción + un solo operando
push eax                ; Empuja el valor de eax a la pila
inc ecx                 ; Incrementa ecx en 1

; Instrucción + dos operandos (el más común)
mov eax, 42             ; Copia 42 al registro eax
add ebx, ecx            ; ebx = ebx + ecx

; Con etiqueta
loop_start:             ; Etiqueta: marca la posición de inicio del bucle
    dec ecx             ; Decrementa ecx en 1
    jnz loop_start      ; Si ecx no es 0, salta de regreso a loop_start

Normas para comentarios

NASM utilizael punto y coma (;)para indicar comentarios; el contenido desde el punto y coma hasta el final de la línea será ignorado por el ensamblador.

Ejemplo

; Comentario de línea completa: explica el propósito del siguiente bloque de código
; Calcula la suma de dos números y muestra el resultado

mov eax, 10             ; Comentario en línea: coloca 10 en eax
add eax, 20             ; Comentario en línea: suma 20 a eax, ahora eax = 30

Los comentarios son extremadamente importantes en el código ensamblador. Sin comentarios, el código ensamblador puede resultar incomprensible incluso para su propio autor después de unas semanas. Adquiere el hábito de escribir comentarios en cada instrucción.


Reglas de nomenclatura de identificadores

Los identificadores (etiquetas, nombres de variables, nombres de constantes, etc.) deben seguir las siguientes reglas:

ReglaDescripción
Caracteres permitidosLetras, dígitos, guion bajo _, punto ., signo de interrogación ?, @, $, #, etc.
Carácter inicialDebe comenzar con una letra, guion bajo, punto o signo de interrogación; no puede comenzar con un dígito
Mayúsculas y minúsculasDistingue entre mayúsculas y minúsculas de forma predeterminada (se puede modificar mediante opciones de compilación)
Palabras reservadasNo pueden coincidir con mnemónicos de instrucciones, nombres de registros ni palabras clave de NASM

Ejemplo

; Identificadores válidos
my_variable:            ; Comienza con letra + guion bajo
.loop_start:            ; Comienza con punto (etiqueta local)
?error_handler:         ; Comienza con signo de interrogación
counter2:               ; Letra + dígito

; Identificadores no válidos (solo como referencia, no los uses)
; 1st_value: ; Error: no puede comenzar con un dígito
; mov: ; Error: mov es una palabra reservada
; my-variable: ; Error: el guion no es un carácter válido

Directivas

Las directivasson comandos dirigidos al ensamblador, no instrucciones para la CPU; se utilizan para controlar el proceso de ensamblado y definir estructuras de datos.

DirectivaPropósitoEjemplo
dbDefine un byte (1 byte)byte_val db 0x55
dwDefine una palabra (2 bytes)word_val dw 0x1234
ddDefine una doble palabra (4 bytes)dword_val dd 0x12345678
equDefine una constanteMAX_SIZE equ 256
resbReserva espacio en bytesbuffer resb 128
reswReserva espacio en palabraswbuf resw 64
resdReserva espacio en dobles palabrasdbuf resd 32
%defineConstante definida con macro%define COUNT 10

Normas de mayúsculas y minúsculas

NASM, por defecto, en cuanto a etiquetas e identificadores,distingue entre mayúsculas y minúsculas.:

Ejemplo

; Ejemplo de sensibilidad a mayúsculas y minúsculas

section .data
    msg db 'EJEMPLO', 0       ; Define la variable msg

section .text
    global _start

_start:
    mov eax, MSG             ; Error: MSG y msg son diferentes (a menos que se active ignorar mayúsculas y minúsculas)
    mov eax, msg             ; Correcto: msg coincide exactamente con la definición

    MOV EAX, 42              ; Sintaxis correcta: los mnemónicos de instrucciones no distinguen entre mayúsculas y minúsculas
    mov eax, 42              ; Escritura recomendada: usar minúsculas para una mejor legibilidad

Los mnemónicos de instrucciones y los nombres de registros no distinguen entre mayúsculas y minúsculas (MOV、Mov、movel efecto es el mismo), pero el estilo recomendado es usar minúsculas de manera uniforme.


Representación de valores numéricos

NASM admite la representación de valores en múltiples bases:

Ejemplo

; Representación de diferentes bases en NASM

mov eax, 42             ; Decimal: escribir el número directamente
mov eax, 0x2A           ; Hexadecimal: prefijo 0x (notación recomendada)
mov eax, 2Ah            ; Hexadecimal: sufijo h
mov eax, 0o52           ; Octal: prefijo 0o
mov eax, 52o            ; Octal: sufijo o
mov eax, 101010b        ; Binario: sufijo b
mov eax, 0b101010       ; Binario: prefijo 0b

Se recomienda utilizar0xel prefijo para representar hexadecimal (como0x2A), de esta manera no es fácil confundirlo con etiquetas.


Un ejemplo completo de sintaxis

El siguiente programa integra los elementos de sintaxis explicados anteriormente, calcula la suma del 1 al 10 y la muestra:

Ejemplo

; Ruta del archivo: sum.asm
; Calcula 1+2+...+10 y muestra el carácter del resultado

section .data
    result db 0                 ; Almacena el resultado del cálculo (1 byte)
    newline db 0xA              ; Carácter de nueva línea

section .text
    global _start

_start:
    ; Inicializa registros y variables
    mov ecx, 10                 ; Contador del bucle: comienza la cuenta regresiva desde 10
    mov eax, 0                  ; eax almacena la suma acumulada, inicialmente 0

sum_loop:                       ; Etiqueta de inicio del bucle
    add eax, ecx                ; eax = eax + ecx
    dec ecx                     ; Decrementa ecx en 1
    jnz sum_loop                ; Si ecx != 0, continúa el bucle

    ; En este punto eax = 55 (10+9+...+1)
    add eax, '0'                ; Convierte el número en un carácter ASCII ('0'=48, 55+48=103='g', incorrecto)
                                ; Una demostración real requiere una conversión más compleja; ver capítulos posteriores

    ; Aquí solo se muestra result (demostración simplificada)
    mov [result], al            ; Almacena el resultado acumulado en result

    ; Sale del programa
    mov eax, 1
    mov ebx, 0
    int 0x80

Nota: en el ejemplo anterior, sumar directamente '0' solo es correcto cuando el número está en el rango de 0-9. La conversión de números de dos o más dígitos se explicará en detalle en capítulos posteriores.

Otras extensiones