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 "
Il migliore amico avrà anche la moglie migliore, perché un buon matrimonio si basa sulla disposizione all'amicizia.
Friedrich W. Nietzsche