
Quasi il classico "Hello world"
Il primo esempio leggerà il marchio di fabbrica della CPU e lo visualizzerà sul terminale. Il codice è scritto per macchine di classe Pentium e non esegue alcun controllo per i 486 o precedenti.
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; hello_1.asm
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; compilare con nasm+gcc
global main
extern printf
section .data
cls db 1Bh,"[2J",0
msg db 0Dh,0Ah,"Marchio del produttore della CPU: "
idx dd 0,0,0
db 0Dh,0Ah,0Ah,0
section .text
main: push dword cls ;Clear del terminale
call printf
pop eax
mov eax,0 ;Identificazione CPU
cpuid
mov [idx],ebx ;Lettura prime 4 lettere
mov [idx+4],edx ;Lettura 4 lettere centrali
mov [idx+8],ecx ;Lettura ultime 4 lettere
push dword msg ;Output Messaggio
call printf
pop eax
ret ;Uscita programma
; EOF ::::::::::::::::::::::::::::::::::::::::::::::::::::::
L'esempio appena illustrato esegue quattro operazioni: la pulizia del terminale, l'identificazione della CPU, l'emissione di un messaggio, l'uscita dal programma. L'uso della printf, appartenente alla libreria libc, semplifica le operazioni di output su terminale (clear e messaggio), si noti il passaggio del parametro (puntatore alla stringa) tramite una push con conseguente pop per ripristinare lo stato dello stack. Al posto della pop eax, che coinvolge l'uso di un registro, si potrebbe usare una add esp,4 che risolve il problema del riallineamento dello stack senza coinvolgere registri. L'uscita del programma realizzata con una semplicissima ret.
Ci proponiamo di risolvere lo stesso problema con l'uso di chiamate al kernel, ovvero con le cosiddette syscall. La soluzione è leggermente più complessa, ma è di particolare interesse il passaggio dei parametri tramite registri; si noti, in particolare, che il registro eax viene utilizzato per individuare il numero della syscall da usare, mentre i parametri (par1, par2, par3, ...) vengono passati ordinatamente tramite i registri ebx, ecx, edx, esi, edi, ebp, rispettivamente.
Il confronto con la soluzione precedente evidenzia alcune cose: l'assenza della dichiarazione extern, la mancanza del terminatore null alla fine delle stringhe, la presenza di una costante per l'individuazione della lunghezza delle stringhe.
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; hello_2.asm
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; compilare con nasm+ld
global main
section .data
cls db 1Bh,"[2J"
CLS equ $-cls
msg db 0Dh,0Ah,"Marchio del produttore della CPU: "
idx dd 0,0,0
db 0Dh,0Ah,0Ah
MSG equ $-msg
section .text
main: ;Clear del terminale
mov edx,CLS ;par3: lunghezza del messaggio
mov ecx,cls ;par2: indirizzo del messaggio
mov ebx,1 ;par1: descrittore del file (stdout)
mov eax,4 ;numero della syscall write
int 80h ;chiamata kernel syscall
mov eax,0 ;Identificazione CPU
cpuid
mov [idx],ebx ;Lettura prime 4 lettere
mov [idx+4],edx ;Lettura 4 lettere centrali
mov [idx+8],ecx ;Lettura ultime 4 lettere
;Output Messaggio
mov edx,MSG ;par3: lunghezza del messaggio
mov ecx,msg ;par2: indirizzo del messaggio
mov ebx,1 ;par1: descrittore del file (stdout)
mov eax,4 ;numero della syscall write
int 80h ;chiamata kernel syscall
;Uscita programma
mov ebx,0 ;Par1: codice di ritorno
mov eax,1 ;numero della syscall exit
int 80h ;chiamata kernel syscall
; EOF ::::::::::::::::::::::::::::::::::::::::::::::::::::::
Se effettuiamo un confronto sulla lunghezza dei due eseguibili ottenuti, anche se i sorgenti non sono perfettamente identici, possiamo notare l'evidente maggior compattezza di hello_2 rispetto ad hello_1.
-rwxr-xr-x 1 byteman users 2972 nov 1 19:02 hello_1* -rwxr-xr-x 1 byteman users 576 nov 1 19:04 hello_2*
Complementi
Per quanto riguarda l'identificazione della CPU, ecco quale stringa viene restituita a seconda dei principali produttori:
AMD "AuthenticAMD"
Centaur "CentaurHauls"
Cyrix "CyrixInstead"
Intel "GenuineIntel"
NexGen "NexGenDriven"
Rise "RiseRiseRise"
UMC "UMC UMC UMC "

Menù

Non vi è nulla al mondo paragonabile alla devozione di una moglie. I mariti non ne hanno idea.
Oscar Wilde