En aquest tema, explorarem com el llenguatge Assembly pot ser utilitzat per interactuar directament amb el maquinari. Aquesta capacitat és una de les raons per les quals Assembly és tan poderós i útil en aplicacions de baix nivell, com ara sistemes operatius, controladors de dispositius i aplicacions embegudes.
Objectius del Tema
- Comprendre els conceptes bàsics d'interfície amb el maquinari.
- Aprendre a utilitzar ports d'entrada/sortida (I/O) per comunicar-se amb dispositius externs.
- Escriure programes Assembly que interactuïn amb el maquinari.
Conceptes Bàsics d'Interfície amb el Maquinari
- Ports d'Entrada/Sortida (I/O)
Els ports d'I/O són adreces de memòria especials que permeten la comunicació entre la CPU i els dispositius perifèrics. Hi ha dos tipus principals de ports d'I/O:
- Ports d'I/O de memòria-mapejada: Aquests ports utilitzen la mateixa adreça de memòria que la RAM.
- Ports d'I/O d'espai d'adreça separat: Aquests ports tenen un espai d'adreça separat de la memòria principal.
- Instruccions d'I/O
Les instruccions d'I/O permeten llegir i escriure dades als ports d'I/O. Les instruccions més comunes són:
IN
: Llegeix dades d'un port d'I/O.OUT
: Escriu dades a un port d'I/O.
Exemple Pràctic: Control d'un LED
Configuració del Maquinari
Suposem que tenim un LED connectat al port d'I/O 0x60. Volem escriure un programa Assembly que encengui i apagui el LED.
Codi Assembly
section .data led_on db 1 ; Valor per encendre el LED led_off db 0 ; Valor per apagar el LED section .text global _start _start: ; Encendre el LED mov al, [led_on] ; Carregar el valor per encendre el LED al registre AL out 0x60, al ; Escriure el valor al port 0x60 ; Esperar una estona call delay ; Apagar el LED mov al, [led_off] ; Carregar el valor per apagar el LED al registre AL out 0x60, al ; Escriure el valor al port 0x60 ; Finalitzar el programa mov eax, 1 ; Codi de sortida del sistema int 0x80 ; Crida al sistema per sortir delay: ; Subrutina de retard mov ecx, 1000000 ; Carregar el comptador de retard .loop: loop .loop ; Decrementar ECX fins que sigui zero ret
Explicació del Codi
-
Declaració de Dades:
led_on
iled_off
són variables que contenen els valors per encendre i apagar el LED, respectivament.
-
Secció de Codi:
_start
: Punt d'entrada del programa.mov al, [led_on]
: Carrega el valor per encendre el LED al registreAL
.out 0x60, al
: Escriu el valor del registreAL
al port0x60
.call delay
: Crida a la subrutina de retard.mov al, [led_off]
: Carrega el valor per apagar el LED al registreAL
.out 0x60, al
: Escriu el valor del registreAL
al port0x60
.mov eax, 1
iint 0x80
: Finalitza el programa amb una crida al sistema.
-
Subrutina de Retard:
delay
: Subrutina que crea un retard utilitzant un bucle.
Exercici Pràctic
Enunciat
Escriu un programa Assembly que faci parpellejar un LED connectat al port d'I/O 0x60 amb un interval de 500 ms.
Solució
section .data led_on db 1 led_off db 0 section .text global _start _start: ; Bucle infinit per fer parpellejar el LED .loop: ; Encendre el LED mov al, [led_on] out 0x60, al call delay ; Apagar el LED mov al, [led_off] out 0x60, al call delay jmp .loop delay: ; Subrutina de retard per 500 ms mov ecx, 500000 .loop_delay: loop .loop_delay ret
Explicació de la Solució
- El programa utilitza un bucle infinit per encendre i apagar el LED amb un retard de 500 ms entre cada canvi d'estat.
- La subrutina
delay
ha estat ajustada per proporcionar un retard de 500 ms.
Errors Comuns i Consells
Errors Comuns
- No carregar correctament els valors als registres: Assegura't que els valors per encendre i apagar el LED es carreguin correctament als registres abans d'escriure'ls als ports d'I/O.
- No utilitzar correctament les instruccions
IN
iOUT
: Recorda queIN
llegeix dades d'un port iOUT
escriu dades a un port.
Consells
- Experimenta amb diferents valors de retard: Ajusta el valor del comptador de retard per veure com afecta la velocitat de parpelleig del LED.
- Utilitza comentaris: Afegeix comentaris al teu codi per fer-lo més llegible i comprensible.
Conclusió
En aquest tema, hem après com utilitzar el llenguatge Assembly per interactuar amb el maquinari mitjançant ports d'I/O. Hem escrit un programa pràctic per controlar un LED i hem explorat com ajustar el retard per fer-lo parpellejar. Aquest coneixement és fonamental per a la programació de baix nivell i el desenvolupament de sistemes embeguts. En el proper tema, explorarem com depurar i perfilar el codi Assembly per assegurar-nos que funcioni correctament i de manera eficient.
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