Input/Output di testo
Nell'esempio seguente vogliamo coinvolgere alcune funzioni base necessarie in quasi tutti i programmi: l'input da tastiera, l'elaborazione, l'output su video e l'output di errori. Prenderemo in considerazione la trasformazione in maiuscolo di una stringa immessa da tastiera. Utilizzeremo solo syscall e pertanto potremo eseguire il link direttamente con ld. Creeremo le condizioni per generare un errore, nel caso di input nullo, in modo da utilizzare tre descrittori di file: STDIN per l'input, STDOUT per l'output normale, STDERR per l'output d'errore.
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ; upper_1.asm ; Converte in maiuscolo l'input dell'utente. ;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ; compilare con nasm+ld %define STDIN 0 %define STDOUT 1 %define STDERR 2 %define SYSCALL_EXIT 1 %define SYSCALL_READ 3 %define SYSCALL_WRITE 4 %define BUFLEN 256 section .data ; Sezione dati inizializzati msg1: db "Digita una stringa: " ; prompt MSG1: equ $-msg1 ; lunghezza di msg1 msg2: db "Originale: " ; MSG2: equ $-msg2 ; lunghezza di msg2 msg3: db "Convertita: " ; MSG3: equ $-msg3 ; lunghezza di msg3 msg4: db 10, "ERRORE: input nullo.", 10 ; messaggio d'errore MSG4: equ $-msg4 ;lunghezza di msg4 section .bss ; Sezione dati non inizializzati buf: resb BUFLEN ; buffer di input da tastiera newstr: resb BUFLEN ; buffer di output conversione rlen: resb 4 ; lunghezza stringa in input (incluso l'invio) section .text ; Sezione codice global _start ; let loader see entry point _start: ;:::::::::::::::::::::::::::::::::::::::: Output Prompt mov eax, SYSCALL_WRITE ; write function mov ebx, STDOUT ; Arg1: file descriptor mov ecx, msg1 ; Arg2: addr of message mov edx, MSG1 ; Arg3: length of message int 080h ; syscall kernel to write ;:::::::::::::::::::::::::::::::::::::::: Input da tastiera mov eax, SYSCALL_READ ; read function mov ebx, STDIN ; Arg 1: file descriptor mov ecx, buf ; Arg 2: address of buffer mov edx, BUFLEN ; Arg 3: buffer length int 080h ; syscall kernel to read ;:::::::::::::::::::::::::::::::::::::::: Test Errore mov [rlen], eax ; salva la lunghezza della stringa dec eax ; decrementa per escludere l'invio cmp eax, 0 ; Test su zero jg read_OK ; Uscita read_OK se Test>0 ;:::::::::::::::::::::::::::::::::::::::: Output messaggio d'errore mov eax, SYSCALL_WRITE ; write function mov ebx, STDERR ; Arg1: file descriptor mov ecx, msg4 ; Arg2: addr of message mov edx, MSG4 ; Arg3: length of message int 080h ; syscall kernel to write jmp exit1 ; salta all'uscita: errore =1 ;:::::::::::::::::::::::::::::::::::::::: Conversione stringa read_OK: mov ecx, [rlen] ; inizializza il contatore mov esi, buf ; puntatore al buffer di input mov edi, newstr ; puntatore al buffer di conversione nextch: mov al, [esi] ; legge un carattere inc esi ; aggiorna il puntatore sorgente cmp al, 'a' ; verifica che sia minuscolo jb store ; Se NO: Salta la conversione cmp al, 'z' ja store ; Se NO: Salta la conversione and al,0DFh ; Se SI: Converte in maiuscolo store: mov [edi], al ; memorizza il carattere inc edi ; aggiorna il puntatore destinazione dec ecx ; aggiorna il contatore jnz nextch ; ricicla ;:::::::::::::::::::::::::::::::::::::::: Output messaggio 2 mov eax, SYSCALL_WRITE ; write message mov ebx, STDOUT mov ecx, msg2 mov edx, MSG2 int 080h ;:::::::::::::::::::::::::::::::::::::::: Output stringa originale mov eax, SYSCALL_WRITE ; write user input mov ebx, STDOUT mov ecx, buf mov edx, [rlen] int 080h ;:::::::::::::::::::::::::::::::::::::::: Output messaggio 3 mov EAX, SYSCALL_WRITE ; write message mov EBX, STDOUT mov ECX, msg3 mov EDX, MSG3 int 080h ;:::::::::::::::::::::::::::::::::::::::: Output stringa convertita mov EAX, SYSCALL_WRITE ; write out string mov EBX, STDOUT mov ECX, newstr mov EDX, [rlen] int 080h ;:::::::::::::::::::::::::::::::::::::::: Uscita mov EBX, 0 ; exit code, normal=0 jmp exit exit1: mov EBX, 1 ; exit code, error=1 exit: mov EAX, SYSCALL_EXIT ; exit function int 080h ; syscall kernel to take over ; EOF ::::::::::::::::::::::::::::::::::::::::::::::::::::::
Tra le cose da notare, l'inserimento della sezione .bss per la definizione di variabili non inizializzate (i buffer: buf e newstr), in contrapposizione alla sezione .data; ed ancora le pseudoistruzioni %define per introdurre delle costanti. Infine la funzione exit riporta in ebx un codice di uscita che vale "0" se tutto si è concluso regolarmente, oppure "1" in caso di uscita su STDERR.
Sii tu stesso il cambiamento che desideri vedere nel mondo.
Mahatma Gandhi