dal 2015 - visita n. 2548
HelloWorld
HelloWorld

 

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ù
Introduzione
I registri del Pentium
Il modello della memoria
Interazione CPU-RAM
I Servizi Linux - Int 80h
I File in Linux
Schema programma NASM
Esempi Write/Read
Esercizi
lods-stos-movs
gcc + nasm
Gestione Command Line
Stack
Stack-Esercizi
Libreria Funzioni Base
Esercizi con la Libreria
Libreria Macro Base
Test 5 esercizi


Sistemi di numerazione
Elementi Bistabili
Strutture di Controllo
Istruzioni JMP
Hello World
I/O di Testo
Command Line
Colori e Macro
Introduzione I/O
Porta Parallela


AppuntiAsm-386.html
Linux ELF Howto
Linux Assembly Howto
Il linguaggio PC Assembly
Assembly di Paul A.Carter
Assembly di Claudio Daffra



Il migliore amico avrà anche la moglie migliore, perché un buon matrimonio si basa sulla disposizione all'amicizia.
Friedrich W. Nietzsche

Valid CSS!
pagina generata in 0.001 secondi