Assembler per 8086 - 1
C o rs o d i Fond a m e n ti d i I n fo rm a tica 2 C dL Ing e gn e ri a In fo rm a tica Ing . F ra n c o Z a m bon e lli
ARCH IT E TT URA D E G L I E L AB O RA T O R I: A SSE M B L E R PE R 8086 /8088
Lu c id i R ea li zz a ti i n C o ll a bo ra z ion e c on :
Prof. Letizia LeonardiUniversità di Modena
Prof. Antonio CorradiUniversità di Bologna
Assembler per 8086 - 2
L IN G UA GGIO ASSE M B L ER PER 8086 /8088
Linguaggio Macchina
•insieme di istruzioni che un elaboratore è in grado dieseguire direttamente
•strettamente correlato alla realizzazione fisicadell'elaboratore
Per scrivere un codice in linguaggio macchina ènecessario:
•conoscere l'architettura della macchina
•ragionare in termini del comportamentodell'elaboratore
•conoscere i dettagli relativi alla scrittura delle singoleistruzioni:-codici numerici e formato interno delle istruzionimacchina-rappresentazione degli operandi
•gestire direttamente gli indirizzi in memoria per ilriferimento ai dati e per i salti al codice
Assembler per 8086 - 3 Ad esempio, per scrivere nel linguaggio macchinadell'8086 l'istruzione:
MOV destinazione, sorgente
è necessario scegliere tra:
•14 diversi codici operativi, in funzione del tipodegli operandi
•svariate possibili rappresentazioni degli operandistessi
L'istruzione macchina che si ottiene ha una lunghezzavariabile tra i due e i sei byte, a seconda delle scelteeffettuate
Assemblatori e compilatori permettono di interfacciareil mondo esterno (i programmi scritti in linguaggi piùevoluti) con il livello più basso della macchina
La conoscenza del linguaggio macchina è indispensabilea coloro che scrivono assemblatori e compilatori (ingenerale, traduttori che generano codice in linguaggiomacchina)
Assembler per 8086 - 4 Linguaggio Assembler
•insieme di istruzioni di tipo elementare
•costringe ancora il programmatore a ragionare intermini della logica della macchina a cui si riferisce
•risulta più ad alto livello rispetto al linguaggiomacchina
•nasconde i dettagli realizzativi delle singole istruzione(codici operativi, formati, ecc.)
•associa ai dati e alle istruzioni nomi simbolici cheidentificano in modo univoco le corrispondentiposizioni di memoria (eliminando, così, la necessitàdi utilizzare indirizzi espliciti)
Assembler per 8086 - 5 Istruzioni eseguibili - a cui corrispondono le istruzionidel linguaggio macchina
Direttive (o pseudoistruzioni) - controllano ilcomportamento dell'assemblatore in fase di traduzione -facilitano lo sviluppo dei programmi - permettono:-la suddivisione di un'applicazione in più moduli-il controllo del formato dei listati-la definizione di macro, ecc.
L'architettura della macchina a cui il linguaggio siriferisce non viene nascosta in alcun modo
Ad esempio, l'assembler dell'8086 tiene contodell'esistenza dei segmenti e permette di gestirli in modocompleto e appropriato
Assembler per 8086 - 6 Formato delle istruzioni
[label] istruzione/direttiva [operando/i] [; commento]
•label consente di dare un nome simbolico (dautilizzare come operando in altre istruzioni) a variabilidi memoria, valori, singole istruzioni, procedure
•istruzione/direttiva è il mnemonico perun'istruzione eseguibile o una direttiva:individua il tipo di operazione da eseguire eil numero e il tipo degli operandi
•operando/i è una combinazione di nessuna, una o piùcostanti, riferimenti a registri o riferimenti allamemoria;se un'istruzione ammette due operandi:-il primo è l'operando destinazione-il secondo è l'operando sorgentead esempio, MOV AX, CX copia il contenuto delregistro CX nel registro AX
•commento consente di rendere più leggibile ilprogramma
Assembler per 8086 - 7 E' indifferente l'uso di lettere maiuscole o minuscole
Il tipo di operandi ammessi varia da istruzione aistruzione
Esistono istruzioni che ammettono come operando solouna costante o solo un particolare registro generale
Nomi simbolici
•caratteri ammessi per i nomi simbolici:A-Z a-z 0-9 _ $ ? @
•il primo carattere di un nome non può essere un digit(0-9)
•ogni nome deve essere univoco (in genere, all'internodel modulo in cui viene definito)
•non deve coincidere con una parola riservata (adesempio, il nome di un registro o di un operatore)
Assembler per 8086 - 8 Costanti numeriche
•di default, tutti i valori numerici sono espressi in basedieci
•è possibile esprimere le costanti numeriche:-in base 16 (esadecimale) mediante il suffisso H (ilprimo digit deve essere numerico)-in base 8 (octal) mediante il suffisso O-in base 2 (binario) mediante il suffisso B
Ad esempio:
0FFh0h777O11001BFFherrata !778Oerrata !
Assembler per 8086 - 9 DIRETTIVE
Istruzioni di tipo dichiarativo, che forniscono informazioniagli strumenti di sviluppo dei programmi (nel caso delTurbo Assembler, l'assemblatore TASM e il linkerTLINK)
AssemblerLinker
METALIVELLO
Direttive di segmento (standard)
Permettono di definire i vari tipi di segmenti
La definizione di ogni segmento deveiniziare con una direttiva SEGMENT eterminare con una direttiva ENDS:
nomeSeg SEGMENT
contenuto del segmento
nomeSeg ENDS
Assembler per 8086 - 10 La direttiva SEGMENT definisce l'inizio di un segmento
nome SEGMENT [allineamento] [comb] ['CLASSE']
•nome - nome simbolico del segmento - se è giàstato definito un segmento con lo stesso nome, ilsegmento corrente è la continuazione del precedente
•allineamento - controlla l'allineamento in memoria disegmenti con lo stesso nome, definiti in moduli diversiil default è PARA
utilizzare:BYTE per i segmenti che contengono codiceDWORD alla doppia parolaWORD per tutti gli altri segmenti
•comb - controlla la modalità di collegamento disegmenti con lo stesso nome, definiti in moduli diversiil default è PRIVATE
utilizzare:STACK per il segmento che contiene lo stack – ciòpermette di impostare SS:SP alla fine del segmentostack al momento dell'esecuzione del programmaPUBLIC per tutti gli altri segmentiAT per segmenti assoluti
Assembler per 8086 - 11 •classe - controlla l'ordine in cui i segmenti vengonocollegati: tutti i segmenti di una determinata classevengono collocati in un blocco contiguo di memoria,indipendentemente dalla loro posizione nel codicesorgente
utilizzare:CODE per i segmenti che contengono codiceDATA per i segmenti che contengono datiSTACK per i segmenti che contengono lo stack
La direttiva ENDS indica la fine di un segmento
nome ENDS
nome è il nome simbolico del segmento
La direttiva END indica la fine del programma sorgente
END[startAddress]
startAddress, se presente, è un nome simbolico cheidentifica l'indirizzo di partenza del programma
Assembler per 8086 - 12 La direttiva ASSUME dice all'assemblatore a qualesegmento un determinato registro di segmento stapuntando
ASSUME segReg:nome [,segReg:nome] ...
ASSUME segReg:NOTHING
ASSUME NOTHING
•segReg è il nome di un registro di segmento(CS, SS, DS, ES)
•nome è il segmento al quale l'assemblatore assumeche segReg punti da questo momento in poi (sino auna nuova ASSUME che coinvolga lo stesso registro)
•NOTHING cancella l'associazione tra registri esegmenti
L'uso di ASSUME non equivale al caricamento di unregistro di segmento,ma permette all'assemblatore di:•controllare la validità dei riferimenti alla memoria•inserire automaticamente eventuali prefissi disegmentazione diversi da quelli di default
Assembler per 8086 - 13 Esempio - Programma con tre segmenti (stack, dati ecodice):
_StackSEGMENT WORD STACK 'STACK'dimensionamento dello stack_StackENDS
_DataSEGMENT WORD PUBLIC 'DATA'definizione dei dati del programma_DataENDS
_CodeSEGMENT BYTE PUBLIC 'CODE'ASSUME CS:_Code, SS:_StackASSUME ES:NOTHINGStart:MOV AX, _DataMOV DS, AXASSUME DS:_Data. . ._CodeENDS
END Start
Assembler per 8086 - 14 Direttive per la definizione di procedure
La definizione di ogni proceduradeve iniziare con una direttiva PROC edeve terminare con una direttiva ENDP
La direttiva PROC definisce l'inizio di una procedura
nome PROC [distanza]
•nome è il nome simbolico della procedura(da utilizzare nelle chiamate alla procedura)
•distanza è:-NEAR - la procedura può essere chiamata soloall'interno del segmento in cui è stata definita(default)-FAR - la procedura può essere chiamata da qualsiasisegmento
La direttiva ENDP indica la fine di una procedura
nome ENDP
nome è il nome simbolico della procedura
Assembler per 8086 - 15 Ad esempio, per definire la procedura FAR di nomeFarProc, si scrive:
FarProcPROC FAR
. . .
FarProcENDP
mentre per definire la procedura NEAR di nomeNearProc, si scriverà:
NearProcPROC NEAR
. . .
NearProcENDP
Assembler per 8086 - 16 Direttive per la definizione dei dati
Permettono di definire:
•il nome•il tipo•il contenuto
delle variabili in memoria
[nome] tipo espressione [, espressione] ...
•nome - nome simbolico del dato
•tipo - lunghezza del dato (se scalare) o di ognielemento del dato (se array) - i tipi più utilizzati sono:
DBriserva uno o più byte (8 bit)
DWriserva una o più word (16 bit)
DDriserva una o più doubleword (32 bit)
•espressione - contenuto iniziale del dato:-un'espressione costante-una stringa di caratteri (solo DB)-un punto di domanda (nessuna inizializzazione)-un'espressione che fornisce un indirizzo(solo DW e DD)-un'espressione DUPlicata
Assembler per 8086 - 17 ByteVarDB0; 1 byte inizializzato a 0
ByteArrayDB1,2,3,4; array di 4 byte
StringDB'8','0','8','6' ; array di 4 caratteri
StringDB'8086'; equivale al precedente
TitoloDB'Titolo',0dh,0ah; stringa che contiene anche una; coppia di caratteri CR/LF
ZerosDB256 dup (0); array di 256 byte inizializzati a 0
TabellaDB50 dup (?); array di 50 byte non inizializzati
WordVarDW100*50; scalare di una word
MatrixDW1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0; array di 16 word
MatrixDW4 dup (1, 3 dup (0)); equivale al precedente
NearPointerDWMatrix; contiene l'offset di Matrix
DoubleVarDD?; scalare di una doubleword
FarPointerDDMatrix; contiene l'offset e l'indirizzo del; segmento di Matrix
Assembler per 8086 - 18 La direttiva EQU
Permette di assegnare un nome simbolico a unacostante
nomeEQUespressione
•nome è il nome simbolico associato alla costante -può essere utilizzato ovunque al posto della costantestessa - usare lettere maiuscole per distinguere lecostanti dalle variabili
•espressione deve fornire un valore costante
CREQU0dh; carattere Carriage Return
LFEQU0ah; carattere Line Feed
. . .
TitoloDB'Titolo',CR,LF; stringa che contiene anche; una coppia di caratteri CR/LF
Assembler per 8086 - 19 OPERATORI
Permettono di formare espressioni complesse dautilizzare come operandi di istruzioni e direttive
L'assemblatore:•valuta ogni espressione al momento della traduzionedel programma sorgente•sostituisce il risultato dell'espressione, che deveessere una costante, all'espressione stessa
Priorità degli operatori
•gli operatori di priorità maggiore vengono calcolatiprima di quelli con priorità inferiore•gli operatori con uguale priorità vengono calcolati dasinistra a destra•eventuali sottoespressioni tra parentesi vengonocalcolate per prime
Assembler per 8086 - 20 Priorità standard
<>, (), [], LENGTH, MASK, SIZE, WIDTH
. (selettore di un elemento di struttura)
HIGH, LOW
+, - (monadici)
: (override di segmento)
OFFSET, PTR, SEG, THIS, TYPE
*, /, MOD, SHL, SHR
+, - (diadici)
EQ, GE, GT, LE, LT, NE
NOT
AND
OR, XOR
LARGE, SHORT, SMALL, .TYPE
Assembler per 8086 - 21 Operatore :
Permette di utilizzare un segmento diverso da quello didefault
segName : espressione
•segName è il nome di un registro segmento o di unsegmento definito con la direttiva SEGMENT
•espressione fornisce un offset relativo al segmentosegName
MOVAX, ES:VarX
copia in AX il contenuto della variabile VarXappartenente al segmento puntato da ES(il segmento di default è puntato da DS)
VarPtrDDSegData:VarName
carica in VarPtr (2 word) l'indirizzo completo (segmento+ offset) della variabile VarName appartenente alsegmento SegData (che può essere diverso dalsegmento di default)
Assembler per 8086 - 22 Operatore SEG
Fornisce l'indirizzo del segmento di un'espressione
SEG espressione
espressione è un riferimento alla memoria (una labelo una variabile)
SEG restituisce l'indirizzo del segmento che contiene ilriferimento alla memoria
VarXDB?
. . .
MOVAX, SEG VarX
MOVDS, AX
carica in DS l'indirizzo del segmento che contiene VarX
Assembler per 8086 - 23 Operatore OFFSET
Fornisce l'offset di un'espressione all'interno di unsegmento
OFFSET espressione
espressione è un riferimento alla memoria (una labelo una variabile)
OFFSET restituisce il numero di byte dall'inizio delsegmento alla locazione della memoria a cui si riferisceespressione
VarXDB?
. . .
MOVSI, OFFSET VarX
carica in SI l'offset di VarX - non il suo contenuto
Assembler per 8086 - 24 MODALITÀ DI INDIRIZZAMENTODEGLI OPERANDI
L'operando di un'istruzione può essere:
•in un registro
•nell'istruzione stessa - operando immediato
•in memoria
•in una porta di I/O
L'indirizzo di un operando in memoria o in una porta diI/O può essere ottenuto in molti modi diversi
L'offset di un operando in memoria viene calcolatodall'EU in funzione della modalità di indirizzamentoutilizzata nell'istruzione e viene detto indirizzo effettivodell'operando - Effective Address o EA
Assembler per 8086 - 25 Operando Registro
È l'indirizzamento più compatto e veloce
L'operando è già nella CPU e quindi non è necessarioaccedere alla memoria
Il registro può essere a 8 o a 16 bit
MOV AX, CX; AX <- CX (16 bit)
Operando Immediato
L'operando è contenuto nell'istruzione
L'accesso all'operando è velocel'operando è nella instruction queue
Il dato può essere una costante di 8 o 16 bit
MOV CX, 100; CX <- 100 (16 bit)
il valore 100 è memorizzato all'interno dell'istruzione in 2byte
Assembler per 8086 - 26 Indirizzamento Diretto
E' l'indirizzamento in memoria più semplice
L'EA è contenuto nel campo displacement dell'istruzione- un valore senza segno di 8 o 16 bit
VarDW0AABBh. . .MOV AX, Var; AX <- Var (16 bit)
MOV AX, [Var]; AX <- Var (16 bit)
AH <- 0AAhAL <- 0BBh
Assembler per 8086 - 27 Indirizzamento Indirettomediante Registro
L'EA si ottiene sommando
•un valore di displacement
•il contenuto corrente di un registro base (BX o BP)
•il contenuto corrente di un registro indice (SI o DI)
tutti i termini tranne uno sono opzionali
MOV BX, OFFSET Var; BX <- offset di Var
MOV AX, [BX]; AX <- [BX] (16 bit)
Assembler per 8086 - 28 Se si aggiorna in modo opportuno il contenuto del/deiregistro/i, la stessa istruzione può agire su più locazionidi memoria
Attenzione: se si utilizza il registro BP, il segmento didefault non è DS, ma SS
MOV AX, [BP+4]; AX <- SS: [BP+4]
MOV CL, ES:[Var+SI]
MOV [BX+SI+2], AX
MOV [BX], 0; 8 o 16 bit?
Operatore PTR
Cast di un'espressione ad un dato tipo
tipo PTR espressione
espressione è un riferimento alla memoriatipo è BYTE, WORD, ...
MOVBYTE PTR [BX], 0; 8 bit
MOVWORD PTR [BX], 0; 16 bit
Assembler per 8086 - 29 Esempio di Indirizzamento conRegistro Base e Registro Indice
L'EA si ottiene come somma
•di un valore di displacement
•del contenuto di un registro base (BX o BP)
•del contenuto di un registro indice (SI o DI)
Le due componenti dell'indirizzo possono variare almomento dell'esecuzione
Questa caso è utile per accedere, ad esempio, ai diversielementi di una matrice: il displacement forniscel'indirizzo di partenza dell'array, mentre il registro base eil registro indice selezionano uno degli elementi (il primoelemento viene selezionato quando entrambi i registrivalgono 0).
Assembler per 8086 - 30 TABLE è l'indirizzo simbolico di una matrice di byte 4x4,memorizzata per colonne nel data segment corrente
MOV BX, 4; inizializza BX a 4MOV DI, 2; inizializza DI a 2MOV AL, [TABLE+BX+DI]; AL <- TABLE(3,2)
BX contiene il displacement tra l'indirizzo di partenzadella matrice e la colonna selezionata (la seconda)
DI contiene il displacement tra l'indirizzo di partenzadella colonna selezionata e la riga selezionata (la terza)
Assembler per 8086 - 31 Indirizzamento delle porte di I/O
Per accedere ad una porta di I/O mappata in memoria,si utilizza una qualsiasi modalità di indirizzamento allamemoria
Per accedere ad una porta di I/O NON mappata inmemoria, è necessario utilizzare le istruzioni:
IN accumulatore, porta
OUT porta, accumulatore
IN (INput) trasferisce un dato da una porta di input, alregistro AX o AL
OUT (OUTput) trasferisce un dato dal registro AX o ALad una porta di output
La porta è identificata:•da un valore costante compreso tra 0 e 255indirizzamento diretto•dal contenuto del registro DX (tra 0 e 65.535)indirizzamento indiretto
IN AX, 15; AX <- port15(word)OUT 3, AL; port3 <- AL(byte)IN AX, DX; AX <- port[DX](word)
Assembler per 8086 - 32 L'operatore PTR
Cast di un'espressione ad un dato tipo
tipo PTR espressione
espressione è un riferimento alla memoriatipo è:•se dati: byte, word, ...•se codice: near, far, ...
MOV[BX], 0; ?
MOVBYTE PTR [BX], 0; 8 bit
MOVWORD PTR [BX], 0; 16 bit
CALL[BX]; ?
CALLWORD PTR [BX]; Near call; BX -> offset
CALLDWORD PTR [BX]; Far call; BX -> seg:offset
Assembler per 8086 - 33 L'operatore SHORT
Informa l'assemblatore che espressione è distante dallalocazione correnteda -128 a +127 byte (indirizzo di un byte)
SHORT espressione
espressione è un riferimento a una label nel segmentocodice corrente
JMPSHORT Lab1; riferimento in avanti
. . .
Lab1:
La direttiva LABEL
forza un simbolo ad un tipo specificato
nomeLABEL tipo
wordsLABEL WORD; struttura come word
bytesdb howmany DUP (?)
. . .
MOVAX, words; prima word
Assembler per 8086 - 34 Direttiva PUBLIC
Rende accessibili da altri moduli uno o più simboli
PUBLIC symbol [, symbol ...]
symbol è il nome di una variabile o di una procedura
_DATASEGMENT WORD PUBLIC 'DATA'ARR_SIZEEQU100MemVarDW10MemArrDBARR_SIZE DUP (0). . ._DATAENDS_CODESEGMENT BYTE PUBLIC 'CODE'NearProcPROC. . .FarProcPROCFAR. . ._CODEENDSPUBLICMemVar,MemArrPUBLICNearProc,FarProc
END
Assembler per 8086 - 35 Direttiva EXTRN
Rende accessibili uno o più simboli definiti in un altromodulo
EXTRN nome:tipo [, nome:tipo ...]
nome è il nome di un simbolo definito PUBLIC in unaltro modulotipo è il tipo del simbolo:•BYTE, WORD, ...•NEAR, FAR, ...
EXTRNMemVar:WORD,MemArr:BYTEEXTRNNearProc:NEAR,FarProc:FAR. . .MOVAX, MemVarMOVBX, OFFSET MemArr. . .CALLNearProcCALLFarProc
Assembler per 8086 - 36 ATTENZIONE
Attenzione alla corrispondenza dei tipi
PUBLICFarProcFarProcPROCFAR. . .RETFarProcENDP
EXTRNFarProc:Near; ERRORE!. . .CALLFarProc. . .
Attenzione alle maiuscole/minuscole
Usare i qualificatori /ml o /mx insieme a TASM
Assembler per 8086 - 37
PR O CEDURE
EF UN Z IO N I
myprog1 segment public 'CODE'nome procCALL proced...nome endpmyprog1 ends
myprog2 segment public 'CODE'proced proc FAR...RETproced endpmyprog2 ends
U S O d e ll o S T ACK
1)per la valutazione di espressioni aritmetiche2) per procedure innestate (ricorsive)la CALL inserisce nello stack l'indirizzo di ritorno;la RET estrae ordinatamente e lo ripristina.3) passaggio dei parametripassati per valoreo per indirizzo4) variabili locali
Assembler per 8086 - 38
S T ACK fr a m e
Possibile uso dello stackOgni procedura riserva il proprio record di attivazioneseparato da quello del chiamante
record di attivazioneCLIENTE SERVITORE
parametri del chiamante
spazio per levariabili locali spazio per ilsalvataggiodei registri
Assembler per 8086 - 39
P ro to c o llo ch ia m an te /ch ia m a to
Il programma cliente (chiamante) deve eseguire:PUSH par1PUSH par2CALL proceduraPOP uscita ; parametro di uscita sullo stackLa procedura chiamata (servitore)procedura PROC farPUSH BPMOV BP,SP ; un nuovo frameSUB SP,10 ; spazio per le variabili locali; usate come [BP - i] con i = 2, 4, 6,...PUSH AX ; salvataggio registri clientePUSH BX ; che il chiamato utilizzaMOV AX, [BP+6] ; recupero dei parametriMOV BX, [BP+8] ; il primo parametro< fase di elaborazione ed esecuzione >MOV [BP+8], parametrouscita; il parametro di uscita ricopre l'ingressoPOP BX ; ripristino dei valori nei registriPOP AX ;MOV SP,BP ; recupero variabili localiPOP BP ; si ristabilisce il vecchio frameRET 2 ; eliminazione parametro ingressoprocedura ENDP
Assembler per 8086 - 40
G e ra rch ia pe r le in te rr u z ion i, con p ri o rit à dec rescen te :
- interrupt interni (o di errore)- interrupt non mascherabili- interrupt mascherabili esterni- interrupt di single-step.
Al verificarsi di più interruzioni "insieme"===>
p ri o ri tà
Routine di interruzione breviod almenotempo di disabilitazionedelle interruzioni esternedeve essere limitato al minimo
Protocollo di uso dello stack per interruzionianalogo a quello per le procedure ===>per garantire innestamento corretto
Assembler per 8086 - 41 SCHEMA DI UN PROGRAMMA ASSEMBLER
in FILE1.asm
code1 segment 'CODE' assume cs: code1, ds: data1, ss:stack1proced1 proc far...proced1 endpproced2 proc near...proced2 endpcode1 ends
code2 segment 'CODE'assume cs: code2, ds: data1, ss:stack1proced3 proc far...proced3 endpcode2 endsdata1 segment 'DATA'.... ; definizione dei dati globalidata1 ends
stack1 segment stack 'STACK'... ; definizione del segmento stackstack1 endsend
Assembler per 8086 - 42 ESEMPIO di funzione ricorsiva- sviluppata in un unico file;
Il sistema operativo fornisce le funzioni diinput/output
function f91 (x:integer):integer;begin if x > 100 then f91 := x - 10else f91 := f91 (f91( x + 11))endif;end f91;
Input di un unico caratterefunzione di sistema operativo (BIOS):
valore fornito con <alt><cifre dalla tastiera numerica>Output di caratteri
stampa degli ascii corrispondentiLa stringa (inversa) di caratteri ascii usando funzioni disistema (DOS)
code1segment para public 'CODE'progproc farassumecs:code1,ds:code1,ss:stack1pushds; salvataggio dell'indirizzo disubax,ax; ritorno al sistema operativopushax; all'indirizzo di offset 0; del programma; il programma è visto come una procedura del; sistema operativo: si termina con una RET
Assembler per 8086 - 43 movax,0int16h; attesa di un carattere da consolemovah,0pushax; il parametro di input nello stackcallf91;procedure vicine;(cs non variato)popaxcallbintoasci; converti e stamparetprogendp
f91proc near ; nuovo frame sullo stackpushbpmovbp,sp ;pushax; salvataggio valore di axmovax, [bp+4]; recupero del valore del parametrocmpax,100jbericorri; se inferiore, ricorrisubax,10mov [bp+4], ax ; valore di ritornopop axpopbpret ; parametro di ritorno sullo stackricorri: ; invocazione ricorsiva
Assembler per 8086 - 44 addax,11; calcolo di f91 ( x + 11)pushaxcallf91popax; calcolo di f91 (f91(x + 11))pushaxcallf91popax; valore di ritornosullo stackmov[bp+4], axpopaxpopbpretf91endp
bintoasciproc ; non crea un nuovo stack framecomment* stampa gli ascii per il binario in AXin ordine inverso + cr e lf*pushdx ; salvataggio registri utilizzatipushsipushaxmovsi,10 ; divisioni successiveagain: subdx,dx ; i caratteri sono scrittidivsi ; in ordine inversoadddx,'0' ; la cifra di resto in asciicallstampa; output di un carattereorax,axjnzagain
Assembler per 8086 - 45 movdl, 0dh ; stampa <cr>callstampamovdl, 0ah ; stampa <lf>callstampapopaxpopsipopdxretbintoasci endp
stampaproc; stampa di un carattere; il carattere è in dl (DX)pushax ; salvataggio valore registro AXpushdx ; e DXmovah,2 ; carattere in dlint 21h ; interrupt al DOSpopdxpopaxretstampaendpcode ends
stack1segment 'STACK'db 100 dup('stack ')stack1ends ; segmento di stackend
Assembler per 8086 - 46
PR O T O C O LL O C L IEN T E /SERV IT O RE
Passaggio di parametri
➊ mediante registri
MOVCX, 5MOVDL, 'A'CALLdisplay ; visualizza "AAAAA"
➋ mediante stack (convenzione C)
func(i,k,22)
MOVAX, 22PUSHAXPUSHkPUSHiCALL_funcADDSP, 6
Assembler per 8086 - 47 Accesso ai parametri passati sullo stackChiamata NEAR
SPoffset di ritornoSP + 2iSP + 4kSP + 622
_funcPROCNEARPUSHBPMOVBP, SP
SPvecchio valore di BPBPSP + 2offset di ritornoBP + 2SP + 4iBP + 4SP + 6kBP + 6SP + 822BP + 8
MOVAX, [BP+4]; primo argomentoADDAX, [BP+6]; secondo argomentoSUBAX, [BP+8]; terzo argomentoPOPBPRET_funcENDP
Assembler per 8086 - 48 Chiamata FAR
SPoffset di ritornoSP + 2segmento di ritornoSP + 4iSP + 6kSP + 822
_funcPROCFARPUSHBPMOVBP, SP
SPvecchio valore di BPBPSP + 2offset di ritornoBP + 2
SP + 4segmento di ritornoBP + 4SP + 6iBP + 6SP + 8kBP + 8SP + 1022BP + 10
MOVAX, [BP+6]; primo argomentoADDAX, [BP+8]; secondo argomentoSUBAX, [BP+10]; terzo argomentoPOPBPRET_funcENDP
Assembler per 8086 - 49 Variabili locali sullo stack
_funcPROCNEARPUSHBPMOVBP, SP;;Servono 2 variabili locali di tipo "short int";SUBSP, 4; riserva 4 byte sullo stack
SP2° variabile localeBP – 4
SP + 21° variabile localeBP – 2SP + 4vecchio valore di BPBPSP + 6offset di ritornoBP + 2SP + 81° argomentoBP + 4SP + 102° argomentoBP + 6SP + 123° argomentoBP + 8
MOVWORD PTR [BP-2], 0MOVWORD PTR [BP-4], 0. . .MOVSP, BPPOPBPRET_funcENDP
Assembler per 8086 - 50 Esempio
typedef struct{int giorno,mese,anno;} DataType;
void fun(DataType *dpar){DataType dtemp;dtemp.giorno = dpar->giorno;dtemp.mese = dpar->mese;dtemp.anno = dpar->anno;}
_funprocnearpushbpmovbp,spsubsp,6; 6 = sizeof(DataType)pushsimovsi,word ptr [bp+4]; dparmovax,word ptr [si]; ax <- dpar->giornomovword ptr [bp-6],ax; dtemp.giorno <- axmovax,word ptr [si+2]; ax <- dpar->mesemovword ptr [bp-4],ax; dtemp.mese <- axmovax,word ptr [si+4]; ax <- dpar->annomovword ptr [bp-2],ax; dtemp.anno<- axpopsimovsp,bppopbpret_funendp
Assembler per 8086 - 51 Schema Generaledi una procedura assembler(convenzione C)
_funprocnear (o far)pushbpmovbp,sp;;allocazione spazio su stack per variabili locali;subsp,xxx;;eventuale salvataggio registri;in uscita devono avere il vecchio valore:;BP, SP, CS, DS, SS, DI, SI;in uscita possono non avere il vecchio valore:;AX, BX, CX, DX, ES e il registro flag;pushdi; se utilizzatopushsi; se utilizzato;;procedura;. . .;;ripristino registri;popsipopdimovsp, bp; ripristino sppopbp; ripristino bpret_funendp
Assembler per 8086 - 52 Restituzione di valori
In AX vengono restituiti i valori a 8 e a 16 bit:[unsigned] char[unsigned] intnear *
int fun1(){. . .return 1;}
movax,1
In DX:AX vengono restituiti i valori a 32 bit:[unsigned] longfar *
long fun2(){ . . .return 1;}
xordx,dxmovax,1
E per parametri di dimensioni maggiori?vedi restituzione di un record C
Assembler per 8086 - 53 Passaggio di parametri
➌ mediante stack (convenzione Pascal)
func(i,k,22)
PUSHiPUSHkMOVAX, 22PUSHAXCALLFUNC; maiuscolo senza _;ADDSP, 6non esiste più !
Il chiamante non deve estrarre gli argomentiche devono essere estratti dal chiamato
Il chiamato deve sapere quanti parametri estrarre
Assembler per 8086 - 54 Accesso ai parametri passati sullo stackChiamata NEAR (convenzione Pascal)
SPoffset di ritornoSP + 222SP + 4kSP + 6i
funcPROCNEARPUSHBPMOVBP, SP
SPvecchio valore di BPBPSP + 2offset di ritornoBP + 2SP + 422BP + 4SP + 6kBP + 6SP + 8iBP + 8
MOVAX, [BP+8]; primo argomentoADDAX, [BP+6]; secondo argomentoSUBAX, [BP+4]; terzo argomentoPOPBPRET6; ret + add sp,6funcENDP
Assembler per 8086 - 55
MO DE LL I D I M E MO R IA
Accesso contemporaneo a 4 segmenti di 64k byte
1 segmento codice - istruzione da eseguire in CS:IP1 segmento stack - top dello stack in SS:SP2 segmenti per i dati del programma - DS e ES
Programmazione in un linguaggio ad alto livellosi sceglie una delle configurazione di segmenti (modellidi memoria) fornite dal compilatore
6 modelli di memoria di complessità crescente:•modello tiny1 solo segmento per codice, dati, stack e heap•modello small1 segmento codice, 1 segmento per dati, stack e heap•modello compact1 segmento codice, 1 segmento dati, 1 segmento perlo stack e più segmenti per l'heap•modello medium•modello large•modello hugepiù segmenti codice e più segmenti dati
Scelta in funzione:• della dimensione del codice• della dimensione dei dati
Assembler per 8086 - 56 Programmazione in assemblersi può scegliere una qualsiasi configurazione disegmenti, utilizzando in modo opportuno la direttivaSEGMENT
Programmazione inassembler + linguaggio ad alto livelloil codice assembler deve utilizzare lo stesso modello dimemoria scelto per compilare il codice ad alto livello
Esempio utilizzato nel seguito: 2 moduli: P.C e S.ASM
Modulo P.C:
void main() { printf("%d\n",lung("Modelli di memoria!")); }
Modulo S.ASM - sottoprogramma e dati statici - il suocontenuto varia al variare del modello di memoriapuò essere espresso in C nel seguente modo:
static char cc = ',';/* variabili statiche */static int j;/* per esemplificazione */
lung(char *str) { if(*str == cc) return 0; for (j = 0; *str++; j++) ; return j; }
Assembler per 8086 - 57 Segmento stack ed eventuali segmenti checompongono l'heap sono automaticamente definiti egestiti a livello superiore (C e DOS)
In alcuni modelli di memoria, segmento dati diviso in:
segmento _DATA - contiene le variabili cui è statoassegnato un valore iniziale (variabile cc)
segmento _BSS - contiene le variabili che non sonostate espressamente inizializzate (variabile j) - il suocontenuto viene automaticamente posto a 0 dal loader
D ir e tti va G R O UP
Permette di riunire un insieme di segmenti in un unicosegmento, accessibile mediante un unico registro disegmento:
nome GROUP nome1 [, nome2 ...]
dove:•nome è il nome simbolico del gruppo di segmenti•nome1, nome2, ... sono i nomi dei segmenti chedevono essere uniti
Assembler per 8086 - 58 Esempio - Per riunire segmento dati e segmento stack inun unico segmento di nome DGROUP:
DGROUPGROUP _Data,_Stack
_DataSEGMENT WORD PUBLIC 'DATA'definizione dei dati del programma_DataENDS
_StackSEGMENT WORD STACK 'STACK'dimensionamento dello stack_StackENDS
_CodeSEGMENT BYTE PUBLIC 'CODE'ASSUMECS:_Code,SS:DGROUP,ES:NOTHINGStart:MOV AX,DGROUPMOV DS,AXASSUME DS:DGROUPcodice_CodeENDS
Assembler per 8086 - 59
M ode ll o d i m e m o ri a T INY
Riferimenti al codice e ai dati mediante il solo offset nelsegmento - puntatori near
Contenuto di S.ASM:
DGROUPgroup_DATA,_BSS
_DATAsegment word public 'DATA'ccdb','_DATAends
_BSSsegment word public 'BSS'jdw?_BSSends
_TEXTsegment byte public 'CODE'assume cs:_TEXT,ds:DGROUP
Assembler per 8086 - 60 _lungprocnearpushbpmovbp,sppushsimovsi,word ptr [bp+4]; si <- str
;if(*str == cc) return 0;
moval,byte ptr [si]; al <- *strcmpal,byte ptr DGROUP:ccjneforxorax,ax; return 0jmpshort fine
;for (j = 0; *str++; j++) ;
for:movword ptr DGROUP:j,0cicla:movbx,siincsi; str++cmpbyte ptr [bx],0jzfine1incword ptr DGROUP:jjmpciclafine1:movax,word ptr DGROUP:j ; return jfine:popsipopbpret_lungendp_TEXTendspublic_lung; visibilità cc e j limitataend
Assembler per 8086 - 61
M ode ll o d i m e m o ri a S M A LL
Riferimenti al codice e ai dati mediante il solo offset nelcorrispondente segmento - puntatori near
Contenuto di S.ASM:
identico a quello relativo al modello TINY
Assembler per 8086 - 62
M ode ll o d i m e m o ri a C OM PAC T
Riferimenti al codice mediante il solo offset nelcorrispondente segmento - puntatori near
Riferimenti ai dati mediante puntatori far(segmento:offset) - occorre gestire in modo uniformeriferimenti a dati che possono essere memorizzati:• nel segmento dati• nel segmento stack• in uno dei segmenti che compongono l'heap
Assembler per 8086 - 63 Contenuto di S.ASM:. . ._lungprocnearpushbpmovbp,sppushsilessi,dword ptr [bp+4] ; es:si <- str
;if(*str == cc) return 0;
moval,byte ptr es:[si]; al <- *strcmpal,byte ptr DGROUP:ccjneforxorax,ax; return 0jmpshort fine
;for (j = 0; *str++; j++) ;
for:movword ptr DGROUP:j,0cicla:movbx,siincsi; str++cmpbyte ptr es:[bx],0jzfine1incword ptr DGROUP:jjmpciclafine1:movax,word ptr DGROUP:j ; return jfine:popsipopbpret_lungendp. . .
Assembler per 8086 - 64
M ode ll o d i m e m o ri a M ED IU M
Riferimenti al codice mediante mediante puntatori far
Riferimenti ai dati mediante puntatori near
Il nome di ogni segmento codice è formato dal nome delfile contenente il codice (F1, ..., Fn), seguito da _TEXTIl registro CS punta sempre al segmento che contiene ilcodice correntemente in esecuzione
Contenuto di S.ASM:
. . .S_TEXTsegment byte public 'CODE'assume cs:S_TEXT,ds:DGROUP
Assembler per 8086 - 65 _lungprocfarpushbpmovbp,sppushsimovsi,word ptr [bp+6]; si <- str
;if(*str == cc) return 0;
moval,byte ptr [si]; al <- *strcmpal,byte ptr DGROUP:ccjneforxorax,ax; return 0jmpshort fine
;for (j = 0; *str++; j++) ;
for:movword ptr DGROUP:j,0cicla:movbx,siincsi; str++cmpbyte ptr [bx],0jzfine1incword ptr DGROUP:jjmpciclafine1:movax,word ptr DGROUP:j ; return jfine:popsipopbpret_lungendpS_TEXTendspublic_lungend
Assembler per 8086 - 66
M ode ll o d i m e m o ri a L AR G E
Riferimenti al codice e riferimenti ai dati mediantepuntatori far
Il contenuto di S.ASM coincide con:•quello relativo al modello medium per quanto riguardail codice - procedura far e segmento di nome S_TEXT•quello relativo al modello compact per quantoriguarda i dati - riferimenti far e override di segmento
Assembler per 8086 - 67
M ode ll o d i m e m o ri a HU G E
Riferimenti al codice e riferimenti ai dati mediantepuntatori far
Il nome di ogni segmento dati è formato dal nome del filecontenente il codice (F1, ..., Fn), seguito da _DATAIl registro DS deve puntare al segmento che contiene idati corrispondenti al codice in esecuzione
Assembler per 8086 - 68 Contenuto di S.ASM:
unico segmento S_DATA contenente dati inizializzatiassenza del segmento _BSS
S_DATAsegment word public 'DATA'ccdb','db0; allinea j alla wordjdw0S_DATAends
S_TEXTsegment byte public 'CODE'assume cs:S_TEXT,ds:S_DATA_lungprocfarpushbpmovbp,sppushdsmovax,S_DATAmovds,axpushsilessi,dword ptr [bp+6]; es:si <- str. . .fine:popsipopdspopbpret_lungendpS_TEXTendspublic_lungend
Assembler per 8086 - 69
R iep il ogo
Modello dimemoria Riferimential codice Riferimentiai dati Dimensione applicazione
Tinynearnearcodice + dati <= 64k
Smallnearnearcodice <= 64k + dati <= 64k
Compactnearfarcodice • 64k + dati <= 1M
Mediumfarnearcodice <= 1M + dati <= 64k
Largefarfarcodice + dati <= 1M
Hugefarfarcodice + dati <= 1M
Assembler per 8086 - 70
SV IL UPP O D I UN PR OG RA MM A
•COMPILATOREtraduce un modulo sorgente (file) scritto in linguaggioad alto livello (ad es. C, Pascal, ...) in codice rilocabilema non eseguibile (modulo oggetto)
•ASSEMBLATOREtraduce un modulo sorgente (file) scritto in linguaggioAssembler in codice rilocabile ma non eseguibile(modulo oggetto)
•LINKER (Collegatore)collega tra loro i vari moduli oggetto e crea un moduloeseguibile
•LOADER (Caricatore)carica in memoria il modulo eseguibile
•DEBUGGERcontrolla l'esecuzione del programma in fase di messaa punto
Assembler per 8086 - 71
C OM P IL A T O RE
FASE DI ANALISI:•analisi lessicale (scanner) - esamina i caratteri delsorgente e genera i simboli (atomici) del programma(identificatori, parole riservate, ecc.)•analisi sintattica (parser) - stabilisce se il programmaè sintatticamente corretto•analisi semantica - stabilisce se il programma èsemanticamente corretto{int x; char x[4]; ...sintatticamente correttosemanticamente errato
FASE DI SINTESI:•preparazione alla generazione del codice:-ottimizzazione rispetto:-l'occupazione di memoria-il tempo di esecuzione•generazione del codice (in forma rilocabile)•eventuale ottimizzazione finale del codice (peepholeoptimization)addax, 14 clock, 4 byteincax3 clock, 1 byte - CF inalterato
Assembler per 8086 - 72 TAVOLE DI INFORMAZIONE:•contengono tutte le informazioni ottenute durante lafase di analisi:-dichiarazioni di procedure-dichiarazioni di variabili-cicli-ecc.•il numero di tavole dipende:-tipo di linguaggio sorgente-tipo di codice oggetto da generare-grado di complessità del compilatore
TAVOLA DEI SIMBOLI (Symbol Table)di ogni identificatore che compare nel modulo sorgentecontiene:•il nome simbolico•il tipo (procedura, variabile intera, array di reali, label, ...)•la visibilità (statico, pubblico, esterno, ...)•la posizione (offset) nel segmento che lo contiene•ecc.
Assembler per 8086 - 73
ASSE M B L A T O RE
Può essere a 1 o più passi:•ad ogni passo viene effettuata una scansione delprogramma sorgente•in genere a 2 passi•TASM è a 1 passo (default)
1 PASSO (analisi):•riconoscimento delle macro e loro espansione•riconoscimento delle direttive•riconoscimento delle istruzioni ammesse•creazione della Symbol Table - aggiornamento di uncontatore per ogni segmento
2 PASSO (sintesi):•traduzione del programma (utilizzo della tabellacontenente i codici operativi)•sostituzione degli operandi simbolici con icorrispondenti indirizzi (rilocabili)•segnalazione di identificatori non definiti•generazione listato•generazione istruzioni speciali per il linker - simbolipubblici o esterni
Assembler per 8086 - 74 IL MODULO OGGETTO
Ogni modulo oggetto contiene:•informazioni necessarie al collegamento con altrimoduli (anche librerie di sistema, non interruptsoftware) - ESD (External Symbol Dictionary)•informazioni necessarie alla rilocazione•istruzioni macchina e dati generati dalla traduzione delsorgente
Modulo X.ASMModulo Y.ASM
C segment byte public 'CODE'
A1proc
. . .
call B1
. . .
public A1
extrn B1:near C segment byte public 'CODE'
B1proc
. . .
call A1
. . .
public B1
extrn A1:near
Modulo X.OBJModulo Y.OBJ
A1procpublicC:0B1procextrn?Informazioni sugli oggetti chepossono dover essere rilocati
Istruzioni e dati inizializzati A1procextrn?B1procpublicC:0Informazioni sugli oggetti chepossono dover essere rilocati
Istruzioni e dati inizializzati