Set di Istruzioni P 8086 In generale le istruzioni di qualsiasi P sono riconducibili ai seguenti gruppi fondamentali: 1. Istruzioni di trasferimento dati 2. Istruzioni aritmetiche e logiche 3. Istruzioni di shift e rotazione 4. Istruzioni per la manipolazione delle stringhe 5. Istruzioni di controllo della sequenza 6. Istruzioni di controllo del P Istruzioni Aritmetiche Logiche Istruzioni di Trasferimento dati Istruzioni per il Controllo della Sequenza SET ISTRUZIONI P 8086 Istruzioni per la Manipolazione di Stringhe Istruzioni di Shift e Rotazione Istruzioni per il Controllo del P 1 ISTRUZIONI DI TRASFERIMENTO DATI Queste istruzioni hanno come obiettivo lo spostamento di dati o per la memoria o per le periferiche di I/O, con uno dei registri interni della CPU. È ammesso anche lo spostamento tra registri, mentre raramente è consentito quello diretto tra memoria e memoria. ISTRUZIONI DI TRASFERIMENTO DATI Tra registri Registri - Disp. I/O Registri - Memoria 2 ISTRUZIONI LOGICHE / ARITMETICHE Queste istruzioni sono strettamente collegate con le funzioni implementate nell’ALU, che è il circuito combinatorio che le realizza. Sono previste operazioni con segno e senza segno, a dimensione variabile in funzione degli operandi ed in grado di aggiustare la codifica del risultato al fine di adeguarla alla rappresentazione decimale. Le operazioni di moltiplicazione e divisione non sono totalmente combinatorie, bensì sono realizzate tramite un algoritmo a passi successivi e quindi richiedono un notevole tempo di esecuzione. Le operazioni logiche implementate sono rappresentate dai principali operatori booleani. 3 ISTRUZIONI DI SHIFT E ROTAZIONE Queste istruzioni hanno l’obiettivo di “spostare” a destra o a sinistra il contenuto dell’ operando di un certo numero di posti. Le differenze tra le varie istruzioni riguardano come vengono trattati i bit che “escono” dall’ operando e viceversa quelli che sono immessi a causa della traslazione o rotazione. 4 ISTRUZIONI DI CONTROLLO DELLA SEQUENZA Questo tipo di istruzioni permettono di variare la struttura strettamente sequenziale di un programma imponendo al registro IP un nuovo valore di indirizzo. Le istruzioni di questo gruppo si possono ulteriormente suddividere in 4 categorie: 1. Salti incondizionati 2. Salti subordinati ad una condizione 3. Chiamata a subroutine e ritorno 4. Interrupt software Istruzioni di Controllo Sequenza Salti incondizionati Interrupt Software CALL subroutine Salti condizionati 5 ISTRUZIONI DI MANIPOLAZIONE DELLE STRINGHE Le stringhe, nel linguaggio dell’8086, sono sequenze di byte o di word. Il set di istruzioni di questo p comprende 5 istruzioni realizzate appositamente per la manipolazione delle stringhe. Caratteristica comune di queste istruzioni è di non avere un operando: infatti lavorano su stringhe indirizzate dai registri indice SI e DI, automaticamente aggiornati dopo l’operazione. L’aggiornamento può consistere in una operazione di incremento o di decremento dell’indice, in relazione allo stato della flag DF (direction flag). SI: Source Index DI: Destination Index 6 ISTRUZIONI DI TRASFERIMENTO DATI Questo gruppo di istruzioni è quello statisticamente più utilizzato. In esse spicca l’istruzione MOV, estremamente flessibile e molto potente, grazie ai numerosi modi di indirizzamento di cui dispone. MOV op _ dest. op_sorg Reg. / Mem . Reg./ Mem . Reg. / Mem . Reg. Immediato Reg. Segmento L’operando sorgente viene copiato nell’operando destinazione. Si noti che tale istruzione non è distruttiva per l’operando sorgente: sicuramente ciò che era presente nell’ operando destinazione verrà cancellato. 7 Vediamo ora quali sono le potenzialità di questa istruzione, raccogliendole in forma tabellare. MODI DI INDIRIZZAMENTO SUPPORTATI Registri Reg/Mem Reg Reg/Mem Immed. SI SI SI SI SI * NO Di uso generale AX, BX, CX, DX [AH, AL,…, DH, DL] Puntatori e indici SI, DI, SP, BP Di Segmento CS, DS, ES, SS * Solo uno dei due registri può essere di segmento. Esempi: a) b) c) d) e) MOV MOV MOV MOV MOV AL, 00 CX, 00FF [0204], AX BX, [0010] [BX], AL 8 PUSH / POP Queste istruzioni permettono di caricare (PUSH) o prelevare (POP) i dati posti nell’area di memoria Stack. PUSH op_sorg POP op_dest OP: REG / MEM; Reg = Registro a 16 bit escluso IP ed RF Il registro IP è escluso in quanto “salvato” automaticamente quando si realizza un salto. Il registro RF delle Flag è escluso in quanto esistono per esse apposite istruzioni di salvataggio. 9 PUSHF / POPF Queste istruzioni funzionano in modo analogo alle normali PUSH e POP però il loro operando è fisso. L’operando su cui esse operano è il registro delle flag. Si noti che queste istruzioni sono le uniche che permettono l’accesso alle flag nel senso di manipolazione. Si pensi alla flag di trappola “T” che permette l’esecuzione del programma in modo “passo passo”. Esempio: Inserimento del contenuto del registro delle flag, in cima allo stack, quindi spostamento di questo nel registro AX. Operazione inversa. a) PUSHF + POP AX FLAG H FLAG L b) PUSH AX + POPF FLAG H FLAG L In questo esempio si nota come dopo una PUSHF , che inserisce in cima allo stack il contenuto del registro delle flag, basta realizzare una normalissima istruzione di POP (nel nostro caso POP AX) per avere a disposizione il contenuto delle flag. Il tutto può essere ripristinato tramite una normale istruzione di POP. 10 LAHF / SAHF Queste sono istruzioni che agiscono sul registro delle flag, in particolare sulla parte bassa di questo, spostandolo nel registro AH, e viceversa: LAHF = L oad AH with flag SAHF = S tore AH into flag Esse permettono di leggere e di modificare il valore dei flag. Per queste in particolare si faccia riferimento alla tabella seguente: SF: Sign flag ZF: Zero flag AF: Aux flag PF: Parity flag CF: Carry flag CF: Può essere sia testato che modificato. (istruzioni di salto condizionato o da CF ) SF, ZF, PF: Possono essere solo testati. AF: Non può essere né letto né modificato. Tale flag viene utilizzato direttamente dalla ALU. 11 XCHG Questa istruzione è a due 2 operandi dei quali si scambia il contenuto: XCHG = eXCHanGe Sintassi: XCHG op_1, op_2 Modi di Indirizzamento: REG / MEM REG REG REG Registri di uso generale Registri indici, base NON tra registri di segmento REG MEM Sia in modo diretto che in modo indiretto Esempi: XCHG XCHG XCHG BX, SI AL, [xxxx] DI, [BX + SI + Spiazzamento 8/16 bit con segno] 12 XLAT XLAT = transLATe byte to AL Questa istruzione utilizza il modo di indirizzata implicito, ovvero non ha operandi ed utilizza registri fissi per puntare alla memoria. In particolare utilizza il registro BX; l’indirizzo di memoria a cui ci riferirà così realizzato: [DS:BX+AL] In pratica la memoria viene indirizzata dal registro BX con un offset positivo contenuto in AL, il tutto all’interno del segmento dei dato puntato da DS. “IL DATO CONTENUTO ALL’INDIRIZZO SPECIFICATO, VIENE TRASLATO NEL REGISTRO AL.” 13 LEA LEA = Load Effective Address to Register Sintassi: LEA Registro destinazione, ind. Memoria Il registro destinazione è un registro di uso generale a 16 bit, indice o base; in esso sarà caricato l’offset specificato dal secondo operando. L’indirizzo di memoria espresso dal secondo operando è in forma diretta o indiretta. Esempi: LEA SI, [BX + SI + 4] SI = BX + DI + 4 CON MODALITÁ INDIRETTA LEA SI, [1000] CON MODALITÁ DIRETTA 14 LDS /LES LDS = Load pointer to DS LES = Load pointer to ES Sintassi: LDS operando _ destinazione, operando _sorgente Op_dest : registro Op_sorg : riferimento diretto o indiretto alla memoria “Il contenuto della locazione di memoria indirizzata dall’ operando sorgente viene posto nel registro specificato dal primo operando, mentre il contenuto della locazione successiva viene posto nel registro DS (LDS) o ES (LES).” Esempio: LDS BX, [SI + 2] (LES BX, [SI + 2]) SI = 0200 Questo tipo di istruzioni sono utilizzate in programmi di una certa complessità, in cui sono presenti più segmenti dati. 15 ISTRUZIONI ARITMETICHE È facilmente intuibile come questo gruppo di istruzioni sia di fondamentale importanza per un µp. L’8086 oltre alle consuete operazioni di somma e sottrazione, consente istruzioni relative a operazioni di moltiplicazione e divisione, tra operandi a 8 bit o a 16 bit con o senza segno! Tali istruzioni non sono frutto di hardware bensì di firmware, ovvero tramite un microprogramma memorizzato nella CPU. In considerazione di ciò, tali istruzioni sono relativamente lente. Le istruzioni aritmetiche, insieme a quelle logiche e di manipolazione dei flag, sono le uniche, con qualche eccezione, che variano il contenuto del registro delle flag. 16 ADDIZIONE E DESTINAZIONE SOTTRAZIONE SORGENTE ALU CF Le istruzioni di addizione e sottrazione sono disponibili nel formato a 8 e 16 bit, con o senza eventuale riporto. Sintassi: ADD ADC SUB SBB dest, sorg; dest, sorg; dest, sorg; dest, sorg; dest = dest + sorg dest = dest + sorg + carry dest = dest – sorg dest = dest – sorg – carry 17 N.B.: Le istruzioni di somma e sottrazione alterano il contenuto di tutti i flag aritmetici: OF: posto a 1 in caso di overflow SF: copia del bit di segno ZF: posto a 1 se il risultato è 0 AF: posto a 1 se c’è riporto intermedio PF: posto ad 1 se il risultato è pari CF: posto ad 1 in caso di riporto sia per operazioni su byte che su word Modi di indirizzamento supportati: REG / MEM REGISTRO REG / MEM IMMEDIATO DESTINAZIONE Registro Memoria Registro Registro Memoria Accumulatore SORGENTE Immediato Immediato Registro Memoria Registro Immediato 18 ESEMPI ADD AX, 1 ADC [DI],0100 SUB AL, BL SBB DX, [1000] ADD [DI], AX SUB AL, 50 Esempio di Somma di 2 parole da 32 bit MOV ADD MOV MOV ADC MOV AX, WORD1_L AX, WORD2_L; WORD3_L, AX AX, WORD1_H AX, WORD2_H; WORD3_H, AX word1_L + word2_L = word3_L (mod. flag) word1_H + word2_H = word3_H (mod. flag) Word1_H Word1_L AX Carry Flag Word2_H ALU AX Carry Flag AX Word2_L ALU AX DAA / DAS Word3_H Word3_L 2a Addizione con riporto 1a Addizione senza riporto 19 DAA DAS (Decimal Adjust for Add) (Decimal Adjust for Subtract) “Le operazioni di somma e sottrazione avvengono su cifre binarie espresse in esadecimale, Al fine di implementare una aritmetica in codice BCD, occorre aggiustare i risultati. Si ricordi infatti che in codice BCD le combinazioni a 4 bit da 1010 a 1111 non esistono: tali combinazioni sono possibili però in operazioni HEX. Le istruzioni precedenti servono quindi ad eliminare le ambiguità in codice BCD.” Esempio: AH AL MOV AL, 47 00 47 ADD AL, 34 00 7B 00 81 DAA Come si nota dal risultato, in codice BCD il numero 7B non ha senso, non esistendo la combinazione ‘1011’ = ( B ) HEX , occorre quindi (come sicuramente si ricorderà !) sommare la quantità “ 6 ” per poter rientrare in codice. Tale operazione è realizzata dalla DAA . Tale istruzione non ha un operando, bensì opererà sul risultato dell’addizione: va quindi posta logicamente dopo di essa. “ operazione ad 8 bit “ . 20 Tutto quanto a proposito della DAA vale anche per la DAS, fermo restando che, trattandosi di una sottrazione, al simbolo ‘ E ’ = ‘ 1110 ’ che non è contemplato nel codice BCD andrà sottratta la quantità ‘6’ = ‘0110’. Esempio: MOV SUB DAS AL, 65 AL, 37 (65) Hex = (37) Hex = -----------(2E) Hex = (0110 0101) Bin (0011 0111) Bin = ---------------------(0010 1110) Bin - (06) Hex -----------(28)Hex (0000 0110) Bin --------------------(0010 1000) Bin = = = (28)Hex è il risultato corretto in BCD dopo la DAS 21 CMP Tale istruzione non ha un operando, bensì opererà sul risultato della sottrazione: va quindi posta logicamente dopo di essa. “operazione ad 8 bit”. Normalmente tale istruzione viene utilizzata insieme alle istruzioni di salto condizionato, al fine di implementare delle strutture condizionali. Sintassi: CMP op_1, op_2 In sostanza viene realizzata una operazione di sottrazione tra op_1 ed op_2, senza però modificare nessun operando, bensì modifica solo il valore delle flag. 22 MODI DI INDIRIZZAMENTO REG / MEM REG / MEM REG IMMEDIATO Esempi: CMP CMP CMP CMP CMP N.B. Modo di indirizzamento: Reg, Reg [xxxx], Reg [Reg], Reg [Reg], xx BY [Reg + Reg + offset], xx Reg - Reg Mem dir. - Reg Mem ind.- Reg Registro imm. Mem ind.imm. BY = Byte PTR = Byte puntato in memoria dall’indirizzo [Reg + Reg + offset] . 23 NEG Questa istruzione fornisce il complemento a 2 dell’ operando. Il risultato sarà memorizzato nell’ operando stesso. Sintassi : NEG op Esempio: MOV AL, 50 NEG AL ( B0 )Hex = (-50)Hex Modi di indirizzamento supportati: REG / MEM NEG AL NEG BY [bx + di] NEG WO [xxxx] N.B.: ; Reg ; memoria indiretto ; memoria diretto WO = WORD PTR = Word (2 byte) puntata in memoria dall’indirizzo [xxxx] 24 INC / DEC Queste istruzioni incrementano o decrementano il contenuto dell’operando. Non c’è influenza sulla flag di carry. Sintassi : INC op / DEC op Modi di indirizzamento supportati : REG / MEM Esempi: INC AX; DEC AL, [BX] ; DEC WO [xxxx] ; Registro Registro indiretto Memoria diretto 25 MUL / IMUL L’istruzione MUL effettua la moltiplicazione tra numeri a 8 o 16 bit senza segno, mentre l’istruzione IMUL agisce su numeri con segno. Le due istruzioni sono codificate con due codici diversi in quanto le operazioni su numeri con segno abbisognano di intervernti correttivi prima e dopo l’operazione stessa. L’OPERAZIONE VIENE EFFETTUATA TRAMITE UN ALGORITMO IN FIRMWARE. Sintassi: MUL IMUL OP OP ; (unsigned MUL tiply) ; (Integer MUL tiply) L’operando può essere un Registro oppure la memoria. REG / MEM L’altro operando è implicitamente l’accumulatore. AL = operazione a 8 bit AX = operazione a 16 bit I flag modificati sono essenzialmente OF e CF ovvero la flag di Overflow e quella di Carry. 26 SCHEMATIZZAZIONE DELLA “ MUL” E DELLA “IMUL” AD 8 E 16 BIT Moltiplicando (8bit) (16bit) AL (AX) Moltiplicatore (8 bit) (16 bit) OPERANDO 8 bit (16 bit) MUL/IMUL Prodotto (16 bit) Prodotto (16 bit bassi ) Prodotto (16bit alti ) (DX) AX (AX) 27 DIV / IDIV Sintassi: DIV IDIV op op ; (Unsigned DIV ision) ; (Integer DIV ision) MODI DI INDIRIZZAMENTO REG - MEM OPERANDO DIV IDIV REG 8 BIT DIV CL IDIV CL REG 16 BIT DIV CX IDIV CX MEM 8 BIT DIV [1000] IDIV [1000] MEM 16 BIT DIV TABLE [SI] IDIV TABLE [SI] In particolare la DIV esegue la divisione senza segno tra il contenuto dell’accumulatore (nel caso di 1 byte) o dell’accumulatore e della sua estensione, ovvero DX (nel caso di divisione a parola), per l’operando sorgente. Il quoziente viene depositato in AL o in AX, a seconda che la divisione sia ad 8 o a 16 bit. Il resto invece viene depositato in AH (8 bit) o in DX (16bit). Se il quoziente va oltre la capacità del Registro destinazione o se si usa uno zero come divisore, il componente genera automaticamente una interruzione. Nel caso della IDIV il tutto è analogo al precedente, ma gli operandi vengono trattati con segno. Le operazioni di correzione del risultato sono identiche a quelle viste per la IMUL. 28 SCHEMATIZZAZIONE DELLA “ DIV” E DELLA “IDIV” AD 8 Bit . DIVISORE ( 8 bit) DIVIDENDO ( 8 bit) OPERANDO AX DIV / IDIV RESTO ( 8 bit) QUOZIENTE ( 8 bit) AH AL 29 SCHEMATIZZAZIONE DELLA “ DIV” E DELLA “ IDIV ” AD 16 Bit . DIVISORE ( 16 bit) DIVIDENDO ( 16 bit) DX AX OPERANDO DIV / IDIV RESTO ( 8 bit) QUOZIENTE ( 8 bit) AH AL 30 ISTRUZIONI LOGICHE La caratteristica di questo gruppo di istruzioni, è che non considerano l’operando come un numero (binario, esadecimale o BCD) bensì come un insieme di bit. Queste istruzioni infatti, sono definite “logiche” in quanto effettuano una operazione Logica Boolena sui bit dell’ operando. Possiamo aggiungere ancora che questo gruppo di istruzioni può divedersi in due sottogruppi, a seconda del numero di operandi coinvolti nelle operazioni considerate, in particolare si avranno: a) SINGOLO OPERANDO (9 Istruzioni) b) DOPPIO OPERANDO (4 Istruzioni) SINGOLO OPERANDO DOPPIO OPERANDO NOT AND SHL TEST SHR OR SAL XOR SAR ROL ROR RCR RCL 31 Vediamo una per una tutte le istruzioni logiche appartenenti al 1° gruppo: NOT Questa istruzione esegue la negazione dell’operando: esegue il complemento a 1 agendo sul singolo bit del dato, sia esso byte o parola. SHL / SAL Questa istruzione esegue lo slittamento logico a sinistra del dato (byte o parola). Il numero di spostamenti che si realizzano è specificato in un apposito Registro contatore . SHIFT SAIFT CF LEFT ( Tralsazione Logica a sinistra ) LEFT ( Tralsazione Aritmetica a sinistra ) 7(15) 0 0 Byte o Word SINTASSI : SINTASSI : SHL op , Count SAL op , Count Gli SHIFT si differenziano in LOGICI e ARITMETICI in quanto una operazione di spostamento verso sinistra ha come effetto aritmetico quello di moltiplicare per 2 l’operando. 32 Esempio: MOV SHL BL, 07 BL, 1 ;BL = 07 ;BL = 0E L’istruzione SAL è del tutto equivalente alla SHL: ha infatti lo stesso codice operativo. Il DEBUG del DOS non riconosce questa istruzione. SHR Questa istruzione esegue lo slittamento a destra (logico o aritmetico) dell’operando. SAR Da notare come nell’istruzione SAR il bit più significatico si conserva. La ragione di ciò va ricercata nella possibilità di errore che si viene a creare nel caso SHR di operandi intesi come numeri relativi. Si noti infatti che, così come l’istruzione di SHL significava MOLTIPLICAZIONE per 2 ad ogni spostamento, anche l’istruzione di SHR rappresenta un’operazione aritmetica, ovvero la DIVISIONE per 2 ad ogni passaggio. Mentre però la SHL, intesa come moltiplicazione, non introduce errori nel caso di operandi negativi, ciò succede alla SHR, intesa come divisione, nel caso di numeri negativi. 7(15) 0 CF 0 Byte o Word SHIFT RIGHT ( Tralsazione Logica a destra ) 33 7(15) 0 CF Byte o Word SHIFT ARITMETIC RIGHT ( Tralsazione Aritmetica a destra ) Esempio: MOV SHR BL, FE BL, 1 ; BL = FE = (1111 1110)2 = (-2)10 ; BL = 7F = (0111 1111)2 = (127)10 Si intuisce allora l’utilità di una istruzione che conservi il bit di segno la SAR : MOV SAR BL, FE BL, 1 ;BL = FE = (1111 1110)2 = (-2)10 ;BL = FF = (1111 1111)2 = (-1)10 OK I flag vengono alterati, in particolare : CF : OF : OF : 0 1 Copia del bit che “fuoriesce” msb = [CF] per traslazioni verso sinistra msb [CF] 0 SAR SINGOLA per traslazioni verso destra MSB di op SHR N.B.: Se si utilizza come contatore di spostamenti, invece del valore 1, il Registro CL, è possibile ottenere la moltiplicazione dell ’ operando per un numero che sia potenza di 2. Combinando questa tecnica con la istruzione ADD è possibile eseguire delle operazioni di moltiplicazione per costanti, in modo molto più efficiente che la MUL. 34 Esempio: MOV MOV SAL CL, 04 AL, 08 AL, CL ; CL = 04 = (0000 0100)2 = (4) 10 ; AL = 08 = (0000 1000)2 = (8) 10 ; AL = 80 = (1000 0000)2 = (128) 10 Il risultato presente in AL è pari a 8 * 16. Pensiamo ora di scrivere in una locazione di memoria un DATO. Sarà possibile moltiplicare tale dato per un certo numero, attraverso l’implementazione algoritmica della seguente formula: DATO = (DATO * 2 i + DATO) * 2 j I = 0, 1, 2, … J = 0, 1, 2, … (2 i + j + 2 j ) Moltiplicatore di dato Esempio: Dato = 03 = (0000 0011) 2 = (3) 10 I = 2 ; J = 1 => (2 3 + 2 ) = 10 => DATO * 10 MOV MOV AX, DATO CL, 02 SAL ADD SAL AX, CL DATO, AX DATO, 1 ; AX = 03 = (0000 0011)2 = (3)10 ; Inizializzazione di CL per la moltiplicazione per 4 ; AX = 03 * 4 = (0000 0011)2 = (3)10 ; DATO = 03 + 0C = 0F = (0000 1111)2 ; DATO = 0F * 2 = 1E = (0001 1110)2 35 ROTATE LEFT ( Rotazione Logica a sinistra ) SINTASSI : CF ROL op , Count 7(15) 0 Byte o Word ROTATE RIGHT ( Rotazione Logica a destra ) SINTASSI : 7(15) ROR op , Count 0 CF Byte o Word L’istruzione ROL esegue la rotazione verso SINISTRA senza riporto. Il numero delle rotazioni è specificato in COUNT. Analoga è la funzione della ROR ma con rotazione verso DESTRA 36 ROTATE with CARRY LEFT ( Rotazione Logica a sinistra con Carry ) SINTASSI : CF RCL op , Count 7(15) 0 Byte o Word ROTATE with CARRY RIGHT ( Rotazione Logica a destra ) SINTASSI : 7(15) ROR op , Count 0 Byte o Word 37 CF L’istruzione RCL esegue la rotazione verso SINISTRA del dato coinvolgendo nell’ operazione il Carry. Tale bit, viene considerato come facente parte dell’ operando . Alla fine della rotazione il bit più pesante dell’ operando va ad occupare il posto del bit meno pesante dell’ operando. In modo analogo si comporta l’ istruzione RCR, con la variante di una rotazione verso destra. Chiaramente il numero di rotazioni è specificato in COUNT. Le istruzioni RCL e RCR sono delle rotazioni a 9 o 17 bit, in cui il 9° o il 17° bit è rappresentato dal carry. Il loro uso è specificatamente legato alle operazioni di SHIFT su dati le cui dimensioni superano i 16 bit. In sostanza si sfrutta il fatto che con queste istruzioni ( e solo con queste) è possibile immettere nell’ operando il contenuto del carry. Esempi potrebbero essere le operazioni di moltiplicazione o di divisione. Esempio : Moltiplicazione di una parola a 32 bit contenuta in DX:AX MOV MOV SAL 1 RCL AX , D21E ; Parte Bassa del Dato in AX DX , 095A ; Parte Alta del Dato in DX AX , 1 ; Prima AX = D21E dopo AX = A43C CF = DX , 1 ; Prima DX =095A dopo DX = 12B5 DX 0000 0101 1010 RCL CF 0 1001 AX 0000 0000 0000 0000 0 38 0000 0000 SAL CF 0000 0000 0000 0000 0000 0000 Per quanto riguarda le istruzioni a 2 operandi, esse condizionano le flags del registro di stato. In particolare i flag CF ed OF restano azzerati, mentre i restanti risentono del risultato dell’ operazione. Le istruzioni di questo sottogruppo sono: AND Sintassi : AND OP_DEST , OP_SORG TEST Sintassi : AND OP_DEST , OP_SORG OR Sintassi : AND OP_DEST , OP_SORG XOR Sintassi : AND OP_DEST , OP_SORG Modi di Indirizzamento : Registro / Memoria Registro Registro / Memoria Registro 39 Queste istruzioni hanno vai campi di impiego. In particolare le istruzioni di OR ed AND possono essere utilizzate per settare o resettare dei bit di una parola. MODIFICA DEI FLAGS 0 Risultato Positivo 1 Risultato Negativo 0 Risultato 0 1 Risultato = 0 SF (Sign Flag) ZF (Zero Flag) AF (Auxiliary Flag) Indeterminato 0 Risultato con numero dispari di “ 1 “ PF (Auxiliary Flag) 1 Risultato con numero pari di “ 1 “ CF (Sign Flag) OF (Overflow Flag) 0 0 Gli altri flag non vengono modificati . 40 ISTRUZIONI DI CONTROLLO DELLA SEQUENZA In questo blocco rientrano tutte quelle istruzioni che sono associate all’ interruzione della normale sequenza del programma di lavoro. Tali interruzioni possono configurarsi in modo diverso. Esse, infatti, possono essere dovute a salti di programma, condizionati o non, a chiamate o ritorni da subroutine ed infine ad interrupt software. Quindi le istruzioni di questo gruppo possono raggrupparsi in 4 categorie: 1) 2) 3) 4) Salti Incondizionati Salti Condizionati Chiamata o ritorno da Subroutine Interrupt Software SALTI INCONDIZIONATI : JMP OPERANDO INTRASEGMENTO FORMA DIRETTA INTERSEGMENTO OPERANDO : INDIRIZZO INTRASEGMENTO FORMA INDIRETTA INTERSEGMENTO 41 Questa istruzione esegue il salto non condizionato. Si trasferisce infatti, il controllo ad una certa locazione obiettivo, senza nulla verificare. l’indirizzo della locazione obiettivo, puo’ essere ottenuto in diversi modi, che comunque coinvolgono il Registro puntatore IP, in particolare l’indirizzo della locazione obiettivo e’ fornito dal contenuto di IP a cui viene sommato uno spostamento dotato di segno. A proposito di quanto appena detto, va aggiunto “ che ciò e’ vero, ossia e’ quello che il P si aspetta, solo quando si lavora con i codici esadecimali, perché sia il DEBUG del DOS che tutti gli assemblatori, utilizzano una diversa convenzione. L’uso degli assemblatori o del DEBUG del DOS, obbliga ad indicare “b” come operando, non lo spiazzamento bensì l’indirizzo dell’ offset all’interno del segmento, ovvero il valore che IP deve assumere. SALTO DIRETTO INTRASEGMENTO JMP JMP SPIAZZAMENTO A 8 BIT SPIAZZAMENTO A 16 BIT SALTO DIRETTO INTERSEGMENTO JMP SEGMENT : OFFSET In questo tipo di Istruzione di salto , si riferimento a valori di IP e di CS che sono contenuti nell’ istruzione stessa. ESEMPIO: JMP 19C0 : 0130 CS = 19C0 HEX , IP = 0130 HEX INDIRIZZO FISICO: 19D30HEX 42 SALTO INDIRETTO INTRASEGMENTO JMP REGISTRO/ MEMORIA Registro puo’ essere un qualsiasi Registro a 16 bit, con esclusione di quelli di segmento, mentre la memoria e’ un riferimento diretto o indiretto alla memoria: ESEMPI: A) JMP [1000] : B) JMP [BX] La word all’indirizzo di memoria puntato da BX, nel segmento dati, rappresenta l’offset , IP = [1000] : La word all’indirizzo di memoria nel segmento dati, rappresenta BX 0200 0200 03 0201 01 IP 0103 0203 0204 INSERIMENTO DATI 43 puntato da BX, l’offset, IP = [bx] SALTI CONDIZIONATI I salti condizionati sono utilizzati per generare delle diramazioni dei cicli in un programma. E’ altresi’ chiaro che essi vanno posti dopo quelle istruzioni che variano le flag. Queste istruzioni possono dividersi in 3 sezioni: 1) Condizioni per numeri assoluti 2) Condizioni per numeri relativi dopo una CMP OP1,OP2 3) Condizioni sui dopo un ‘ istruzione con effetto sui flag flag La sezione 1 e la 2, sono utilizzate dopo un’ istruzione di comparazione, mentre la 3 dopo una qualsiasi istruzione che modifica i flag. SINTASSI: J condizione , spiazzamento Spiazzamento: Condizione: Valore relativo ad 8 bit ( - 128 ; + 127 ). Tale valore sara’ sommato al contenuto attuale del IP che rappresenta l’ indirizzo dell’ istruzione di quella di salto. Vedi tabella 44 SALTO DI INTERSEGMENTO JMP FAR MEMORIA L’operando in questo caso e’ solo un riferimento diretto o indiretto alla memoria. non e’ possibile infatti, disporre di un Registro come riferimento, in quanto e’ necessario un indirizzo fisico, che non e’ possibile esprimere attraverso un unico Registro. l’operatore far e’ indispensabile e va anteposto a “memoria”, per poter distinguere questo tipo di salto da quello indiretto intrasegmento con riferimento alla memoria, diretto o indiretto. ESEMPIO JMP FAR [SI]: La parola posta all’indirizzo puntato da si, nel segmento dati, rappresenta l’indirizzo fisico di memoria da caricare in CS ed IP; IP =[SI] CS=[SI+2] JMP FAR [SI] CON SI=0200 SI 0200 PI 0200 3C 0201 01 0202 0203 0204 45 C0 013C CS 19 19C0 ISTRUZIONI LOOP JCXZ Del gruppo di istruzioni di salto , fanno parte anche: LOOP spiazzamento ( CX=CX – 1 , SALTA SE CX /= 0 ) JCXZ (SALTA SE CX = 0 ) spiazzamento N.B. Sia la sintassi che i modi di indirizzamento sono simili a quelli dei salti condizionati , ma in questo caso la condizione non e’ sulle flag , bensi’ sullo stato del Registro interno cx. nessun flag viene modificato da queste istruzioni. Tramite l’istruzione loop e’ possibile ideare facilmente un ciclo, esempio: RIPETI : MOV CALL LOOP CX, n° Cicli Routine la routine sara’ ripetuta n volte. Ripeti L ‘ istruzione loop presenta alcune varianti: LOOPE SPIAZZ. (CX = CX - 1 SALTA SE CX /=0 E ZF=1 ) LOOP EQUAL LOOPZ SPIAZZ. (CX = CX - 1 SALTA SE CX /=0 E ZF=1 ) LOOP ZERO LOOPNE SPIAZZ. (CX = CX -1 SALTA SE CX /=0 E ZF=1 ) LOOP NOT EQUAL LOOPNZ SPIAZZ. (CX = CX -1 SALTA SE CX /=0 E ZF=1) LOOP NOT ZERO 46 CALL RET Queste istruzioni costituiscono il mezzo attraverso il quale il P 8086 implementa i sottoprogrammi. SINTASSI: CALL OFFSET quando il P incontra una istruzione di CALL, per prima cosa decrementa il Registro SP, salva il Registro IP , quindi caricalo stesso IP con il valore fornito dall’operando. il segmento di stack e’ puntato dal Registro SS (stack segment), mentre l’offset all’interno del segmento e’ dato da SP (stack pointer). In base alla modalita’ di indirizzamento, si possono avere 4 diversi tipi di chiamata, in particolare : CHIAMATA DIRETTA INTRASEGMENTO CHIAMATA DIRETTA INTERSEGMENTO CHIAMATA INDIRETTA INTRASEGMENTO CHIAMATA INDIRETTA INTERSEGMENTO 47 1) Esempio di chiamata diretta intrasegmento PRIMA IP : 0207 CS : 0204 5 : CALL 0300 DOPO IP : 0300 CALL 00 MEMORIA BASSA 03 STACK 6 07 SS: SP-2 7 02 SS: SP-2 8 . . . STACK MEMORIA ALTA CS : 0300 Subroutine 48 2) Esempio di chiamata diretta intersegmento : CS 13D0 : 0204 CALL CALL 47B5 : 0300 IP STACK 47B5 : 0300 09 00 DOPO 02 03 D0 B5 13 47 CS IP 13D0 : 0209 STACK PRIMA 47B5 : 0300 Subroutine SINTASSI : CALL SEGMENT : OFFSET SP = SP – 2 , CS [SP] SP = SP – 2 , IP [SP] CS = SEGMENT , IP = OFFSET 49 3) CHIAMATA INDIRETTA INTERSEGMENTO SINTASSI: CALL FAR REG / MEMORIA ESEMPIO: CALL FAR [DI] SP = SP – 2 , CS SP = SP – 2 , IP CS = [DI +1] , IP = ; ; ; [SP] [SP] [DI] per quanto riguarda l’istruzione di RET, esistono due forme diverse di rientro, in particolare: 1) RITORNO INTRASEGMENTO R ET 2) RITORNO INTERSEGMENTO RETF RET ; [SP] IP , SP = SP + 2 RETF ; [SP] CS , SP = SP + 2 , 50 [SP] IP, SP =SP+2 INT n INTERRUPT SINTASSI : INT n SOFTWARE n numero assoluto ad 8 Bit Queste istruzioni sono impropriamente chiamate “interruzioni“, perché in realtà non lo sono. Una interruzione e’ infatti, qualcosa di asincrono al programma, che interrompe l’ attuale svolgimento delle operazioni, per eseguire una particolare procedura. tale compito e’ svolto dalle “interruzioni hardware“, da cui derivano, per meccanismo di funzionamento, le interruzioni software. Le interruzioni int sono normali istruzioni, poste all’ interno del programma in corso, quindi in tale accezione non possono essere considerate delle interruzioni vere e proprie. INT CALL Il meccanismo di funzionamento delle INT e’ basato su una tabella di 1024 byte locata all’ indirizzo 0000 : 0000 tale tabella contiene 256 vettori da 4 byte che rappresentano altrettanti indirizzi fisici a 32 bit SEG: OFFSET Quando si incontra una istruzione di INT, il processore esegue la routine posta all’indirizzo specificato nel vettore memorizzato nella locazione 4 * N in poi in sostanza si effettua un salto indiretto in effetti oltre al “salto” il processore effettua qualcosa di piu’, ovvero il salvataggio dello “stato macchina”. 51 Salvataggio stato macchina REGISTRO DELLE FLAG REGISTRO CS REGISTRO IP AZZERAMENTO FLAG IF AZZERAMENTO FLAG TF STACK CS IP IP CS FH TABELLA DEI PUNTATORI DELLE ROUTINE DI FL INT IP INT 00 0000:0000 INT 02 0000:0004 INT 03 0000:0008 INT 21 0000:0084 INT FF 0000:03FC IP IP STACK OFFSET L SP = SP - 2 ; F [ SP ] OFFSET H 0 TF ; 0 IF SEGMENT L SP = SP - 2 ; CS [ SP ] SEGMENT H SP = SP - 2 ; IP [ SP ] SP = SP - 2 ; F [ SP ] [ n * 4 ] IP ; [ ( n* 4 ) +2 ] CS 52 In definitiva si puo’ dire che questo tipo istruzione e’ simile ad una CALL o ad un salto indiretto che pero’ sfrutta il meccanismo degli interrupt di tipo hardware. La domanda che ora ci si può porre e’ la seguente: perché visualizzare le INT software quando potremmo utilizzare le CALL? la risposta e’ data dalla possibilità di trasportare il codice prodotto da una macchina all’altra. Si consideri infatti che anche piccole modifiche al sistema operativo o al BIOS, portano ad alterare molti degli indirizzi di memoria e quindi dover cambiare all’interno del sistema operativo stesso, molti degli operandi delle CALL di sistema. Tramite l ’ uso degli INT, basterà modificare i vettori posti all’interno della tabella delle interruzioni, lasciando inalterato il programma. Cosi’ come per le CALL, anche per le INT e’ previsto il rientro al programma principale: I RET ; [SP] IP; SP = SP+2 , [SP] FLAG_REG. [SP] CS , SP = SP+2 SP = SP+2 Come si puo’ notare, l’istruzione di RET, riporta il sistema nella condizione precedente all’istruzione di INT. INT O ( INTERRUPT ON OVERFLOW ) INT 4 OF = 1 INT3 INT n ( Normalmente utilizzata dai DEBUGGER ) n=3 Queste ultime due istruzioni sono codificate con un solo Byte 53 ISTRUZIONI DI CONTROLLO PROCESSORE Di questa categoria di istruzioni, alcune permettono di alterare il contenuto del Registro delle flag, altre sono normalmente utilizzate dai programmatori di sistema. ISTRUZIONI CHE AGISCONO SUL CARRY FLAG (CF). CLC ; CL EAR CARRY CMC ; COMPLEMENT CARRY STC ; S E T CARRY ISTRUZIONI CHE AGISCONO SULLA DIRECTION FLAG (DF). CLD ; CLEAR DIRECTION ISTRUZIONI CHE AGISCONO SUL FLAG INTERRUPT (IF). CLI STI ; ; CLEAR INTERRUPT ENABLE S E T INTERRUPT ENABLE N.B IF = 0 IF = 1 INTERRUZIONI INTERRUZIONI ESTERNE MASCHERABILI DISABILITATE ESTERNE MASCHERABILI ABILITATE. 54 ISTRUZIONI SPECIALI HLT ; HALT (FERMATA) Quando viene eseguita questa istruzione, il processore si porta in uno stato di inattività, dal quale non esce se non dopo una istruzione di RESET o di una richiesta di interruzione. wait ; (attesa) quando viene eseguita questa istruzione, il processore si porta in uno stato di attesa, dal quale uscirà’ solo dopo una richiesta di interruzione esterna o in seguito ad una istruzione di RESET o in base allo stato logico di un pin della CPU, ovvero il pin di test. Se tale pin e’ allo stato logico zero si procede nell ‘esecuzione del programma, altrimenti si resta in attesa che tale stato logico si realizzi. Tale istruzione e’ normalmente utilizzata con dispositivi esterni al fine di realizzare la sincronizzazione con la CPU, ad esempio, coprocessori matematici, memorie ……… . ESC ; ESCAPE TO EXTERNAL DEVICE SINTASSI : ESC OPERANDO Tale istruzione serve a generare istruzioni per il coprocessore matematico 8087. Durante un’istruzione successiva in memoria e risincronizza le operazioni tramite l’istruzione wait. LOCK ; BUS LOCK (BLOCCA) Tale istruzione e’ posta prima di un‘ istruzione che non deve assolutamente essere interrotta, ad esempio da una richiesta di rilascio del controllo dei BUS. 55 ISTRUZIONI DI I / O La gestione delle periferiche di I/O e’ realizzata normalmente tramite 2 istruzioni specifiche, ciò’ non toglie pero’ possibilità’ di utilizzare le istruzioni per l ’accesso dei dati in memoria (MOV). GESTIONE PERIFERICHE I/O I / O PORT MAPPED I / O MEMORY MAPPED Con questa modalità’ di gestione delle periferiche, una parte di indirizzi sono associati ad altrettante periferiche di i/o. Le istruzioni per l’indirizzamento sono pertanto quelle relative all’accesso dei dati in memoria. I / O MEMORY MAPPED : I / O PORT MAPPED : Questa modalità’ e’ quella normalmente utilizzata dall’8086 e fa uso di 2 specifiche istruzioni: IN ed OUT. IN : OUT SINTASSI : : IN ACCUMULATORE , PORTA SINTASSI : OUT PORTA , ACCUMULATARE 56 I dati che si potranno spostare sono di lunghezza pari ad 1 byte o ad 1 word. Nel caso di una in essi occuperanno al o AX rispettivamente, nel caso di una OUT il contenuto di al o AX rispettivamente e’ memorizzato nella porta specificata. la porta selezionata può essere nel range 0 65535. Due sono le diverse modalità’ di indirizzamento. A) DIRETTO , PER PORTE TRA 0 ED FF B) INDIRETTO , TRAMITE REGISTRO DX PER QUALSIASI INDIRIZZO. ESEMPI : IN AL , 60 ; PORT [60] OUT 43 , AL ; AL IN AL , DX ; PORT [DX] OUT DX , AL ; AL AL INDIRIZZAMENTO DIRETTO PORT [43] AL INDIRIZZAMENTO INDIRETTO PORT [DX] N.B Lo spazio di indirizzamento realmente utilizzato nei PC non e’ di 64 K byte (0 / FFFF )Hex bensì da ( 0 / 3FF ) Hex . 57 IL LINGUAGGIO ASSEMBLY Il linguaggio assembly e’ un linguaggio di basso livello mediante il quale e’ possibile gestire in forma diretta tutte le risorse del P. Si noti che la maggior parte delle istruzioni in linguaggio assembly coincidono con le istruzioni mnemoniche del set di istruzioni del P. La differenza, tra un programma scritto in linguaggio mnemonico ed uno scritto in linguaggio assembly , sta nella “gestione della memoria”, nei “riferimenti dei salti” e nell’ “interfaccia con il sistema operativo”. Infatti mentre in un programma scritto esclusivamente in linguaggio mnemonico, tutto ciò’ che riguarda: salti, locazioni di memoria, etc. viene espresso in forma numerica, in linguaggio assembly si fa uso delle cosiddette “label” o “etichette”. La procedura con la quale si realizza un programma scritto in assembly e’ abbastanza simile a quella usata per i linguaggi ad alto livello. I programmi utilizzati allo scopo sono detti “assemblatori”: MASM ; TASM Le varie fasi che porteranno alla realizzazione del programma, fanno uso di altrettanti programmi ovvero : EDITOR ASSEMBLER LINKER DEBUGGER 58 vediamoli singolarmente : EDITOR L’editor e’ il programma che ci permette di scrivere il cosiddetto “programma software”, ad esso sarà associato un file con estensione .asm, ovvero assembly. ASSEMBLER Tramite l’assemblatore, si realizza la fase appena successiva a quella di editor. Fornendo al programma il file con estensione .asm, l’assemblatore produrra’ un “file oggetto” con estensione .obj. Il file oggetto conterrà’ la traduzione di tutte le estensioni in linguaggio macchina, ma che e’ ancora incompleto riguardo l’interfaccia con il s.o. tale fase in genere produce alcuni altri file utili per la documentazione ed il DEBUG. Un file di tale genere e’ quello con estensione .lst (listing) . LINKER Il programma che permette di convertire il file oggetto in file eseguibile dal dos e’ il linker. Il file che esso produrrà’ sara’ ad estensione .exe. Tale file conterra’ tutte le istruzioni in linguaggio macchina ed in piu’ una testata di 512 byte detta header utilizzata dal S.O. per caricare il file in memoria. DEBUGGER Il debugger e’ un programma che permette l’individuazione degli eventuali errori presenti nel programma stesso. Lettereralmente significa spulciare ovvero togliere elementi fastidiosi. Un programma di tal genere permette di eseguire una serie di operazioni, quali: 1) OPERAZIONE DI DUMP Tramite questa operazione il codice oggetto assemblato viene caricato in memoria e visualizzato in tutte le forme possibili decimale, hex, ascii. 2) OPERAZIONE DI DISASSEMBLAGGIO Tramite tale operazione e’ possibile avere in lista un codice mnemonico dei comandi presenti in una versione del programma. 59 3) OPERAZIONE EDIT Tramite tale operazione e’ possibile aggiungere o modificare codici macchina nella prima versione del programma. 4) REGISTER DUMP E STACK DUMP Con questa operazione e’ possibile visualizzare e modificare i contenuti di tutti i Registri interni della cpu e in conteporanea una piccola porzione di memoria attorno al valore puntato dallo stack pointer. 5) OPERAZIONE TRACE (SINGLE STEP) Con tale operazione sara’ possibile eseguire un’ istruzione alla volta, visualizzando i cambiamenti apportati ai Registri interni della CPU e l’istruzione stessa. 6) BREAKPOINT Tale operazione ci permette di aggiungere dei punti di blocco forzato nell’esecuzione del programma, al fine di verificare lo stato della CPU in particolari punti del programma. Questi blocchi si chiamano breakpoint. 60 SEQUENZA DELLE OPERAZIONI NECESSARIE PER LO SVILUPPO DI UN PROGRAMMA ASSEMBLY SVILUPPO DI UN PROGRAMMA IN ASSEMBLY EDIT ASM CORREZIONE DEGLI ERRORI TRAMITE LE INFORMAZIONI DI TASM ( o MASM ) … LST ASSEMBLER … OBJ SI ERRORI ? NO CORREZIONE DEGLI ERRORI TRAMITE LE INFORMAZIONI DI DEBUG LINKER … EXE ESECUZIONE OK ? NO CAUSA INDIVIDUATA ? SI SI NO FINE DEBUG 61 LA STRUTTURA DI UN PROGRAMMA ASSEMBLY I programmi scritti in linguaggio assembly essenzialmente dai seguenti segmenti: 8086 sono costituiti 1) SEGMENTO DI CODICE 2) SEGMENTO DI DATI 3) SEGMENTO DI STACK si noti che un segmento di programma, e’ un insieme di istruzioni e/o dati, i cui indirizzi sono tutti relativi allo stesso Registro di segmento. DIRETTIVE ASSEMBLY Le direttive assembly sono delle parole chiave mediante le quali l’assemblatore svolge particolari compiti. Si ricorda infatti che una notevole caratteristica dei programmi scritti in assembly, che non e’ disponibile in assembler (scrittura in linguaggio mnemonico), e’ l’utilizzo delle label allora sarà necessario specificare all’assemblatore che cosa fare quando si incontrano questo tipo di comandi. Cioè l’assemblatore dovrà poter interpretare non solo i formati mnemonici delle istruzioni tipiche della CPU, ma anche dei comandi aggiuntivi che hanno lo scopo di informarlo su come deve comportarsi ed interpretare le altre istruzioni e che non devono generare codice macchina. Tali comandi, come già’ detto prendono il nome di pseudo istruzioni o direttive e vanno inserite nel campo del codice operativo, così come ogni istruzione. DIRETTIVA SEGMENT DIRETTIVA ASSUME DIRETTIVA END LA DICHIARAZIONE DELLE ETICHETTE (LABEL) Una label e’ un nome che rappresenta l’ indirizzo di un’istruzione e può essere utilizzata in un salto, una chiamata a sottoprogramma (CALL), oppure in una istruzione di LOOP. DIRETTIVA LABEL 62 LA DICHIARAZIONE DEI DATI DIRETTIVA DB ( DEFINE BYTE ) DIRETTIVA DW (DEFINE WORLD) DIRETTIVA DD ( DEFINE DOUBLE-WORLD ) DICHIARAZIONE DEI SIMBOLI I simboli dei nomi descrittivi, che rappresentano un numero, un testo, un’istruzione o un indirizzo. I simboli permettono di rendere più’ leggibile un programma ed e’ pertanto opportuno utilizzarli il più frequentemente possibile. DIRETTIVA = ( SEGNO DI UGUAGLIANZA ) DIRETTIVA EQU (EQUATE ) LE BASI DEI NUMERI I numeri interi possono essere espressi sia in forma decimale che esadecimale, binaria ed ottale. Il numero deve essere seguito dalla lettera che identifica la base: B Q D H o O BINARIO OTTALE DECIMALE ESADECIMALE Normalmente i numeri sono espressi in forma decimale a meno diversa indicazione, a tal scopo si usa una particolare direttiva. di DIRETTIVA RADIX I COMMENTI Come e’ noto ciò che nel file sorgente e’ scritto tra “ “, e’ considerato come commento, quindi ignorato dall’ assemblatore. E’ possibile un’alternativa a ciò, quando il commento lo si vuole su più’ linee: DIRETTIVA COMMENT 63 SCRIVERE UN PROGRAMMA IN ASSEMBLER 8086 Per poter realizzare un programma in assembler 8086 e' necessario scrivere un file con estensione *.asm con le caratteristiche minime specificate nei listati che seguono: programma 1 ; Programma per lo scambio di due valori a 16 bit Dati SEGMENT ; definizione dati usati nel programma Primo DW 0102h; Secondo DW 0304h; Dati ENDS Sistema SEGMENT STACK DW 100 DUP (?) Top LABEL WORD Sistema ENDS ; definiamo uno stack di 100 bytes Codice SEGMENT ; Definizione dei segmenti ; ASSUME serve a definire a quale puntatore potrà essere assegnato la struttura ASSUME CS: Codice, SS:Sistema, DS:Dati, ES:Dati Inizio: ;Inizializzazione dei registri di segmento MOV AX,sistema MOV SS,AX LEA AX,Top MOV SP,AX MOV AX,Dati MOV DS,AX MOV ES,AX ; calcolo del prodotto della parte bassa degli operandi MOV AX,WORD PTR Primo MOV BX,WORD PTR Secondo MOV WORD PTR Primo,BX MOV WORD PTR Secondo,AX ; ritorno al sistema operativo MOV AL,00H MOV AH,4CH INT 21H Codice ENDS END ; ENDS fine segmento inizio ; fine programma con definizione inizio, in IP verra' caricato l' indirizzo ; corrispondente a inizio 64 programma 2 ; ; programma che stampa su video una stringa con int 21h ; stack segment para stack 'stack' ; definiamo uno stack di 48 bytes che il sistema db 48 dup ('stack') ; posizionerà dove meglio crede stack ends ; dati segment para 'dati' ; definizione di una stringa di caratteri ashii con il '$' msg db ' si fa presto a dire ….','$' dati ends ; codice segment para 'codice' assume ds:dati ; ASSUME serve a definire a quale puntatore assume ss:stack ; potrà essere assegnato la struttura dati assume cs:codice ; org 0100h ; definiamo l' indirizzo d' inizio della procedura che segue ; main proc near ; definiamo il tipo di procedura ( near-far ) ; push ds ; salviamo il puntatore alla zona dati ; mov ax,dati ; posizioniamo il puntatore alla zona dati in cor rispondenza mov ds,ax ; della struttura dati 'dati' ; mov es,ax ; operazione inutile per il programma attuale ; lea dx,msg ; assegno a dx l' indirizzo della stringa ; mov ax,0900h ; definisco parametri in ax per poter stampare la stringa con int 21 ah = 09 int 21h ; richiamo l' int 21 - stampo la stringa ; pop ds ; ripristino il puntatore alla zona dati iniziale ; mov ax,4c00h ; definisco parametri in ax per poter interrompere il programma e ridare il ; controllo al sistema con l' int 21 ah = 4c int 21h ; richiamo l' int 21 - fine programma ritorno al sistema operativo ; main endp ; ENDP fine procedura main ; codice ends ; ENDS fine segmento ; end main ; fine programma con definizione inizio, in IP verra' caricato l' indirizzo ; corrispondente al main 65 OSSERVAZIONI 1 - i commenti devono essere preceduti dal ; 2 - le strutture dati vengono definiti tra le direttive SEGMENT ed ENDS 3 - le procedure vengono definite tra le direttive PROC ed ENDP 4 - ASSUME definisce sostanzialmente il tipo di struttura ma non assegna nessun valore numerico ai puntatori di segmento 5 - ORG serve a definire gli indirizzi d' inizio di programma e subroutine 6 - PROC serve a definire le dimensioni dei programmi 7 - l' END finale fissa l’IP Per assemblare il programma il comando é TASM nome programma senza estensione. Se si vuole il listato il comando é tasm nome progr. /l. Viene creato un file *.OBJ che deve essere linkato con il comando TLINK nome programma senza estensione. Viene creato un file *.EXE che può essere direttamente eseguito oppure se ne può realizzare il debug in due maniere differenti: 1 - con il comando DEBUG *.EXE e si entra nel debug classico del PC 2 - con il comando TD *.EXE e si entra in ambiente TURBO DEBUGGER E’ preferibile l'ambiente TURBO DEBUGGER che é organizzato a finestre e permette di visualizzare contemporaneamente tutte le caratteristiche (programma, memoria, registri) ed evidenzia le modifiche attuate dal programma in esecuzione. Inoltre possiede un ottimo HELP . I comandi sono quelli standard del debug, ma esiste la possibilità (con l' uso del mouse) di una più facile selezione. 66 TURBO ASSEMBLER Version 2.01 Copyright (c) 1988, 1990 Borland International Sintassi: TASM [options] source [,object] [,listing] [,xref] /a,/s Alphabetic or Source-code segment ordering /c Generate cross-reference in listing /dSYM[=VAL] Define symbol SYM = 0, or = value VAL /e,/r Emulated or Real floating-point instructions /h,/? Display this help screen /iPATH Search PATH for include files /jCMD Jam in an assembler directive CMD (eg. /jIDEAL) /kh# Hash table capacity # symbols /l,/la Generate listing: l=normal listing, la=expanded listing /ml,/mx,/mu Case sensitivity on symbols: ml=all, mx=globals, mu=none /mv# Set maximum valid length for symbols /m# Allow # multiple passes to resolve forward references /n Suppress symbol tables in listing /o,/op Generate overlay object code, Phar Lap-style 32-bit fixups /p Check for code segment overrides in protected mode /q Suppress OBJ records not needed for linking /t Suppress messages if successful assembly /w0,/w1,/w2 Set warning level: w0=none, w1=w2=warnings on /w-xxx,/w+xxx Disable (-) or enable (+) warning xxx /x Include false conditionals in listing /z Display source line with error message /zi,/zd Debug info: zi=full, zd=line numbers only TURBO LINK Version 3.01 Copyright (c) 1987, 1990 Borland International Sintassi: TLINK objfiles, exefile, mapfile, libfiles /m map file with publics /x no map file at all /i initialize all segments /l include source line numbers /s detailed map of segments /n no default libraries /d warn if duplicate symbols in libraries /c lower case significant in symbols /3 enable 32-bit processing /v include full symbolic debug information /e ignore Extended Dictionary /t create COM file /o overlay switch /ye expanded memory swapping /yx extended memory swapping 67 TURBO DEBUGGER Version 2.01 Copyright (c) 1988, 1990 Borland International Sintassi: TD [options] [program [arguments]] -x- = turn option x off -c<file> -do,-dp,-ds -h,-? -i -k -l -m<#> -p -r -rp<#> -rs<#> -sc -sd<dir> -sm<#> -vg -vn -vp -y<#> -ye<#> Use configuration file <file> Screen updating: do=Other display, dp=Page flip, ds=Screen swap Display this help screen Allow process id switching Allow keystroke recording Assembler startup Set heap size to # kbytes Use mouse Use remote debugging Set COM # port for remote link Remote link speed: 1=slowest, 2=slow, 3=medium, 4=fast No case checking on symbols Source file directory <dir> Set spare symbol memory to # Kbytes (max 256Kb) Complete graphics screen save 43/50 line display not allowed Enable EGA/VGA palette save Set overlay area size in Kb Set EMS overlay area size to # 16Kb pages 68