Upload
majong-devjfu
View
479
Download
0
Embed Size (px)
Citation preview
',6�� 'LSDUWLPHQWR�GL�,QIRUPDWLFD�H�6LVWHPLVWLFD� 8QLYHUVLWj�GL�1DSROL
L’assembler 80x86
Corso di Calcolatori Elettronici IIProf. Giulio Iannello
6OLGH�D�FXUD�GL�6LPRQ�3LHWUR�5RPDQR
Dipartimento di Informatica e SistemisticaUniversità degli Studi di Napoli “Federico II”
',6�� 'LSDUWLPHQWR�GL�,QIRUPDWLFD�H�6LVWHPLVWLFD� 8QLYHUVLWj�GL�1DSROL
I sottoprogrammi: roadmap
¾ 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
L’indirizzamento ind iretto in assembler
¾ I registri funzionano da SXQWDWRUL
¾ Notazione: » Il registro è racchiuso tra parentesi quadre:
♦>5HJ@
¾ Esempi:mov ax, [Data] ; normal direct memory addressing of a wordmov ebx, Data ; ebx = & Datamov 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
Registri come 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 �($;��(%;��(&;��(';�, nonché i registri indice �(6,��
(',�, possono essere usati con l’indirizzamento indiretto
',6�� 'LSDUWLPHQWR�GL�,QIRUPDWLFD�H�6LVWHPLVWLFD� 8QLYHUVLWj�GL�1DSROL
Chiamata a sottoprogramma
¾ 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
Un semplice sottoprogramma
¾ 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 destroyedget_int:
call read_intmov [ebx], eax ; store input into memoryjmp ecx ; jump back to caller
',6�� 'LSDUWLPHQWR�GL�,QIRUPDWLFD�H�6LVWHPLVWLFD� 8QLYHUVLWj�GL�1DSROL
Il programma principale (1/ 4 )
%include "asm_io.inc"
segment .dataprompt1 db "Enter a number: ", 0prompt2 db "Enter another number: ", 0outmsg1 db "You entered ", 0outmsg2 db " and ", 0outmsg3 db ", the sum of these is ", 0segment .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
Il programma principale (2/ 4 )
segment .text
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
1%��FKLDPDWD�D�JHWBLQW
',6�� 'LSDUWLPHQWR�GL�,QIRUPDWLFD�H�6LVWHPLVWLFD� 8QLYHUVLWj�GL�1DSROL
Il programma principale (3/ 4 )
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
1%��LQGLUL]]R�GL�ULWRUQR
',6�� 'LSDUWLPHQWR�GL�,QIRUPDWLFD�H�6LVWHPLVWLFD� 8QLYHUVLWj�GL�1DSROL
Il programma 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
Un estratto del file d i OLVWLQJ
..
..
..
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
..
..
..
1%���$��� ���
',6�� 'LSDUWLPHQWR�GL�,QIRUPDWLFD�H�6LVWHPLVWLFD� 8QLYHUVLWj�GL�1DSROL
Considerazioni
¾ 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
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� specifica il segmento che contiene lo stack (solitamente lo stesso segmento in cui sono contenuti i dati)
¾ Il registro (63��6WDFN 3RLQWHU��contiene l’indirizzo del dato situato in cima allo stack
',6�� 'LSDUWLPHQWR�GL�,QIRUPDWLFD�H�6LVWHPLVWLFD� 8QLYHUVLWj�GL�1DSROL
Push e Pop
¾ Push:» Inserisce una double word nello stack
♦ Sottrae 4 da (63
♦ Memorizza la double word all’indirizzo contenuto in (63 (‘>(63@¶�
¾ Pop:» Legge la double word memorizzata in >(63@
» Aggiunge 4 ad (63
¾ Nell’80x86 esistono le istruzioni:» SXVKD��SXVK�DOO�
♦ salva sullo stack il contenuto dei registri ($;��(%;��(&;��(';��(6,��(',�HG�(%3
» SRSD �SRS�DOO�
♦ Ripristina il valore di tali registri
',6�� 'LSDUWLPHQWR�GL�,QIRUPDWLFD�H�6LVWHPLVWLFD� 8QLYHUVLWj�GL�1DSROL
Le istruzioni FDOO�e UHW
¾ Utilizzate per semplificare la chiamata a sottoprogrammi con l’ausilio dello stack» FDOO
♦Salva sullo stack �SXVK� 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
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 shortget_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_intmov [ebx], eax ; store input into memoryret
',6�� 'LSDUWLPHQWR�GL�,QIRUPDWLFD�H�6LVWHPLVWLFD� 8QLYHUVLWj�GL�1DSROL
Vantaggi nell’utilizzo dello 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 salvatosullo stack
» Tale principio di funzionamento è anche alla base della ricorsione
',6�� 'LSDUWLPHQWR�GL�,QIRUPDWLFD�H�6LVWHPLVWLFD� 8QLYHUVLWj�GL�1DSROL
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
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
Parametri sullo stack
¾ I parametri sono inseriti nello stack prima della chiamata a sottoprogramma �FDOO�
¾ Nel caso di parametri il cui valore debba essere alterato dal sottoprogramma, è necessario salvare sullo stack gli indirizzi dei dati �SDVVDJJLR�SHU�ULIHULPHQWR�
¾ 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
Accesso ai parametri sullo 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
L’utilizzo del 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�
» 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
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
Rimozione dei parametri dallo 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���e VFDQI��)» 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
Rimozione dei parametri dallo 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
Un esempio completo
¾ 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
Il programma 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
Il programma 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
La subroutine get_int
segment .data
prompt db ") Enter an integer number (0 to quit): ", 0
segment .text
get_int:
push ebp
mov ebp, esp
mov eax, [ebp + 12]
call print_int
mov eax, prompt
call print_string
call read_int
mov ebx, [ebp + 8]
mov [ebx], eax ; store input into memory
pop ebp
ret ; jump back to caller
3URORJR
(SLORJR
',6�� 'LSDUWLPHQWR�GL�,QIRUPDWLFD�H�6LVWHPLVWLFD� 8QLYHUVLWj�GL�1DSROL
La subroutine print_sum
segment .data
result db "The sum is ", 0
segment .text
print_sum:
push ebp
mov ebp, esp
mov eax, result
call print_string
mov eax, [ebp+8]
call print_int
call print_nl
pop ebp
ret
3URORJR
(SLORJR
',6�� 'LSDUWLPHQWR�GL�,QIRUPDWLFD�H�6LVWHPLVWLFD� 8QLYHUVLWj�GL�1DSROL
L’immagine dello stack
2OG�(%32OG�(%3 2OG�(%3
2OG�(%3
5(7
5(7 5(7
5(7
,1387
,1387 ,1387
,1387
(';
('; (';
(';(63
(63
(63
(63
(63 (%3
(%3��
(%3���