En aquest tema, aprendrem a escriure un bootloader simple en llenguatge Assembly. Un bootloader és un programa petit que s'executa quan l'ordinador s'encén i carrega el sistema operatiu a la memòria. Aquest exercici ens ajudarà a comprendre millor com funciona el procés d'arrencada d'un ordinador i com interactuar directament amb el maquinari.
Objectius
- Entendre el concepte de bootloader.
- Escriure un bootloader simple en Assembly.
- Carregar i executar el bootloader en un entorn d'emulació.
Requisits Previs
- Coneixements bàsics de llenguatge Assembly.
- Entorn de desenvolupament configurat per a Assembly.
- Familiaritat amb eines d'emulació com QEMU o Bochs.
Conceptes Clau
Què és un Bootloader?
Un bootloader és un programa que s'executa quan l'ordinador s'encén. La seva funció principal és carregar el sistema operatiu a la memòria i transferir-li el control. Els bootloaders es troben en el primer sector del disc dur, conegut com el Master Boot Record (MBR).
Estructura del Bootloader
Un bootloader simple en Assembly ha de complir amb els següents requisits:
- Ha de ser de 512 bytes o menys.
- Ha de tenir una signatura específica (0x55AA) als últims dos bytes per ser reconegut pel BIOS.
Escriure el Bootloader
Codi del Bootloader
A continuació, es mostra un exemple de codi Assembly per a un bootloader simple que mostra un missatge a la pantalla:
[BITS 16] ; Indica que el codi és de 16 bits [ORG 0x7C00] ; Indica l'adreça d'origen del codi start: mov si, msg ; Carrega l'adreça del missatge a SI call print_string hang: jmp hang ; Bucle infinit per mantenir el bootloader en execució print_string: mov ah, 0x0E ; Funció de BIOS per imprimir caràcters .next_char: lodsb ; Carrega el següent byte de la cadena a AL cmp al, 0 ; Comprova si és el final de la cadena je .done ; Si és zero, finalitza int 0x10 ; Crida a la interrupció de BIOS per imprimir el caràcter jmp .next_char ; Continua amb el següent caràcter .done: ret ; Retorna al punt de crida msg db 'Hello, World!', 0 ; Missatge a imprimir times 510-($-$$) db 0 ; Omple amb zeros fins a 510 bytes dw 0xAA55 ; Signatura de boot (0x55AA)
Explicació del Codi
[BITS 16]
i[ORG 0x7C00]
: Indiquen que el codi és de 16 bits i que s'executarà a l'adreça 0x7C00, on el BIOS carrega el bootloader.start:
: Etiqueta d'inici del codi.mov si, msg
: Carrega l'adreça del missatge a SI.call print_string
: Crida a la subrutina per imprimir la cadena.hang:
: Bucle infinit per mantenir el bootloader en execució.print_string:
: Subrutina per imprimir una cadena de caràcters.msg db 'Hello, World!', 0
: Defineix el missatge a imprimir.times 510-($-$$) db 0
: Omple amb zeros fins a 510 bytes.dw 0xAA55
: Signatura de boot (0x55AA).
Carregar i Executar el Bootloader
Utilitzant QEMU
QEMU és una eina d'emulació que ens permet provar el nostre bootloader sense necessitat de maquinari físic.
- Guarda el codi Assembly en un fitxer anomenat
bootloader.asm
. - Assembla el codi utilitzant NASM:
nasm -f bin -o bootloader.bin bootloader.asm
- Executa el bootloader utilitzant QEMU:
qemu-system-x86_64 -drive format=raw,file=bootloader.bin
Utilitzant Bochs
Bochs és una altra eina d'emulació que es pot utilitzar per provar el bootloader.
- Guarda el codi Assembly en un fitxer anomenat
bootloader.asm
. - Assembla el codi utilitzant NASM:
nasm -f bin -o bootloader.bin bootloader.asm
- Configura Bochs per carregar el fitxer
bootloader.bin
i executa'l.
Exercicis Pràctics
Exercici 1: Modificar el Missatge
Modifica el codi del bootloader per mostrar un missatge diferent a la pantalla.
Exercici 2: Afegeix una Segona Cadena
Modifica el codi per imprimir una segona cadena després de la primera.
Exercici 3: Interacció amb l'Usuari
Modifica el codi per esperar una tecla de l'usuari abans de mostrar el missatge.
Solucions
Solució a l'Exercici 1
Solució a l'Exercici 2
start: mov si, msg1 call print_string mov si, msg2 call print_string jmp hang msg1 db 'Hello, World!', 0 msg2 db 'Welcome to Assembly!', 0
Solució a l'Exercici 3
start: call wait_for_key mov si, msg call print_string jmp hang wait_for_key: mov ah, 0 int 0x16 ; Espera una tecla ret msg db 'Hello, World!', 0
Conclusió
En aquest tema, hem après a escriure un bootloader simple en llenguatge Assembly, carregar-lo i executar-lo en un entorn d'emulació. Hem explorat conceptes clau com la signatura de boot i la interacció amb el BIOS. Els exercicis pràctics ens han ajudat a reforçar els conceptes apresos i a experimentar amb modificacions del codi. En el proper tema, aprofundirem en la creació d'un nucli bàsic de sistema operatiu.
Curs de Programació en Assembly
Mòdul 1: Introducció al Llenguatge Assembly
- Què és el Llenguatge Assembly?
- Història i Evolució de l'Assembly
- Conceptes Bàsics i Terminologia
- Configuració de l'Entorn de Desenvolupament
Mòdul 2: Fonaments del Llenguatge Assembly
- Comprensió de la CPU i la Memòria
- Registres i les Seves Funcions
- Sintaxi i Estructura Bàsiques
- Escrivint el Teu Primer Programa en Assembly
Mòdul 3: Representació de Dades i Instruccions
- Sistemes Binari i Hexadecimal
- Tipus de Dades i Mides
- Instruccions Aritmètiques
- Instruccions Lògiques
Mòdul 4: Flux de Control
Mòdul 5: Conceptes Avançats d'Assembly
- Interrupcions i Crides de Sistema
- Macros i Assembly Condicional
- Assembly Inline en Llenguatges d'Alt Nivell
- Optimització del Codi Assembly
Mòdul 6: Assembly per a Diferents Arquitectures
Mòdul 7: Aplicacions Pràctiques i Projectes
- Escrivint un Bootloader Simple
- Creant un Nucli Bàsic de Sistema Operatiu
- Interfície amb el Maquinari
- Depuració i Perfilat del Codi Assembly