1. L’assem bler 80x86
Corso di Calcolatori Elettronici II
Prof. Giulio Iannello
6OLGH D FXUD GL 6LPRQ 3LHWUR 5RPDQR
Dipartimento di Informatica e Sistemistica
Università degli Studi di Napoli “Federico II”
',6 'LSDUWLPHQWR GL ,QIRUPDWLFD H 6LVWHPLVWLFD 8QLYHUVLWj GL 1DSROL
2. I sottoprogram m i: road m ap
L’utilizzo delle subroutine per la realizzazione di
¾
programmi modulari
Scambio di informazioni tra programma chiamante e
¾
programma chiamato
» DOOLQJ FRQYHQWLRQV
» Come interfacciare programmi assembler e programmi C
♦6WDQGDUG FDOOLQJ FRQYHQWLRQV
Esempi pratici con QHWZLGH DVVHPEOHU
¾
',6 'LSDUWLPHQWR GL ,QIRUPDWLFD H 6LVWHPLVWLFD 8QLYHUVLWj GL 1DSROL
3. L’ind irizzam ento ind iretto in assem bler
I registri funzionano da SXQWDWRUL
¾
Notazione:
¾
» Il registro è racchiuso tra parentesi quadre:
♦5HJ@
Esempi:
¾
mov ax, [Data] ; normal direct memory addressing of a word
mov ebx, Data ; ebx = Data
mov ax, [ebx] ; ax = *ebx
La terza istruzione legge una parola, a partire dall’indirizzo
memorizzato in HE[
',6 'LSDUWLPHQWR GL ,QIRUPDWLFD H 6LVWHPLVWLFD 8QLYHUVLWj GL 1DSROL
4. Registri com e puntatori
Ciò a cui punta un registro è determinato esclusivamente
¾
dall’istruzione adoperata
» I registri non hanno un WLSR a differenza delle variabili nei
linguaggi di alto livello
» E’ compito esclusivo del programmatore assicurarsi che
l’utilizzo del registro come puntatore sia corretto
In assembly 80x86, tutti i registri JHQHUDO SXUSRVH a 32 bit
¾
($; (%; (; (';
6. , possono essere usati con l’indirizzamento indiretto
',6 'LSDUWLPHQWR GL ,QIRUPDWLFD H 6LVWHPLVWLFD 8QLYHUVLWj GL 1DSROL
7. Chiam ata a sottoprogram m a
Un sottoprogramma è un’unità di codice indipendente, che può
¾
essere richiamata da diverse parti di un medesimo programma
Una semplice tecnica per l’invocazione di sottoprogrammi fa uso
¾
dei salti:
» Dovendo funzionare in generale, è necessario fare in modo che il
sottoprogramma possa essere richiamato da diversi punti all’interno del
programma chiamante:
♦ il ritorno dal sottoprogramma non può fare riferimento ad una etichetta
prefissata
» Si utilizza la IRUPD LQGLUHWWD dell’istruzione MPS
♦ Il valore di ritorno è contenuto in un registro, al quale si accede tramite
indirizzamento indiretto
',6 'LSDUWLPHQWR GL ,QIRUPDWLFD H 6LVWHPLVWLFD 8QLYHUVLWj GL 1DSROL
8. Un sem plice sottoprogram m a
JHWBLQW usa una semplice convenzione:
¾
HE[
» contiene l’indirizzo della double word da memorizzare
HF[ contiene l’indirizzo dell’istruzione del programma chiamante a cui fare
»
ritorno
; subprogram get_int
; Parameters:
; ebx - address of dword to store integer into
; ecx - address of instruction to return to
; Notes:
; value of eax is destroyed
get_int:
call read_int
mov [ebx], eax ; store input into memory
jmp ecx ; jump back to caller
',6 'LSDUWLPHQWR GL ,QIRUPDWLFD H 6LVWHPLVWLFD 8QLYHUVLWj GL 1DSROL
9. Il program m a principale (1/ 4 )
%include quot;asm_io.incquot;
segment .data
prompt1 db quot;Enter a number: quot;, 0
prompt2 db quot;Enter another number: quot;, 0
outmsg1 db quot;You entered quot;, 0
outmsg2 db quot; and quot;, 0
outmsg3 db quot;, the sum of these is quot;, 0
segment .bss
; These labels refer to double words used to store the
inputs
input1 resd 1
input2 resd 1
',6 'LSDUWLPHQWR GL ,QIRUPDWLFD H 6LVWHPLVWLFD 8QLYHUVLWj GL 1DSROL
10. Il program m a principale (2/ 4 )
segment .text
1% FKLDPDWD D JHWBLQW
global asm_main
asm_main:
enter 0,0 ; setup routine
pusha
mov eax, prompt1 ; print out prompt
call print_string
mov ebx, input1 ; store address of input1 in ebx
mov ecx, ret1 ; store return address into ecx
jmp short get_int ; read integer
ret1:
mov eax, prompt2 ; print out prompt
call print_string
',6 'LSDUWLPHQWR GL ,QIRUPDWLFD H 6LVWHPLVWLFD 8QLYHUVLWj GL 1DSROL
11. Il program m a principale (3/ 4 )
1% LQGLUL]]R GL ULWRUQR
mov ebx, input2
mov ecx, $ + 7 ; ecx = this address + 7
jmp short get_int
mov eax, [input1] ; eax = dword at input1
add eax, [input2] ; eax += dword at input2
mov ebx, eax ; ebx = eax
; next print out result message as series of steps
mov eax, outmsg1
call print_string ; print out first message
mov eax, [input1]
call print_int ; print out input1
mov eax, outmsg2
call print_string ; print out second message
',6 'LSDUWLPHQWR GL ,QIRUPDWLFD H 6LVWHPLVWLFD 8QLYHUVLWj GL 1DSROL
12. Il program m a principale (4/ 4 )
mov eax, [input2]
call print_int ; print out input2
mov eax, outmsg3
call print_string ; print out third message
mov eax, ebx
call print_int ; print out sum (ebx)
call print_nl ; print new-line
popa
mov eax, 0 ; return back to C
leave
ret
',6 'LSDUWLPHQWR GL ,QIRUPDWLFD H 6LVWHPLVWLFD 8QLYHUVLWj GL 1DSROL
13. Un estratto d el file d i OLVWLQJ
..
1% $
..
..
81 00000025 BB[04000000] mov ebx, input2
82 0000002A B9[31000000] mov ecx, $ + 7
83 0000002F EB53 jmp short get_int
84
85 00000031 A1[00000000] mov eax, [input1]
86 00000036 0305[04000000] add eax, [input2]
87 0000003C 89C3 mov ebx, eax
..
..
..
',6 'LSDUWLPHQWR GL ,QIRUPDWLFD H 6LVWHPLVWLFD 8QLYHUVLWj GL 1DSROL
14. Consid erazioni
Con la tecnica esposta sono possibili due alternative:
¾
» Definire un’etichetta per ogni chiamata a sottoprogramma:
♦Es: ‘UHW¶ nell’esempio precedente
» Calcolare D SULRUL l’indirizzo dell’istruzione cui fare ritorno:
♦Es: ‘ ¶ nell’esempio precedente
Entrambi i metodi sono poco eleganti:
¾
» Una soluzione migliore è rappresentata dall’utilizzo dello VWDFN
',6 'LSDUWLPHQWR GL ,QIRUPDWLFD H 6LVWHPLVWLFD 8QLYHUVLWj GL 1DSROL
15. Lo stack
Una lista /DVW ,Q )LUVW 2XW messa a disposizione del programmatore
¾
assembler
Contenuta nella memoria
¾
Una struttura dati su cui sono definite due operazioni:
¾
» Inserimento:
♦ SXVK
» Estrazione:
♦ SRS
Il registro 66 6WDFN 6HJPHQW
16. specifica il segmento che contiene lo
¾
stack (solitamente lo stesso segmento in cui sono contenuti i dati)
Il registro (63 6WDFN 3RLQWHU
17. contiene l’indirizzo del dato situato
¾
in cima allo stack
',6 'LSDUWLPHQWR GL ,QIRUPDWLFD H 6LVWHPLVWLFD 8QLYHUVLWj GL 1DSROL
18. Pu sh e Pop
Push:
¾
» Inserisce una double word nello stack
♦ Sottrae 4 da (63
♦ Memorizza la double word all’indirizzo contenuto in (63 (‘(63@¶
19. Pop:
¾
» Legge la double word memorizzata in (63@
» Aggiunge 4 ad (63
Nell’80x86 esistono le istruzioni:
¾
SXVKD SXVK DOO
21. »
♦ Ripristina il valore di tali registri
',6 'LSDUWLPHQWR GL ,QIRUPDWLFD H 6LVWHPLVWLFD 8QLYHUVLWj GL 1DSROL
22. Le istru zioni FDOO e UHW
Utilizzate per semplificare la chiamata a sottoprogrammi
¾
con l’ausilio dello stack
FDOO
»
♦Salva sullo stack SXVK
23. l’indirizzo dell’istruzione di ritorno
♦Effettua un salto incondizionato ad un sottoprogramma
UHW
»
♦Preleva un indirizzo dallo stack
♦Salta all’indirizzo prelevato
',6 'LSDUWLPHQWR GL ,QIRUPDWLFD H 6LVWHPLVWLFD 8QLYHUVLWj GL 1DSROL
24. Utilizzo d i FDOO e UHW
Nel programma dell’esempio precedente:
¾
» Il blocco del programma chiamante…
mov ebx, input1 ; store address of input1 in ebx mov
ecx, ret1 ; store return address into ecx jmp short
get_int ; read integer
…è sostituito da:
mov ebx, input1 ; store return address into ecx call
get_int ; read integer
» La subroutine diventa:
get_int:
call read_int
mov [ebx], eax ; store input into memory
ret
',6 'LSDUWLPHQWR GL ,QIRUPDWLFD H 6LVWHPLVWLFD 8QLYHUVLWj GL 1DSROL
25. Vantaggi nell’u tilizzo d ello stack
Semplicità
¾
Possibilità di innestare le chiamate di procedura:
¾
» Es: JHWBLQW nel nostro esempio chiama UHDGBLQW
» Ciò è reso possibile dalla proprietà LIFO dello stack:
♦UHDGBLQW al termine della propria esecuzione, restituisce il
controllo a JHWBLQW, il cui indirizzo era stato salvato sullo stack;
♦JHWBLQW a sua volta, restituisce il controllo al programma
chiamante, il cui indirizzo di ritorno è stato anch’esso salvato
sullo stack
» Tale principio di funzionamento è anche alla base della ricorsione
',6 'LSDUWLPHQWR GL ,QIRUPDWLFD H 6LVWHPLVWLFD 8QLYHUVLWj GL 1DSROL
26. Calling conventions (1/ 2)
C’è bisogno di accordo tra programma chiamante e
¾
programma chiamato, riguardo alle convenzioni utilizzate
per lo scambio di informazioni
Ciò resta valido qualora si voglia far interagire codice in
¾
linguaggio ad alto livello con codice assembly
Le convenzioni di chiamata possono variare in funzione:
¾
» del compilatore utilizzato
» Delle opzioni di compilazione utilizzate
Una convenzione XQLYHUVDOPHQWH valida fa riferimento
¾
all’utilizzo delle istruzioni FDOO e UHW
',6 'LSDUWLPHQWR GL ,QIRUPDWLFD H 6LVWHPLVWLFD 8QLYHUVLWj GL 1DSROL
27. Calling conventions (2/ 2)
Tutti i compilatori per PC supportano una convenzione di
¾
chiamata che consente di creare sottoprogrammi cosiddetti
UHHQWUDQW
Un sottoprogramma UHHQWUDQW può essere invocato da
¾
qualsiasi punto di un programma chiamante (al limite
anche se stesso)
Per che ciò sia possibile, è necessario che il passaggio dei
¾
parametri avvenga tramite lo stack
',6 'LSDUWLPHQWR GL ,QIRUPDWLFD H 6LVWHPLVWLFD 8QLYHUVLWj GL 1DSROL
28. Param etri su llo stack
I parametri sono inseriti nello stack prima della chiamata a
¾
sottoprogramma FDOO
29. Nel caso di parametri il cui valore debba essere alterato
¾
dal sottoprogramma, è necessario salvare sullo stack gli
indirizzi dei dati SDVVDJJLR SHU ULIHULPHQWR
30. Se la dimensione di un parametro è inferiore ad una
¾
GRXEOH ZRUG, è necessaria una conversione prima di
effettuare l’inserimento nello stack
',6 'LSDUWLPHQWR GL ,QIRUPDWLFD H 6LVWHPLVWLFD 8QLYHUVLWj GL 1DSROL
31. Accesso ai param etri su llo stack
I parametri inseriti nello stack non vengono rimossi dal
¾
sottoprogramma, ma l’accesso ad essi avviene
direttamente sullo stack:
» Dato che essi vengono inseriti nello stack prima dell’esecuzione
dell’istruzione FDOO, per estrarli sarebbe necessario effettuare,
preliminarmente, un SRS dallo stack dell’indirizzo di ritorno (che
andrebbe, in seguito, nuovamente inserito)
» Lasciando i parametri sullo stack, è possibile accedere ad essi da
diverse parti del sottoprogramma, evitando di occupare registri
dedicati, o locazioni di memoria
',6 'LSDUWLPHQWR GL ,QIRUPDWLFD H 6LVWHPLVWLFD 8QLYHUVLWj GL 1DSROL
32. L’u tilizzo d el registro (%3
Se lo stack è utilizzato anche per memorizzare dati locali del
¾
sottoprogramma, diventa necessario gestire la zona dello stack
associata al sottoprogramma stesso (nota come IUDPH)
Per fare riferimento ai dati sullo stack, ogni sottoprogramma utilizza
¾
il registro (%3
» Prima di utilizzarlo, il sottoprogramma salva il valore corrente di (%3 sullo
stack
» Subito dopo, il nuovo valore di EBP viene fissato all’attuale valore dello stack
pointer (63
33. » Ciò consente ad (63 di cambiare in seguito all’inserimento (o prelievo) di
ulteriori dati, mentre (%3 resta fisso e può essere utilizzato come riferimento
» Alla fine dell’esecuzione, il valore precedente di (%3 (salvato sullo stack)
viene ripristinato
',6 'LSDUWLPHQWR GL ,QIRUPDWLFD H 6LVWHPLVWLFD 8QLYHUVLWj GL 1DSROL
34. Prologo ed Epilogo
Prologo:
push ebp ; save original EBP value on stack
mov ebp, esp ; new EBP = ESP
Epilogo:
pop ebp ; restore original EBP value
ret
',6 'LSDUWLPHQWR GL ,QIRUPDWLFD H 6LVWHPLVWLFD 8QLYHUVLWj GL 1DSROL
35. Rim ozione d ei param etri d allo stack
In seguito all’esecuzione si un sottoprogramma, i
¾
parametri devono essere eliminati dallo stack:
» Le convenzioni C specificano che è compito del programma
chiamante rimuovere i parametri dallo stack
» Questo semplifica la realizzazione di funzioni con numero
variabile di parametri (tipo SULQWI
37. )
» Altri linguaggi impongono che sia il sottoprogramma ad
occuparsi della ‘pulizia’ dello stack al termine dell’esecuzione
La rimozione dei parametri è effettuata semplicemente
¾
aggiungendo un offset opportuno allo stack pointer
» In alternativa si potrebbe utilizzare l’istruzione SRS la quale
comunque richiede che il valore estratto sia salvato in un registro
',6 'LSDUWLPHQWR GL ,QIRUPDWLFD H 6LVWHPLVWLFD 8QLYHUVLWj GL 1DSROL
38. Rim ozione d ei param etri d allo stack
Un esempio:
¾
» Un programma che chiama un sottoprogramma, passandogli un
parametro sullo stack
push dword 1 ; pass 1 as parameter
call fun
add esp, 4 ; remove parameter from stack
',6 'LSDUWLPHQWR GL ,QIRUPDWLFD H 6LVWHPLVWLFD 8QLYHUVLWj GL 1DSROL
39. Un esem pio com pleto
Un programma principale e due sottoprogrammi che utilizzano le
¾
convenzioni del C per lo scambio di informazioni
Tutti contenuti in unico modulo (cioè un unico file)
¾
Utilizzo di più segmenti GDWD e WH[W
¾
» Combinati in unico segmento GDWD ed un unico segmento WH[W durante il
processo di linking
Pseudocodice:
¾
i = 1;
sum = 0;
while( get_int(i, input), input != 0 ) {
sum += input;
i++;
}
print_sum(num);
',6 'LSDUWLPHQWR GL ,QIRUPDWLFD H 6LVWHPLVWLFD 8QLYHUVLWj GL 1DSROL
40. Il program m a principale (1/ 2)
segment .text
global asm_main
asm_main:
enter 0,0 ; setup routine
pusha
mov edx, 1 ; edx is ’i’ in pseudo-code
while_loop:
push edx ; save i on stack
push dword input ; push address of input on stack
call get_int
add esp, 8 ; remove i and input from stack
mov eax, [input]
cmp eax, 0
je end_while
',6 'LSDUWLPHQWR GL ,QIRUPDWLFD H 6LVWHPLVWLFD 8QLYHUVLWj GL 1DSROL
41. Il program m a principale (2/ 2)
add [sum], eax ; sum += input
inc edx
jmp short while_loop
end_while:
push dword [sum] ; push value of sum onto stack
call print_sum
pop ecx ; remove [sum] from stack
popa
leave
ret
',6 'LSDUWLPHQWR GL ,QIRUPDWLFD H 6LVWHPLVWLFD 8QLYHUVLWj GL 1DSROL
42. La su brou tine get_int
segment .data
prompt db quot;) Enter an integer number (0 to quit): quot;, 0
segment .text
get_int:
push ebp
3URORJR
mov ebp, esp
mov eax, [ebp + 12]
call print_int
mov eax, prompt
(SLORJR
call print_string
call read_int
mov ebx, [ebp + 8]
mov [ebx], eax ; store input into memory
pop ebp
ret ; jump back to caller
',6 'LSDUWLPHQWR GL ,QIRUPDWLFD H 6LVWHPLVWLFD 8QLYHUVLWj GL 1DSROL
43. La su brou tine print_su m
segment .data
result db quot;The sum is quot;, 0
segment .text
print_sum:
push ebp 3URORJR
mov ebp, esp
mov eax, result
call print_string
(SLORJR
mov eax, [ebp+8]
call print_int
call print_nl
pop ebp
ret
',6 'LSDUWLPHQWR GL ,QIRUPDWLFD H 6LVWHPLVWLFD 8QLYHUVLWj GL 1DSROL