Architettura dei Calcolatori 08 Assembler

2,259 views

Published on

Published in: Technology, Business
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
2,259
On SlideShare
0
From Embeds
0
Number of Embeds
7
Actions
Shares
0
Downloads
85
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Architettura dei Calcolatori 08 Assembler

  1. 1. Dispense del corso di Architettura dei Calcolatori Intel 8086/8 – ISA e Assembly
  2. 2. a.a. 2007/2008 Architettura dei calcolatori Intel 8086 Bus indirizzi (20bit) AX BX CX DX SP BP Bus dati (16bit) DI CS SI DS ES SS IP BUS Internal cntr. Temporary regs. Instruction queue EU ALU cntr. FLAGS BIU EU
  3. 3. a.a. 2007/2008 Architettura dei calcolatori I registri della CPU 8086 • Il set di registri è la parte più importante di ciò che è visibile dal programmatore o al compilatore • Registri sono divisi in: – General Purpose Registers, – Segment Registers, – Miscellaneous Registers Registers. • I General Purpose Registers hanno in realtà uno scopo ben preciso insito nel loro nome (non ortogonali) , anche se molte istruzioni consentono di utilizzare i registri generici indipendentemente dal loro scopo primario. • I registri sono AX BX CX DX SI DI BP SP AX, BX, CX, DX, SI, DI, BP, SP. • Questi sono registri a 16 bit e per i primi 4 è possibile accedere direttamente agli 8 bit più significativi (parte alta/high) o agli 8 bit meno significativi (parte bassa/low) specificando H o L invece che X. Cioè, per esempio, CL è il registro a 8 bit corrispondente alla parte bassa di CX, mentre AH è la parte alta di AX.
  4. 4. a.a. 2007/2008 Architettura dei calcolatori I registri generici • AX è l’accumulatore: serve per numerose operazioni matematiche, o di I/O o per speciali trasferimenti di dati. • BX è il registro base: serve per contenere l’indirizzo di partenza durante gli indirizzamenti in memoria. • CX è il registro di conteggio: serve per effettuare conteggi durante cicli o ripetizioni ripetizioni. • DX è il registro dati: per contenere parte di dati eccedenti durate le operazioni aritmetiche(in coppia con AX) e per g indirizzi delle istruzioni di I/O. ) gli • SI e DI sono registri indice utilizzati principalmente durante le operazioni con stringhe di byte. Tipicamente SI punta alla sorgente, mentre DI punta alla destinazione. • BP è il puntatore base e, in modo molto simile a BX, serve come indirizzo di partenza(principalmente entro lo stack), tipicamente durante l’accesso a parametri e variabili di funzioni. • SP è il puntatore allo stack: l’8086 ha istruzioni per la gestione di questa struttura dati direttamente nella sua architettura e questo registro viene implicitamente referenziato da tutte queste istruzioni. istruzioni
  5. 5. a.a. 2007/2008 Architettura dei calcolatori I registri di segmento • Senza entrare nel dettaglio del funzionamento dei segmenti, tali registri sono stati definiti perchè l’Intel si trovò di fronte al problema di indirizzare 1MB di memoria e che per motivi di progetto ed economici decise di non utilizzare registri a 20bit, ma di combinare opportunamente due registri a 16bit 16bit. • Esistono quindi 4 registri di segmento che hanno la funzione di suddividere la memoria in parti relative ai dati in esse contenuti: – CS è l’indirizzo del segmento codice, cioè l’area di memoria da cui vengono lette le istruzioni da eseguire. – DS è l’indirizzo del segmento dati, cioè l’area di memoria che contiene le variabili o le costanti necessarie al programma. – ES è l’indirizzo del segmento ausiliario che consente di disporre rapidamente di ulteriore spazio per i dati senza dovere continuamente modificare DS. – SS è l’indirizzo del segmento di stack. • L’utilizzo dei segmenti consente una notevole flessibilità, ma complica notevolmente la progettazione del software in particolare per le strutture dati di software, dimensioni superiori ai 64KB.
  6. 6. a.a. 2007/2008 Architettura dei calcolatori Registri speciali • Esistono due ulteriori registri speciali che non vengono modificati direttamente dal programmatore, ma sono fondamentali per l’esecuzione del software: – IP è l’instruction pointer, cioè l’indirizzo, all’interno del code segment dal quale prelevare la prossima istruzione.Specifica l’offset della successiva istruzione da eseguire in riferimento al segmento codice g g corrente. – FLAG è un registro a 16 bit nel quale ogni bit (9 utilizzati nel 8086) ha un significato speciale che indica la modalità di funzionamento del software, lo stato del sistema o il risultato dell’istruzione precedente. • Le istruzioni possono fare riferimento a tutti i registri generali e di segmento per leggerne o scriverne il valore, con l’eccezione di CS che può solo essere letto. • Non è possibile fare riferimento a IP o a FLAG, perché questi sono implicitamente o esplicitamente modificati da istruzioni apposite. • CS:IP e’ il corrispondente del Program Counter nella micro architettura
  7. 7. a.a. 2007/2008 Architettura dei calcolatori Il registro FLAG 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 OF DF IF TF SF ZF AF PF CF • Ecco una breve descrizione del significato dei singoli bit: Flag di Stato: – Overflow(OF): Indica che operazione ha riportato un risultato troppo grande – Sign(SF): Viene posto a 1 se il risultato di una operazione è negativo – Z (ZF) Vi Zero(ZF): Viene messo a 1 se il risultato di una operazione è 0 i lt t i – Auxiliary Carry(AF): Indica un riporto o un prestito tra la parte bassa e quella alta di un numero. Viene usato dalle istruzioni aritmetico decimale. – Parity Flag(PF): Posto a 1 quando c’è un numero pari di bit a 1 nel risultato cè dell’operazione. Utilizzato dai programmi di comunicazione. – Carry Flag(CF): Indica un riporto o un prestito nella parte alta dell’ultimo risultato. Serve per realizzare istruzioni multi word. Flag di Controllo: – Direction(DF): Indica se decrementare o incrementare per le istruzioni con le stringhe. Indica se la stringa viene letta/scritta a p g partire dall’elemento con indirizzo piu’ p alto/basso – Interrupt Enable(IF): Indica se le interruzioni mascherabili sono abilitate – Trap(TF): Questo flag è usato dai debugger per eseguire i p g p( ) g gg p g programmi un p passo alla volta. Genera un INT 3 dopo ogni istruzione
  8. 8. a.a. 2007/2008 Architettura dei calcolatori Assemblatore Intel • Il codice macchina è una sequenza numerica che codifica le istruzioni e gli operandi. Ad esempio, il codice operativo 8A 49 E4 indica di copiare il byte contenuto all’indirizzo di memoria dato da BX+DI-28 nel registro CL. • Non N è molto comodo programmare calcolando il codice macchina, per questo motivo si lt d lld di hi t ti i utilizza un programma che traduce le istruzioni da una forma testuale più comprensibile al programmatore nel codice macchina. • L’istruzione precedente p allora essere scritta come: p può mov cl,[bx+di-28] • Non esiste purtroppo un accordo ufficiale sulla sintassi che deve essere rispettata da un assemblatore ed esistono diverse varianti per lo stesso codice operativo. – Ad esempio l’istruzione precedente, con il Microsoft Macro Assembler (MASM), può essere scritta come mov cl,[bx+di]-28 o mov cl,[bx][di][-28] o mov cl,[di][-28][bx], ecc... • Un altro pacchetto disponibile e’ il “flat assembler” (FASM) un assemblatore che può essere utilizzato gratuitamente e del quale sono disponibili i sorgenti in rete. • Per i dettagli sulla sintassi di questo assemblatore si rimanda alla documentazione Solo per chiarezza, per coloro che hanno utilizzato altri assemblatori, notiamo che la sintassi degli indirizzi è molto più rigida: quando si specifica un operando in memoria questo deve essere compreso tra parentesi quadre e all’interno delle parentesi possono comparire registri, etichette e valori immediati separati da “più”. Inoltre nella dichiarazione di dati la direttiva dup viene sostituita da times che ha una sintassi leggermente diversa.
  9. 9. a.a. 2007/2008 Architettura dei calcolatori Linguaggio macchina ed assembler • Linguaggio macchina è binario • Linguaggio assembler è in forma simbolica; • Il formato di una istruzione in assembler è il seguente: Etichetta: Mnemonico Operando1, Operando2; Commento • Etichetta – è un identificatore (stringa) cui è assegnato l’indirizzo del primo byte dell’istruzione alla quale si riferisce – Può servire come nome simbolico cui riferirsi nei salti condizionati e incondizionati • Mnemonico – indica l’operazione vera e propria • es: operazione di somma => ADD i > • Operando – la presenza dipende dall’istruzione – possiamo avere istruzioni con 1 2 o nessun operando 1, • Commento – Se non presente il punto e virgola può essere omesso
  10. 10. a.a. 2007/2008 Architettura dei calcolatori Regole di Sintassi - Costanti numeriche • Un numero con suffisso che indica la base: – B o b (binario), – D o d (decimale) (decimale), – O o o (ottale), – H o h (esadecimale). • Per default la base è d i l P d f lt l b decimale • In caso di base esadecimale la prima cifra a sx deve essere compreso tra 0 e 9 es: BC2H deve essere scritto 0BC2H altrimenti verrebbe confusa con una stringa. g • Esempi corretti: – 0FFh – 0h – 777O – 11001B • Esempi errati: – FFh errata ! t – 778O errata
  11. 11. a.a. 2007/2008 Architettura dei calcolatori Dichiarazione dei dati • Sintassi: – <nome var> <mnemonico> op1, op2,… ;commento • Lo mnemonico determina la dimensione in byte – DB (define byte) ogni operando occupa 1 byte – DW (define word) ogni operando occupa 1 word = 2bytes ( )g p p y – DD (define double word) occupa 2 word = 4bytes • Gli operandi possono essere dei valori o espressioni costanti • Per riservare lo spazio di memoria si usa “?” ? • Esempio: DATA_SEG SEGMENT DATA_BYTE DATA BYTE DB 10,4,10H 10 4 10H DATA_WORD DW 100,?,-5 DATA_DW DD 3*20,0FFFDH DATA_SEGMENT ENDS • Individuano 3 aree di memoria contigue lunghe ciascuna: 3 bytes, 6 bytes e 8 bytes • Come definire un “array” – <nome var> DB | DW| DD <dim> DUP (<elementi>) | ( ) • duplica gli <elementi> specificati il numero di volte specificato da dim
  12. 12. a.a. 2007/2008 Architettura dei calcolatori Modalità di Indirizzamento • Esistono molti modi per indicare nell’istruzione dove trovare l’operando • REGISTRO: l’operando si trova in un registro • IMMEDIATO: l’operando è nella istruzione • MEMORIA se è i memoria, ci sono di in i i diversi modi di calcolare i di ll MEMORIA: l’indirizzo; alcune CPU prevedono molte modalità, maggiore flessibilità e diminuzione del numero delle istruzioni; ma questo implica reti logiche più complesse nella gestione ed un codice operativo con più bit
  13. 13. a.a. 2007/2008 Architettura dei calcolatori Metodi di indirizzamento in Memoria Intel • Oltre che ai registri è possibile accedere alla memoria e questo può essere fatto in 17 modi di indirizzamento (8086) per specificare un indirizzo di memoria. Questi possono essere raggruppati in 3 categorie: – Indirizzamento diretto: si specifica l’indirizzo di memoria tramite un valore p numerico detto displacement, cioè spostamento. – Indirizzamento indiretto tramite registro base: si specifica l’indirizzo di memoria tramite il valore contenuto in uno tra i registri base BX o BP. – Indirizzamento indiretto tramite registro indice: si specifica l’indirizzo di memoria tramite il valore contenuto in uno tra i registri indice SI o DI. • È possibile combinare queste tre modalità ottenendo tutte le possibili combinazioni. Per ricordare le combinazioni valide è sufficiente memorizzare la tabella seguente (ognuno dei tre elementi può non essere presente): BX SI Disp + + BP DI • Le modalità di indirizzamento viste si riferiscono sempre e solo al calcolo dell’offset, ovvero di un valore a 16 bit dato dalla somma dei tre possibili campi. A queste si deve sommare, scalato l’indirizzo di segmento (modello di memoria segmentato)
  14. 14. a.a. 2007/2008 Architettura dei calcolatori Modi di indirizzamento di I/O Intel L’architettura INTEL ha uno spazio di indirizzamento specifico per l’I/O ed istruzioni specifiche per accedervi. Indirizzamento DIRETTO L indirizzo L’indirizzo può essere solo a 8 bit nell’istruzione (fino a 256 indirizzi diversi). nell istruzione AL serve per contenere il dato (a 8 bit) in AL,PORTA1 ; AL I/O[PORTA1] out PORTA2,AL ; I/O[PORTA2] AL Indirizzamento INDIRETTO con registro DX L’indirizzo è a 16 bit ed è nel registro DX g in AL,DX ; AL I/O[DX] out DX,AL ; I/O[DX] AL
  15. 15. a.a. 2007/2008 Architettura dei calcolatori Insieme delle istruzioni 8086 • Possiamo suddividere le istruzioni 8086 in gruppi funzionali: – Trasferimento di dati – Trasferimento di controllo – Aritmetica binaria – Logica binaria – Shift e Rotate – Operazioni su stringhe di dati – Istruzioni per il controllo dei flag g – Aritmetica decimale (Binary Coded Decimal) – Varie • Di seguito esamineremo ogni gruppo di istruzioni, rimandando per i dettagli sulla sintassi alle guide elettroniche fornite sul sito.
  16. 16. a.a. 2007/2008 Architettura dei calcolatori Trasferimento di dati • Fanno parte di questo gruppo: – MOV dest,sorg Sposta il contenuto del secondo operando nel primo – XCHG dest,sorg Scambia il contenuto dei due operandi – PUSH word Inserisce una word nello stack – POP word Estrae una word dallo stack – IN accum,porta Legge un dato dalla porta specificata – OUT porta,accum Scrive un dato sulla porta specificata • L istruzione L’istruzione MOV è certamente la più usata e semplice da comprendere. XCHG consente di scambiare due registri senza passare per una variabile temporanea. • È importante notare che non è possibile muovere o scambiare dati tra memoria e memoria, ma solo tra memoria e registri/valori. • Le istruzioni di IN e OUT consentono di accedere ai registri delle periferiche collegate al bus di sistema.
  17. 17. a.a. 2007/2008 Architettura dei calcolatori Trasferimento di dati (2) • Le istruzioni PUSH e POP lavorano con lo stack. Per la precisione, l’istruzione PUSH AX è equivalente a: SP = SP - 2 [SS:SP] = AX Mentre POP AX equivale a: AX = [SS:SP] = AX [ ] SP = SP + 2 • Quello che può sembrare strano è il fatto che il puntatore allo stack venga decrementato ad ogni inserimento. In realtà questo consente una modalità di programmazione molto compatta (nota anche come Modello di memoria Tiny) in cui tutti i segmenti hanno lo stesso valore, i dati seguono immediatamente il codice e lo stack parte dalla fine del segmento: 0 FFFF Codice Dati … Stack • Questo modello di memoria ha un chiaro svantaggio, cioè limita il programma e tutti i suoi dati ad un massimo di 64KB, ma elimina la necessità di occuparsi della segmentazione.
  18. 18. a.a. 2007/2008 Architettura dei calcolatori Trasferimento di controllo • Fanno parte di questo gruppo: – CALL ind Esegue la procedura all’indirizzo ind – RET Ritorna da una procedura – INT num Esegue l’interruzione software num – IRET Ritorna da una interruzione software – JMP ind Salta all’indirizzo ind – Jxx ind Salta all’indirizzo ind se è verificata la condizione xx – LOOP ind Decrementa CX e se non è zero salta a ind – LOOPxx ind Come LOOP, ma salta solo se è verificata xx • L’istruzione più chiara è certamente JMP che può essere considerato un sostituto per “MOV IP i d” e L’i t i iù hi t t JMP, h ò id t tit t IP,ind” che chiarisce il concetto indicando che si “salta” in un’altra zona del programma. • CALL è la versione di JMP che consente di tornare da dove si era venuti. Per fare questo prima del salto viene eseguito un PUSH IP. Se si salta in un altro segmento viene prima salvato CS, poi IP ed infine si salta. RET ritorna alla posizione precedente.
  19. 19. a.a. 2007/2008 Architettura dei calcolatori Trasferimento di controllo (2) • Le istruzioni di salto condizionato sono: JA (JNBE) JAE (JNB) JB (JNAE) JBE (JNA) JE (JNBE), (JNB), (JNAE), (JNA), JE, JG (JNLE), JGE (JNL), JL (JNGE), JLE (JNG), JNE A=above (superiore), B=below (inferiore), E=equal (uguale), G=greater (maggiore), L=less (minore), N=not • Questi salti fanno riferimento al risultato dell’operazione aritmetica CMP (compare) che esegue una sottrazione ed aggiorna i FLAG in modo opportuno. Quindi queste interpretazioni logiche non sono altro che una combinazione dello stato dei FLAG. • Esistono salti che fanno esplicito riferimento ai FLAG: • JC, JNC, JNO, JNP (JPO), JNS, JNZ, JO, JP (JPE), JS, JZ C=carry (riporto), O=overflow, S=sign (segno), Z=zero, P=parity • Esiste inoltre JCXZ che salta se CX è uguale a 0.
  20. 20. a.a. 2007/2008 Architettura dei calcolatori Trasferimento di controllo (3) JNE Jump if Not Equal ZF = 0 Istruzione Descrizione Salta se ... JA Jump if Above CF = 0 e ZF = 0 JNG Jump if Not Greater ZF = 1 o SF ≠ OF JAE Jump if Above or Equal CF = 0 JNGE Jump if Not Greater nor Equal SF ≠ OF JB Jump if Below CF = 1 JNL Jump if Not Less SF = OF JBE Jump if Below or Equal CF = 1 o ZF = 1 JNLE Jump if Not Less nor Equal ZF = 0 e SF = OF JC Jump if Carry CF = 1 JNO Jump if No Overflow OF= 0 JE Jump if Equal ZF = 1 JNP Jump if No Parity (odd) PF = 0 JG Jump if Greater ZF = 0 e SF = OF JNS Jump if No Sign SF = 0 JGE Jump if Greater or Equal SF = OF JNZ Jump if Not Zero ZF = 0 JL Jump if Less SF ≠ OF JO Jump on Overflow OF =1 JLE Jump if Less or Equal JP Jump on Parity (even) PF = 1 ZF = 1 o SF ≠ OF JNA Jump if Not Above CF = 1 o ZF = 1 JPE Jump if Parity Even PF = 1 JNAE Jump if Not Above nor Equal CF = 1 JPO Jump if Parity Odd PF = 0 JNB Jump if Not Below CF = 0 JS Jump on Sign SF = 1 JNBE Jump if Not Below nor Equal CF = 0 e ZF = 0 JZ Jump if Zero ZF = 1 JNC Jump if No Carry CF = 0
  21. 21. a.a. 2007/2008 Architettura dei calcolatori Trasferimento di controllo (4) • L’istruzione LOOP consente di eseguire i tipici cicli di una programmazione strutturata. La variabile di controllo è CX e LOOP è equivalente a un decremento di CX seguito da un salto se CX è diverso CX, da 0. • Esistono inoltre LOOPE (LOOPZ) e LOOPNE (LOOPNZ) che combinano il test CX diverso da 0 con il risultato di una operazione di compare precedente. • Infine l’istruzione INT consente di invocare le interruzioni software, che per ora possiamo considerare come chiamate a funzione tramite un indice numerato. Successivamente nel corso ne capiremo il reale significato. Per ora basti sapere che INT è una CALL far ( g p (cioè inter- segmento) che salva sullo stack anche il registro FLAG. • Per questo motivo esiste un ritorno speciale IRET che prima estrae dallo stack IP e CS e poi anche FLAG FLAG.
  22. 22. a.a. 2007/2008 Architettura dei calcolatori Implementare un If o un While ;if (c==‘5') cmp c,‘5' j jne else char c; ;then-part ... call SeVero if (c==‘5') jmp endif SeVero(); ;else-part ;else part else else: SeFalso(); call SeFalso endif: ;while (n>0) while: cmp n,0 int n; jle end_while ... ;loop body ;loop-body while (n>0) sub n,2 n-=2; jmp while end_while:
  23. 23. a.a. 2007/2008 Architettura dei calcolatori Aritmetica binaria • Fanno parte di questo gruppo: – ADC dest,sorg Add with Carry – ADD d t Addition Additi dest,sorg – CMP dest,sorg Compare – DEC dest Decrement – DIV sorg Divide, Unsigned – IDIV sorg Integer Divide, Signed – IMUL sorg Integer Multiply, Signed – INC dest Increment – MUL sorg Multiply, Unsigned M lti l U i d – NEG dest Negate – SBB dest,sorg Subtract with Borrow – SUB dest,sorg Subtract • Le operazioni più semplici sono certamente INC e DEC che aumentano o diminuiscono di uno il valore di un registro o di una variabile in memoria memoria.
  24. 24. a.a. 2007/2008 Architettura dei calcolatori Aritmetica binaria • Esistono poi ADD e SUB che effettuano somma e sottrazione del secondo operando rispetto al primo e salvano il risultato nel primo. • CMP è identico a SUB però non salva il risultato dato che serve unicamente per SUB, risultato, confrontare il contenuto di due registri e quindi effettua una differenza per impostare i flag, ma non usa il risultato per nessuno scopo. • ADC e SBB sono le versioni di somma e sottrazione che tengono conto di riporto o prestito dell’operazione precedente, utili per effettuare elaborazioni con numeri più grandi di 16 bit. • MUL effettua la moltiplicazione di AL o AX con il byte o word passato come parametro e mette il prodotto rispettivamente in AX o in DX:AX (cioè la parte alta in DX e la parte bassa in AX). IMUL è l’equivalente per numeri con segno. • DIV divide AX o DX AX per il b te o word passate come parametro e mette il di ide DX:AX byte ord quoziente e il resto in AL e AH o in AX e DX. IDIV è l’equivalente per numeri con segno. • Nel caso che il risultato della DIV sia troppo grande per il registro destinazione o che il divisore sia 0, viene generato un INT 0h (Divisione per zero). • La NEG produce il negato del registro passato come parametro.
  25. 25. a.a. 2007/2008 Architettura dei calcolatori Esempio Voglio realizzare la seguente operazione: W = X+Y+24-Z X+Y+24 Z Devo svolgere il calcolo in vari passaggi: mov AX,X ; metto X in AX add AX,Y ; aggiungo Y al contenuto di AX add AX,24 ; gli sommo 24 sub AX,Z ; gli sottraggo Z mov W,AX ; memorizzo in W il contenuto di AX … X DW 34 Y DW 16 Z DW 20 W DW ?
  26. 26. a.a. 2007/2008 Architettura dei calcolatori Esempio: Somma di valori a 32 bit • Voglio sommare i due valori a 32 bit 0123 BC62 e 0012 553A • Visto che nell’8086 i dati sono al massimo a 16 bit, posso svolgere il calcolo i d step successivi. N l secondo step posso usare l l in due t i i Nel dt direttamente l’istruzione ADC. mov ax,W10 ; si somma la word meno significativa add ax,W20 mov W30,ax mov ax,W11 ; si somma la word più significativa adc ax,W21 ; e si somma con carry mov W31,ax ; in W31 si mette il risultato ; dati W11 dw 0123h W10 dw bc62h W21 dw 0012h W20 dw 553ah W31 dw ? W30 dw ? ; non inizializzato
  27. 27. a.a. 2007/2008 Architettura dei calcolatori Esempio 1 • Vediamo il primo esempio completo di programma assembly: _TEXT segment assume cs:_TEXT, ds:_TEXT, ss:_TEXT org 100h Leggi: mov ah,07h ; Questa è la funzione di lettura int 21h ; di un carattere senza mostrarlo a video cmp al,1Bh ; Il codice ASCII è 1B (ESC)? je Fine ; Se sì, vai alla fine mov ah,02h ; Funzione di scrittura a video mov dl,al ; In DL ci va il carattere da visualizzare int 21h jmp Leggi ; Leggi un altro carattere Fine: ret _TEXT ends end Leggi
  28. 28. a.a. 2007/2008 Architettura dei calcolatori Esempio 1 • Tutto il programma è incluso in un unico segmento che abbiamo chiamato _TEXT (come fa il C, ma è solo un nome si poteva scegliere anche qualcos’altro). La direttiva per dichiarare segmenti è SEGMENT e viene chiusa da ENDS. • Alla fine del programma si deve sempre includere END, seguito dall’etichetta da cui deve cominciare il programma. • La seconda riga informa l’assemblatore che CS conterrà l indirizzo del segmento _TEXT, l assemblatore l’indirizzo TEXT come anche DS ed SS. • La terza riga contiene una direttiva per l’assemblatore che specifica che la prima istruzione sarà all’indirizzo 100h nel segmento. Questo è lo standard per i file .COM del vecchio MS- DOS ed è anche quello che utilizzeremo. Nei primi 100h byte c’erano dati del sistema operativo, come la linea di comando e le istruzioni per terminare il programma. • Dalla quarta riga vediamo una delle principali caratteristiche dell’assemblatore, cioè quella di consentire la dichiarazione di etichette per indicare la posizione di una istruzione senza conoscere l’indirizzo. • Che valore verrà sostituito all’etichetta Leggi?
  29. 29. a.a. 2007/2008 Architettura dei calcolatori Esempio 1 • L’etichetta Leggi indica l’indirizzo di una MOV che carica 07h nel registro AH. Poi viene chiamato l’INT 21h. Questa è l’interruzione che consente di accedere alle funzioni del DOS. La funzione richiesta viene passata in AH e la funzione 07h attende la pressione di un tasto. Il risultato (il codice ASCII del tasto premuto) viene ritornato in AL. • Il programma prosegue con una CMP, per verificare se l’utente ha premuto il carattere ESC. Come già spiegato, CMP esegue una sottrazione t AL e 1Bh e i ESC C ià i t tt i tra imposta il fl zero t flag (ZF). Possiamo allora verificare se sono uguali, con un JE. JE è infatti un sinonimo per JZ,che però mette in evidenza (solo a livello concettuale) che la differenza è stata eseguita con lo scopo di verificare una uguaglianza. Nel caso si sia premuto ESC, si salta all’etichetta Fine. • Il carattere letto viene poi visualizzato tramite la funzione 02h del DOS, che vuole il p , carattere da visualizzare in DL. Infine si salta nuovamente all’etichetta Leggi. • Nel caso si arrivi a Fine, viene eseguita una RET. Il DOS si è infatti preoccupato di fare una PUSH dell’indirizzo di ritorno, o meglio ha eseguito il nostro programma facendo una CALL all’Entry Point, ovvero l’etichetta che abbiamo messo a fianco della direttiva END.
  30. 30. a.a. 2007/2008 Architettura dei calcolatori Esempio 2 _TEXT segment assume cs: TEXT, ds: TEXT, ss: TEXT org 100h Leggi: mov ah,07h ; Questa è la funzione di lettura int 21h ; di un carattere senza mostrarlo a video cmp al,1Bh ; Il codice ASCII è 1B (ESC)? je Fine ; Se sì, vai alla fine mov Numero,al call ScriviNumero mov ah,02h ; Funzione di scrittura a video mov dl,' ' ; In DL ci va il carattere da visualizzare int 21h jmp Leggi ; Leggi un altro carattere Fine: ret
  31. 31. a.a. 2007/2008 Architettura dei calcolatori Esempio 2 (segue) In questo esempio vediamo come si ScriviNumero: mov ah,0 definiscono i dati tramite la direttiva mov al,Numero define byte ovvero DB. Dopo la mov bl,16 direttiva DB è possibile inserire uno o div bl mov ah,0 più valori numerici separati da virgole, mov si,ax stringhe tra apici (ogni carattere è un mov dl,CaratteriEsa[si] byte) oppure un ? che indica dati non mov ah,02h int 21h inizializzati (in realtà vale solo se posizionato alla fine di un segmento, mov ah,0 altrimenti è come scrivere 0). mov al,Numero mov bl,16 Inoltre è possibile notare come div bl xchg ah,al CaratteriEsa[si] sia un indirizzamento mov ah,0 indiretto tramite registro indice, mov si,ax equivalente al meno chiaro mov o d ,Ca atte dl,CaratteriEsa[si] sa[s ] mov ah,02h [CaratteriEsa+si]. int 21h ret CaratteriEsa db '0123456789ABCDEF' Numero db ? _TEXT ends end Leggi
  32. 32. a.a. 2007/2008 Architettura dei calcolatori Esempio 2 (segue) La seconda parte potrebbe essere proc ScriviNumero near mov ah,0 scritta anche così. Cioè invece che mov al,Numero dichiarare una etichetta “normale”, si mov bl,16 utilizza la direttiva PROC chiusa da div bl mov ah,0 ENDP. Non cambia nulla, a parte il mov si,ax fatto che si può esplicitare mov dl,CaratteriEsa[si] l’indicazione NEAR che indica una mov ah,02h int 21h funzione all’interno dello stesso segmento. mov ah,0 mov al,Numero mov bl,16 div bl xchg ah,al mov ah,0 mov si,ax mov o d ,Ca atte dl,CaratteriEsa[si] sa[s ] mov ah,02h int 21h ret CaratteriEsa db '0123456789ABCDEF' endp ; ScriviNumero Numero db ? TEXT ends end Leggi
  33. 33. a.a. 2007/2008 Architettura dei calcolatori Logica binaria • Fanno parte di questo gruppo: – AND dest,sorg AND bit a bit – NOT d t NOT bit a bit dest – OR dest,sorg OR bit a bit – TEST dest,sorg Test – XOR dest,sorg OR esclusivo bit a bit • AND, NOT, OR e XOR eseguono l’operazione logica indicata sui bit dei registri forniti come parametri. TEST è invece un AND che però non salva il risultato, un po’ come CMP, ma modifica i FLAG. Questa istruzione serve per verificare se un certo bit di un byte o word è a 1.
  34. 34. a.a. 2007/2008 Architettura dei calcolatori Shift e Rotate • Fanno parte di questo gruppo: – SHL dest,count Spostamento logico a sinistra – SHR d t Spostamento logico a destra S t tl i dt dest,countt – SAL dest,count Spostamento aritmetico a sinistra – SAR dest,count Spostamento aritmetico a destra – ROL dest,count Rotazione verso sinistra – ROR dest,count Rotazione verso destra – RCL dest,count Rotazione attraverso il carry verso sinistra – RCR dest,count Rotazione attraverso il carry verso destra • Gli shift logici spostano tutti i bit in una certa direzione, espellendo gli estremi nel carry e inserendo degli zeri come nuovi bit. • SAL è id ti a SHL mentre SAR i identico SHL, t inserisce bit uguali al bit di segno originale, preservando i li l ii l d quindi il segno del numero. • I rotate sono equivalenti agli shift, ma reinseriscono il bit “espulso” dalla parte opposta come nuovo bit Le rotazioni attraverso il carry invece inseriscono il carry bit. carry.
  35. 35. a.a. 2007/2008 Architettura dei calcolatori Schemi operativi
  36. 36. a.a. 2007/2008 Architettura dei calcolatori Esempio 3 proc ScriviNumero near In questo esempio è stata riscritta la xor bh,bh procedura ScriviNumero, utilizzando anche le mov ah,02h istruzioni logiche e la rotate. mov ch,2 Nella prima riga, XOR viene utilizzato per mov dh,Numero Ripeti: azzerare BH. mov cl,4 Il parametro count per gli shift e i rotate può ror dh,cl essere soltanto 1 oppure CL. Att lt t CL Attenzione i mov bl,dh perché alcuni assemblatori consente anche and bl,0fh altri valori, ma questi funzionano soltanto dal mov dl,CaratteriEsa[bx] int 21h 80386 in avanti. dec ch Notare anche la mancanza di una CMP prima jnz Ripeti di JNZ. ret CaratteriEsa db '0123456789ABCDEF' endp ; ScriviNumero
  37. 37. a.a. 2007/2008 Architettura dei calcolatori Operazioni su stringhe di dati • Fanno parte di questo gruppo: – CMPS (CMPSB/CMPSW) Confronta stringhe di byte o word – MOVS (MOVSB/MOVSW) Copia t i h C i stringhe di b t o word byte d – LODS (LODSB/LODSW) Carica una stringa in AL o AX – STOS (STOSB/STOSW) Scrive AL o AX in una stringa – SCAS (SCASB/SCASW) Confronta AL o AX con una stringa • Prefissi relativi a questo gruppo – REP/REPE/REPZ Ripetono l’operazione se CX≠0 e se ZF=0, poi CX=CX-1 – REPNE/REPNZ Ripetono l’operazione se CX≠0 e se ZF=1, poi l operazione ZF 1, CX=CX-1 • Queste operazioni sono istruzioni complesse che consentono di lavorare con stringhe di dati in modo semplice. L’indirizzo della stringa sorgente è sempre DS:SI e quello L indirizzo destinazione è ES:DI. • Ognuna di queste operazioni ha una forma con operandi a dimensione variabile e due senza operandi (B per byte e W per word), ma in realtà la prima è solo un modo per consentire più chiarezza nel codice e coincide esattamente con le altre due.
  38. 38. a.a. 2007/2008 Architettura dei calcolatori Operazioni su stringhe di dati (2) • Tutte le istruzioni stringa incrementano di uno in caso di byte o di due in caso di word SI e DI. Se però il DF (flag direzione) è a 1 la direzione viene invertita e quindi SI e DI vengono decrementati. – MOVS(B/W) copia un dato da DS:SI a ES:DI – LODS(B/W) carica un dato da DS:SI in AL o AX – STOS(B/W) scrive il dato da AL o AX a ES:DI • Solitamente per MOVS e STOS si utilizza il prefisso REP che consente di ripetere la copia o la scrittura CX volte. LODS si può ripetere, ma è totalmente inutile, dato che AL/AX viene continuamente sovrascritto. – CMPS(B/W) confronta il dato in DS:SI con quello in ES:DI – SCAS(B/W) confronta il dato in DS:SI con AL o AX • CMPS e SCAS vengono tipicamente ripetuti con REPE/Z o REPNE/Z a seconda g p p che si voglia continuare fino a che il dato è uguale o diverso.
  39. 39. a.a. 2007/2008 Architettura dei calcolatori Istruzioni per il controllo dei flag • Fanno parte di questo gruppo: – CLC/STC Clear/Set Carry Flag (Pone CF a zero o a uno) – CLD/STD Clear/Set Direction Flag (Pone DF a zero o a uno) – CLI/STI Clear/Set Interrupt-Enable Flag (Pone IF a zero o a uno) – CMC Complement Carry Flag (Inverte lo stato di CF) – LAHF Copia FLAG in AH – SAHF Copia AH nei FLAG p – POPF Estrae i FLAG dallo stack – PUSHF Memorizza i FLAG sullo stack • Queste istruzioni ti i Q t i t i i tipicamente vengono usate CLD e STD prima d ll i t i i stringa, CLC t t i delle istruzioni t i CLC, STC e CMC prima di alcune operazioni aritmetiche su numeri grandi, CLI e STI prima e dopo l’esecuzione di sezioni che lavorano con l’hardware o con le tabelle degli interrupt. • Le altre servono tipicamente nelle routine di risposta agli interrupt interrupt.
  40. 40. a.a. 2007/2008 Architettura dei calcolatori Aritmetica decimale (Binary Coded Decimal) • Fanno parte di questo gruppo: – AAA ASCII Adjust after Addition – AAD ASCII Adj t b f Adjust before Di i i Division – AAM ASCII Adjust after Multiply – AAS ASCII Adjust after Subtraction – DAA Decimal Adjust after Addition – DAS Decimal Adjust after Subtraction • Non vedremo i dettagli di queste istruzioni, che servono per utilizzare il formato numerico Binary Coded Decimal (BCD). Questo formato prevede che i numeri compaiano in forma decimale, con una cifra per byte (formato unpacked-BCD) o due cifre per byte (formato packed-BCD).
  41. 41. a.a. 2007/2008 Architettura dei calcolatori Varie • Fanno parte di questo gruppo: – LEA dest,source Carica l’indirizzo di source in dest – LDS dest,source Carica il puntatore all’indirizzo source in DS:dest p , – LES dest,source Carica il puntatore all’indirizzo source in ES:dest – NOP Non fa niente (no operation) – XLAT Estrae un dato da una tabella in memoria • LEA carica l’indirizzo di variabili in memoria in un registro, risolvendo eventuali indici o scostamenti. • LDS e LES servono per caricare una variabile puntatore far con una sola istruzione. • XLAT è equivalente ad una MOV AL,[BX+AL] (istruzione sintatticamente errata). Se ad esempio abbiamo una serie di dati (byte) in memoria e vogliamo estrarre il 3°, possiamo caricare in BX l’indirizzo dei dati e 3 l indirizzo in AL 3. • Operatore OFFSET – Formato: OFFSET <variabile o label> – L’operatore OFFSET restituisce il valore dell’offset di una variabile o della label – P ò essere usato i alternativa all’istruzione LEA solo nei casi più semplici Può in l i ll’i i l i i iù li i – – Esempio: MOV AX, OFFSET VAR LEA AX, VAR , (se Var è una variabile => Sono equivalenti)
  42. 42. a.a. 2007/2008 Architettura dei calcolatori Esempio 4 Questa ennesima versione di proc ScriviNumero near ScriviNumero, mostra l’uso che si può mov dh,Numero mov cl,2 fare di XLAT. Ripeti: Notare che è stato invertito il verso Nt h tt i tit rol dh,1 della rotazione e che è stata usata rol dh,1 l’istruzione LOOP per la ripetizione. rol dh,1 rol dh,1 Il parametro della XLAT è sempre [BX] mov al,dh che va infatti caricato opportunamente. and al,0fh Anche se non viene indicato [BX], il mov bx,offset CaratteriEsa comportamento di XLAT non cambia. xlat Notare anche che se vogliamo mov ah,02h mov dl,al l’indirizzo di una variabile dobbiamo int 21h usare la direttiva offset. loop Ripeti ret CaratteriEsa db '0123456789ABCDEF' endp ; ScriviNumero
  43. 43. a.a. 2007/2008 Architettura dei calcolatori Esempio 5 – Le stringhe _TEXT segment ; Visualizzo Stringa2 assume cs:_TEXT, ds:_TEXT, ss:_TEXT mov cl,Stringa2 org 100h mov si,offset Stringa2 + 1 mov ah,02h Inizio: ; Copio Stringa2 in Stringa1 Stampa2: xor ch,ch lodsb mov cl,Stringa2 mov dl,al mov Stringa1,cl int 21h mov si,offset Stringa2 + 1 g loop p Stampa2 p mov di,offset Stringa1 + 1 rep movsb ; Termino il programma Fine: ret ; Visualizzo Stringa1 mov cl,Stringa1 cl Stringa1 ; Dati del programma mov si,offset Stringa1 + 1 Stringa1 db ? mov ah,02h db 255 dup (?) Stampa: lodsb Stringa2 db 16,'Prova di stringa' mov dl,al db 255-16 dup (?) int it 21h loop Stampa _TEXT ends ; Riempio Stringa2 di ‘*’ end Inizio mov al,'*' mov cl,100 mov Stringa2,cl mov di,offset Stringa2 + 1 rep stosb
  44. 44. a.a. 2007/2008 Architettura dei calcolatori Esempio 5 • In questo esempio vengono utilizzate le istruzioni per le stringhe. • Per comodità si sono definite le stringhe al modo del PASCAL, ovvero con un b t iniziale che contiene l l byte i i i l h ti la lunghezza d ll stringa e uno spazio h della t i i di 255 byte. Notare che è stata usata la direttiva dup per allocare lo spazio necessario. La sintassi è: [numero di ripetizioni] dup ( dato da ripetere ) • Quindi Stringa1 è l’indirizzo di una struttura di 256 byte, in cui il primo indica il numero di caratteri effettivamente presenti nel buffer di 255 caratteri successivo. • Stringa2 è analoga, ma viene inizializzata con un testo. • Il programma copia Stringa2 in Stringa1, ne visualizza il contenuto, riempie Stringa2 di asterischi e mostra il risultato. • Provate a modificare il programma in modo che la parte che esegue la visualizzazione sia una procedura da invocare con una CALL.
  45. 45. a.a. 2007/2008 Architettura dei calcolatori Esempio 6 – Uso di più segmenti _TEXT segment para public 'CODE' ; Visualizza stringa assume cs:_TEXT, ds:_DATA, ss:_STACK mov ah,09h mov dx,offset str_ACapo ; inizializiamo DS in modo che punti al int 21h ; segmento dati Inizio: mov ax,_DATA ; Chiamo la funzione DOS per terminare mov ds,ax ; i programmi ; Visualizza stringa mov ah,4ch mov ah,09h , mov al,00h , mov dx,offset str_Messaggio1 int 21h _TEXT ends int 21h ; Input di un carattere (viene ritornato _DATA segment para public 'DATA' ; in al) mov ah,01h ah 01h str Messaggio1 db 'Digita un carattere: Digita int 21h ','$' ; Memorizzo il carattere str_ACapo db 0dh,0ah,'$' mov Carattere,al str_Messaggio2 db 'Hai premuto il ; Visualizza stringhe carattere: ','$' mov ah,09h mov dx,offset str_ACapo Carattere db ? _DATA ends int 21h mov ah,09h _STACK segment para stack g p 'STACK' mov dx,offset str Messaggio2 gg int 21h ; Dimensione dello stack ; Output del carattere premuto dw 32 dup (?) _STACK ends mov ah,02h mov dl,Carattere end Inizio int 21h
  46. 46. a.a. 2007/2008 Architettura dei calcolatori Esempio 6 • In questo esempio vediamo un programma con più segmenti (che quindi diventerà un EXE e non un COM. • Non ’è ll N c’è nulla di particolarmente strano nel programma che si li it a ti l tt l h i limita visualizzare stringhe e caratteri con le funzioni del DOS. Attenzione che la funzione per stampare stringhe in DOS vuole un carattere ‘$’ alla fine della stringa. • Per dichiarare un segmento di stack è necessario riservare un po’ di spazio a differenza di prima e quindi si sono riservate 32 word.

×