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

  1. 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.

  1. 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

  1. Declaració de Dades:

    • led_on i led_off són variables que contenen els valors per encendre i apagar el LED, respectivament.
  2. Secció de Codi:

    • _start: Punt d'entrada del programa.
    • mov al, [led_on]: Carrega el valor per encendre el LED al registre AL.
    • out 0x60, al: Escriu el valor del registre AL al port 0x60.
    • call delay: Crida a la subrutina de retard.
    • mov al, [led_off]: Carrega el valor per apagar el LED al registre AL.
    • out 0x60, al: Escriu el valor del registre AL al port 0x60.
    • mov eax, 1 i int 0x80: Finalitza el programa amb una crida al sistema.
  3. 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 i OUT: Recorda que IN llegeix dades d'un port i OUT 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.

© Copyright 2024. Tots els drets reservats