Programmazione Assembly Note su Microsoft Assembler Giacomo Fiumara giacomo.fiumara@unime.it Anno Accademico 2012-2013 1 / 254
Microsoft Assembler Masm32.com installare configurare path perchè contenga la directory bin di Masm32 2 / 254
Microsoft Assembler Strumenti Editor di testo (anche Notepad) emulatore DOS Assemblatore (ml) Link a 16 bit (link16) 3 / 254
Microsoft Assembler Documentazione Documentazione Intel Debugger K. R. Irvine, Assembly language for Intel-based computers, 4th or 5th edition J. T. Streib, Guide to Assembly Language, Springer L. B. Das, The x86 Microprocessors, Pearson 4 / 254
Codice Assembly embedded in programmi C Uno degli elementi di maggiore difficoltà della programmazione Assembly è rappresentata dalla gestione dell I/O Per evitare queste difficoltà, nei primi tempi, è possibile effettuare l embedding di porzioni di codice Assembly in programmi C La compilazione deve essere effettuata tenendo conto della presenza di codice Assembly Per esempio, nel caso di un compilatore gcc (consigliato), il comando di compilazione è: gcc -fasm-blocks nome_programma.c -o nome_programma.x 5 / 254
Codice Assembly embedded in programmi C /2 Si consideri il seguente codice C: #include stdio.h int main() { int num1, num2; num1 = 5; num2 = num1; printf("%s%d\n", "Valore di num2: ", num2); return 0; } 6 / 254
Codice Assembly embedded in programmi C /3 Si modifica come segue: #include stdio.h int main() { int num1, num2; num1 = 5; asm{ mov eax, num1 mov num2, eax } printf("%s%d\n", "Valore di num2: ", num2); return 0; } 7 / 254
Registri Introduzione Una delle cose più importanti di un processore è l insieme dei registri Quelli accessibili al programmatore sono detti general purpose Nel caso delle architetture x86 sono presenti, per motivi di compatibilità, registri a 8, 16, 32 bit 8 / 254
Registri È la situazione dei registri eax, ebx, ecx, edx Ognuna della porzioni può essere considerata un registro vero e proprio Ognuna delle porzioni può essere utilizzata indipendentemente (e contemporaneamente) dalle altre 9 / 254
Registri Registri a 32 bit Nome 16/8 bit Descrizione eax Accumulator ax, ah, al Arithmetic and Logic ebx Base bx, bh, bl Arrays ecx Counter cx, ch, cl Loops edx Data dx, dh, dl Arithmetics esi Source Index si Strings and arrays edi Destination Index di Strings and arrays esp Stack Pointer sp Top of stack ebp Base Pointer bp Base of stack eip Instruction Pointer ip Points to next instruction eflags Flag flag Status and control flag 10 / 254
Registro eflags Si tratta di un registro particolare, nel senso che ogni singolo bit che lo compone può essere riferito indipendentemente dagli altri Ogni bit controlla un operazione della CPU o fornisce informazioni sul risultato dell operazione Si tratta comunque di un registro che può essere acceduto in lettura e scrittura: In lettura per verificare, come detto, il risultato di un operazione In scrittura per impostare lo stato di un flag del processore 11 / 254
Registro eflags /2 Il registro eflags è un registro a 16 bit 7 bit non sono utilizzati 6 flag condizionali (contengono informazioni sullo stato delle operazioni della CPU): Carry Flag (CF) Zero Flag (ZF) Parity Flag (PF) Sign Flag (SF) Auxiliary Carry Flag (AF) Overflow Flag (OF) 3 flag di controllo: Direction Flag (DF) Interrupt Flag (IF) Trap Flag (TF) 12 / 254
Registro eflags /3 Flag condizionali Carry Flag (CF) Viene settato se si verifica un riporto sul bit più significativo durante un calcolo. Il riporto può verificarsi sul bit 7 (operazioni a 8 bit) oppure sul bit 15 (operazioni a 16 bit) Zero Flag (ZF) Viene settato quando il risultato di un operazione logico-aritmetica è zero. Per esempio: quando si decrementa il contenuto di un registro (di solito il registro CX, che viene usato come contatore), il contenuto del registro sarà zero. In quel momento ZF viene settato. Un altro caso è rappresentato dal confronto tra due numeri. Parity Flag (PF) Quando questo flag viene settato, si ha un numero pari di bit nel byte meno significativo del registro destinazione. Non viene molto usato. 13 / 254
Registro eflags /4 Flag condizionali /2 Sign Flag (SF) Viene settato se il risultato di un operazione logico-aritmetica è negativo. Di fatto contiene il MSB (most significant bit) del risultato, ovvero il bit di segno nelle operazioni aritmetiche con segno. Auxiliary Carry Flag (AF) Identico a CF, salvo il fatto che viene settato quando si produce riporto sul bit 3, cioè quando si produce riporto sui 4 bit meno significativi. Overflow Flag (OF) Viene settato se: si produce overflow nel MSB con riporto si produce overflow senza riporto 14 / 254
Registro eflags /5 Flag di controllo Direction Flag (DF) Controlla la direzione (sx-dx o viceversa) nella manipolazione delle stringhe. Quando è settato, le operazioni che auto-incrementano i registri sorgente e destinazione (SI e DI) incrementano entrambi i registri e il flusso dei caratteri che compongono le stringhe avviene da sinistra verso destra. Quando è posto uguale a zero, il flusso avviene da destra verso sinistra. Interrupt Flag (IF) Quando viene settato da programmi con sufficienti privilegi, gli interrupt hardware mascherabili possono essere gestiti. Trap Flag (TF) Viene settato per scopi di debug: i programmi vengono eseguiti un istruzione per volta e si arrestano. Ovviamente, questo consente di esaminare lo stato dei registri. 15 / 254
Registri di segmento Architettura della memoria Il processore 8086 ha un bus degli indirizzi a 20 bit Questo significa che la memoria indirizzabile ammonta a 2 20 = 1.048.576 byte Cioè dall indirizzo 00000H all indirizzo fffffh La memoria è vista come suddivisa in quattro segmenti: Segmento dati Segmento codice Segmento stack Segmento extra 16 / 254
Registri di segmento /2 Ognuno dei segmenti è accessibile mediante l indirizzo contenuto nel corrispondente registro di segmento Ogni registro memorizza l indirizzo base (di partenza) del segmento corrispondente Considerata la differenza di dimensione (indirizzo a 20 bit, registro a 16), nei registri vengono memorizzati i 16 bit più significativi dell indirizzo L indirizzo fisico (a 20 bit) di un dato viene calcolato a partire dall indirizzo base (contenuto nel registro) Per esempio, l indirizzo logico 2222H : 0016H diventa 22220H + 0016H = 22236H Si noti che il registro DS (Data Segment) contiene il valore 2222H, e che la quantità 0016H viene detta scostamento (offset) 17 / 254
Registri di segmento /3 Segmento di Codice Il segmento di codice (Code Segment, CS) è l area di memoria che contiene soltanto il codice di un programma. L offset rispetto al segmento di codice è fornito dall Instruction Pointer (IP), che punta sempre all istruzione successiva. L indirizzo logico di una istruzione è pertanto CS:IP Segmento di Stack Il segmento di stack (Stack Segment, SS) è l area di memoria che contiene lo stack. È gestita seconda la logica last-in-first-out. Il registro Stack Pointer punta alla cima dello stack. Un indirizzo logico 4466H : 0122H significa che il registro SS contiene il valore 4466H e che il registro IP 0122H: l indirizzo fisico si ottiene come 44660H + 01220H = 44782H. 18 / 254
Registri di segmento /4 Segmento Dati e Segmento Extra Contengono entrambi dati, ma in alcuni casi particolari (quando si gestiscono stringhe) può essere necessario gestirli in segmenti separati. I registri corrispondenti sono DS (Data Segment) e ES (Extra Segment). 19 / 254
Struttura della memoria 20 / 254
Struttura della memoria /2 21 / 254
Mappa della memoria Disposizione del codice eseguibile e dei dati in memoria: Stack Dati non inizializzati Dati del programma Codice eseguibile Prefisso del segmento del programma (PSP, Program Segment Prefix 22 / 254
Modelli di memoria I programmi eseguibili presentano di norma segmenti separati per i dati, il codice, lo stack ogni segmento non può occupare più di 64kB di memoria il modello di memoria è il modo in cui un programma indirizza le differenti aree della mappa di memoria Modello Num. segmenti codice Num. segmenti dati small 1 1 compact 1 più di 1 medium più di 1 1 large più di 1 più di 1 23 / 254
Interrupt Introduzione Sono il mezzo con cui i circuiti esterni al microprocessore comunicano il verificarsi di un evento i microprocessori possono rispondere ad interrupt hardware e/o software un dispositivo hardware può produrre un segnale di interrupt che viene elaborato dal PIC (Programmable Interrupt Controller) e da questi trasmesso al processore gli interrupt software vengono generati mediante la funzione INT l effetto di un interrupt è che il processore arresta la sua normale attività ed esegue una routine residente in memoria (gestione di interrupt) al termine, il microprocessore riprende la sua attività dal punto in cui l interrupt l aveva fermato 24 / 254
Interrupt Gestione degli interrupt 8086 La famiglia di processori 80x86 gestisce fino a 256 interrupt differenti (da 00H fino a FFH), dove H sta per esadecimale ad ogni interrupt è associata una routine l indirizzo di ognuna delle 256 routine è memorizzato in una tabella, detta tabella dei vettori di interrupt ogni vettore di interrupt occupa 4 byte, quindi l indirizzo di ogni vettore di interrupt può essere ottenuto moltiplicando per 4 il numero dell interrupt 25 / 254
Interrupt Interrupt software Quando il processore esegue l istruzione: INT 12H vengono caricati sullo stack i contenuti correnti: del registro dei flag del registro del codice (CS) del registro IP (Instruction Pointer) il controllo viene trasferito alla routine di gestione dell interrupt, mediante l indirizzo 48H il processore esegue la routine di gestione dell interrupt la routine termina con l istruzione IRET, che scarica dallo stack i contenuti dei registri della routine interrotta il controllo viene restituito al programma interrotto 26 / 254
Interrupt Interrupt del DOS Interrupt 20H (32D) 21H (33D) 22H (34D) 23H (35D) 24H (36D) 25H (37D) 26H (38D) 27H (39D) 28H (20D) 2FH (47D) Descrizione Arresto del programma Servizi generali del DOS Indirizzo di terminazione Indirizzo del gestore del Ctrl-C Indirizzo gestore errori critici Lettura disco assoluta Scrittura disco assoluta TSR (Terminate and Stay Resident) Interrupt stato d attesa DOS Interrupt Multiplex 27 / 254
Interrupt L interrupt int21h Uno degli interrupt più utilizzati è INT 21H Nell elenco alcune funzioni: Funzione 00H (00D) 01H (01D) 02H (02D) 05H (05D) 08H (08D) 09H (09D) 0FH (15D) 10H (16D) Descrizione Termina Input di un carattere con eco Output di un carattere Output della stampante Input dalla console senza eco Output di una stringa Apertura file Chiusura file 28 / 254
Interrupt L interrupt int21h Esempio di utilizzo di una delle funzioni dell interrupt int 21h: mov ah, 1h int 21h Nell esempio: il valore 1h viene caricato nel registro ah (viene selezionata la funzione di input carattere con eco) viene invocato l interrupt il carattere digitato da tastiera viene memorizzato nel registro al 29 / 254
Struttura di un programma assembly.model small.stack 100h.data.code start:... mov ax, 4c00h int 21h end start 30 / 254
Esempi di programmazione assembly ; prog1.asm ; stampa il carattere a a schermo ;.model small.stack 100h.code start: mov dl, a mov ah, 2h int 21h mov ax, 4c00h int 21h end start 31 / 254
Esempi di programmazione assembly / 2 ; legge un carattere da tastiera e lo stampa a video.model small.stack 100h.code start: mov ah, 1h int 21h mov dl, al mov ah, 2h int 21h mov ax, 4c00h int 21h end start 32 / 254
Esempi di programmazione assembly / 3 ; legge un carattere da tastiera ; lo stampa a video ; viene visualizzato un prompt.model small.stack 100h.code start: mov dl, > mov ah, 2h int 21h mov ah, 1h int 21h mov bl, al mov dl, mov ah, 2h int 21h mov dl, bl mov ah, 2h int 21h mov ax, 4c00h int 21h end start 33 / 254
Esempi di programmazione assembly / 4 ; prog4.asm ; legge un carattere da tastiera ; mostra CR, LF e il carattere inserito ;.model small.stack 100h.code start: mov dl, > mov ah, 2h int 21h mov ah, 1h int 21h mov bl, al mov dl, 13d mov ah, 2h int 21h mov dl, 10d mov ah, 2h int 21h mov dl, bl mov ah, 2h int 21h mov ax, 4c00h int 21h end start 34 / 254
Esempi di programmazione assembly / 5 ; prog5.asm ; visualizza una stringa a video ;.model small.stack 100h.data stringa db Ciao a tutti, 13, 10, \$ mov dx, offset stringa mov ah, 9h int 21h mov ax, 4c00h int 21h end start.code start: mov ax, @data mov ds, ax 35 / 254
Operazioni e Metodi di Indirizzamento L architettura 8086 richiede l esistenza di uno o due operandi Per esempio uno shift richiede un operando, un addizione due Come esempio si consideri l istruzione mov destination, source Gli operandi (destination e source) possono essere specificati nei seguenti modi: Indirizzamento mediante registri Indirizzamento immediato Indirizzamento diretto Indirizzamento indiretto mediante registri Indirizzamento relativo mediante registri Indirizzamento indicizzato Indirizzamento indicizzato relativo 36 / 254
Operazioni e Metodi di Indirizzamento Indirizzamento mediante registri In questo caso, destination e source sono entrambi registri Per esempio: mov al, ah mov si, ax mov ax, bl ; errore (un dato a 8 bit viene copiato in un registro a 16 bit) mov bl, ax ; errore (un dato a 16 bit viene copiato in un registro a 8 bit) 37 / 254
Operazioni e Metodi di Indirizzamento Indirizzamento immediato In questo caso, source è un dato costante Per esempio: mov al, 33h mov cx, 1234h mov al, c mov var1, 44 38 / 254
Operazioni e Metodi di Indirizzamento Indirizzamento diretto In questo caso, destination o source sono indirizzi (offset rispetto al valore di DS) di memoria Per esempio: mov ax, [1234h] mov [5678h], al mov var1, al mov bx, var2 39 / 254
Operazioni e Metodi di Indirizzamento Indirizzamento indiretto mediante registri In questa modalità di indirizzamento, l indirizzo di un dato è memorizzato in un registro, che si comporta come se fosse un puntatore al dato. I registri permessi in questa modalità sono BX, SI, DI mov al, [bx] ; il contenuto della locazione il cui indirizzo è puntato da bx viene copiato in al mov [si], cl ; il contenuto di cl viene copiato nella locazione il cui indirizzo è puntato da si 40 / 254
Operazioni e Metodi di Indirizzamento Indirizzamento relativo mediante registri In questa modalità il registro (quelli permessi sono BX, SI, DI, BP) contiene l indirizzo di un dato; a questo viene aggiunto uno scostamento mov cl, 10[bx] mov cl, [bx+10] mov cl, [bx]10 41 / 254
Operazioni e Metodi di Indirizzamento Indirizzamento indicizzato In questa modalità l indirizzo del dato viene ottenuto sommando il contenuto di due registri: un registro base e un registro indice mov al, [bx][si] mov [bx][di], cx 42 / 254
Operazioni e Metodi di Indirizzamento Indirizzamento indicizzato relativo In questa modalità l indirizzo del dato viene ottenuto sommando il contenuto di due registri ed uno scostamento mov dl, 5[bx][di] mov 5[bp][si], ax 43 / 254
Operazioni e Metodi di Indirizzamento Esempio - Indirizzamento relativo mediante registri.model small.data array db 10h, 20h, 30h, 40h, 50h.code start: mov di, 0 mov al, array[di] add al, 07h add di, 05h mov array[di], al mov ax, 4c00h int 21h end start 44 / 254
Operazioni e Metodi di Indirizzamento Esempio - Indirizzamento indicizzato.model small.data array db 34h, 87h, 56h, 05h, 07h.code start: mov bx, offset array mov di, 0 mov al, [bx + di] add al, 35h mov di, 05 mov [bx + di], al mov ax, 4c00h int 21h end start 45 / 254
Tipi di dati Gli operandi numerici possono essere espressi in notazione decimale, binaria, esadecimale e ottale la convenzione utilizzata dall assemblatore è che un operando viene espresso in base 10 a meno che non sia presente un suffisso che indichi il contrario i suffissi utilizzabili sono: H (hexadecimal) D (decimal) B (binary) O o Q (octal) nessuno (decimale) 46 / 254
Tipi di dati /2 Tipo BYTE SBYTE WORD SWORD DWORD SDWORD FWORD QWORD TBYTE REAL4 REAL8 REAL10 Descrizione Intero senza segno a 8 bit Intero con segno a 8 bit Intero senza segno a 16 bit Intero con segno a 16 bit Intero senza segno a 32 bit Intero con segno a 32 bit Intero a 48 bit Intero a 64 bit Intero a 80 bit Reale a 32 bit Reale a 64 bit (long) Reale a 80 bit (extended) 47 / 254
Tipi di dati /3 La direttiva BYTE riserva uno o più byte per la memorizzazione di dati. La direttiva: numero BYTE 01100101b riserva un byte di memoria e lo inizializza al valore 65H a tutti gli effetti pratici, sono assolutamente equivalenti le seguenti direttive: numero BYTE 01100101b numero BYTE 65h numero BYTE 101 numero BYTE 145q 48 / 254
Tipi di dati /4 Analogamente, le direttive WORD e DWORD permettono di riservare una o due parole di memoria tenendo conto del segno del numero che si vuole memorizzare; si può avere: WORD da -32.768 a 32.767 oppure WORD da 0 a 65.535 DWORD da -2.147.483.648 a 2.147.483.647 oppure DWORD da 0 a 4.294.967.295 49 / 254
Tipi di dati /5 Esempio Ad esempio: var1 WORD -1 var2 WORD 0 var3 WORD 32767 var4 WORD 65535 var5 WORD -32768 dvar1 DWORD 0 dvar2 DWORD -1 dvar3 DWORD 4294967295 dvar4 DWORD -2147483648 dvar3 DWORD 4294967266 50 / 254
Tipi di dati /6 BYTE La direttiva BYTE permette di definire operandi sotto forma di caratteri o di stringhe di caratteri caratteri e stringhe devono essere racchiusi tra apici (semplici o doppi) char1 BYTE g char2 BYTE "g" str1 BYTE ciccio str2 BYTE "ciccio s" 51 / 254
Tipi di dati /7 Assegnazioni multiple Le costanti permettono le assegnazioni multiple L etichetta si riferisce soltanto all offset del primo byte Per esempio: lista BYTE 10, 20, 30, 40 Offset 0000 10 0001 20 0002 30 0003 40 Valore 52 / 254
Tipi di dati /8 Operatore DUP L operatore DUP produce un allocazione ripetuta, mediante l utilizzo di un espressione costante come contatore È particolarmente utile quando si alloca spazio per array o stringhe, e può essere impiegato per la definizione di dati inizializzati o meno Per esempio: BYTE 20 DUP(0) ; 20 byte, tutti inizializzati a zero BYTE 20 DUP(?) ; 20 byte, non inizializzati mioarray DWORD 100 DUP(101) ; 100 elementi DWORD, inizializzati a 101 53 / 254
Tipi di dati /9 Esempio di utilizzo di DUP ; prog9.asm ; utilizzo di DUP.model small.stack 100h.data ostr db 50 dup( * ).code start: mov ax, @data mov ds, ax mov dx, offset ostr call puts mov ax, 4c00h int 21h ;;;;;;;;;;;;;;;;;; ; subroutine puts puts: mov ah, 9h int 21h ret end start 54 / 254
Istruzione mov Copia dati da un operando sorgente ad un operando destinazione bisogna rispettare le seguenti regole: gli operandi devono avere la stessa dimensione gli operandi non possono essere entrambi locazioni di memoria i registri CS, EIP e IP non possono essere operandi destinazione un valore immediato non può essere spostato in un registro di segmento Le possibilità sono: MOV reg, reg MOV mem, reg MOV reg, mem MOV mem, imm MOV reg, imm 55 / 254
Istruzione xchg Scambia il contenuto di due operandi Le possibilità sono: xchg reg, reg xchg reg, mem xchg mem, reg Per esempio: xchg ax, bx xchg ah, al xchg var1, bx 56 / 254
Operandi con offset diretto E possibile aggiungere un offset ad una variabile questo permette di raggiungere locazioni di memoria prive di etichette esplicite Per esempio: vettore byte 10h, 20h, 30h, 40h, 50h... mov al, vettore ; al = 10 mov al, [vettore+1] ; al = 20 mov al, [vettore+2] ; al = 30 57 / 254
Operandi con offset diretto /2 Lo scostamento dipende dalla dimensione della locazione di memoria Per esempio:.data vettore word 100h, 200h, 300h.code mov ax, vettore ; ax = 100 mov ax, [vettore+2] ; ax = 200 ogni elemento dell array occupa 16 bit, e quindi l offset deve essere di 2 per raggiungere il secondo elemento dell array 58 / 254
Incremento e decremento Permettono (rispettivamente) di incrementare e decrementare di 1 un singolo operando La sintassi: inc reg/mem dec reg/mem Per esempio:.data var word 1000h.code inc var ; var = 1001h mov bx, var dec bx ; bx = 1000h 59 / 254
Addizione e sottrazione Permettono di addizionare (sottrarre) l operando sorgente all (dall )operando destinazione La sintassi: add dest/source sub dest/source Per esempio:.data var1 word 2000h var2 word 1000h.code mov ax, var1 add ax, var2... mov ax, var1 sub ax, var2 60 / 254
Istruzione NEG Inverte il segno di un numero mediante complemento a due Sono permessi gli operandi: NEG reg NEG mem 61 / 254
Implementazione di istruzioni matematiche Si supponga di dover implementare l espressione: Res = X + (Y Z) res sword? x sword 25 y sword 30 z sword 40 ; primo termine (-x) mov ax, x neg ax ; secondo termine (y - z) mov bx, y sub bx, z ; addizione e memorizzazione add ax, bx mov res, ax 62 / 254
Operatori MASM presenta una serie di operatori utili per descrivere e indirizzare variabili: offset, restituisce la distanza di una variabile dall inizio del segmento di appartenenza ptr, permette di modificare la dimensione di default di una variabile type, restituisce la dimensione in byte di ogni elemento di un array lengthof, restituisce il numero di elementi di un array sizeof, restituisce il numero di byte usati per inizializzare un array 63 / 254
Operatore offset L operatore offset restituisce l offset di una variabile, cioè la distanza in byte della variabile dall inizio del segmento dati in modalità protetta un offset è sempre di 32 bit in modalità reale un offset è sempre di 16 bit Per esempio:.data bvar byte? wvar word? dvar1 dword? dvar2 dword?.code mov si, offset bvar ; si = 4000 mov si, offset wvar ; si = 4001 mov si, offset dvar1 ; si = 4003 mov si, offset dvar2 ; si = 4007 64 / 254
Operatore ptr Permette di modificare la dimensione di default di un operando È necessario quando si tenta di accedere alla variabile utilizzando un attributo di dimensione differente da quello utilizzato per la dichiarazione della variabile esempio: spostare i 16 bit meno significativi di una variabile DWORD in un registro (a 16 bit) Per esempio:.data var dword 12345678h.code mov ax, var ; SBAGLIATO mov ax, word ptr var ; ax = 5678h mov ax, byte ptr var ; ax = 78h mov ax, word ptr [var + 2] ; ax = 1234h 65 / 254
Operatore type Restituisce la dimensione in byte di un singolo elemento di una variabile Per esempio:.data var1 byte? ; type = 1 var2 word? ; type = 2 var3 dword? ; type = 4 66 / 254
Operatore lengthof Conta il numero di elementi di un array definiti in base ai valori che appaiono nella linea della label Per esempio:.data byte1 byte 10, 20, 30 ; lengthof = 3 vec1 word 30 dup(?),0,0 ; lengthof = 32 vec2 word 5 dup(3 dup(?)) ; lengthof = 5*3 vec3 dword 1, 2, 3, 4 ; lengthof = 4 str1 byte "12345678", \$ ; lengthof = 9 67 / 254
Operatore sizeof Restituisce un valore uguale al prodotto di lengthof per type Per esempio: vec word 32 dup(0) ; sizeof = 64 68 / 254
Procedure ; prog7.asm ; conversione M/m.model small.stack 100h.data istr db Carattere M: $ ostr db Carattere m: $.code ; subroutine getc getc proc mov ah, 1h int 21h ret getc endp ; subroutint putc putc proc mov ah, 2h int 21h ret putc endp ; subroutine puts puts proc mov ah, 9h int 21h ret puts endp 69 / 254
Procedure /2 ; subroutine put1310 put1310 proc mov dl, 13d mov ah, 2h int 21h mov dl, 10d mov ah, 2h int 21h ret put1310 endp main proc mov ax, @data mov ds, ax mov dx, offset istr invoke puts call getc mov bl, al add bl, 32d call put1310 mov dx, offset ostr call puts mov dl, bl call putc mov ax, 4c00h int 21h main endp end main 70 / 254
Procedure /3 Programmazione modulare ; modules2.asm ; conversione M/m ; programmazione modulare, ; le procedure si trovano ; nel file procs.asm.model small.stack 100h.data istr db Carattere M: $ ostr db Carattere m: $.code getc proto putc proto puts proto put1310 proto main proc mov ax, @data mov ds, ax mov dx, offset istr invoke puts invoke getc mov bl, al add bl, 32d invoke put1310 mov dx, offset ostr invoke puts mov dl, bl invoke putc mov ax, 4c00h int 21h main endp end main 71 / 254
Procedure /4 Programmazione modulare - file procedure.model small.code ; subroutine getc getc proc mov ah, 1h int 21h ret getc endp ; subroutint putc putc proc mov ah, 2h int 21h ret putc endp ; subroutine puts puts proc mov ah, 9h int 21h ret puts endp ; subroutine put1310 put1310 proc mov dl, 13d mov ah, 2h int 21h mov dl, 10d mov ah, 2h int 21h ret put1310 endp end 72 / 254
Procedure /5 Programmazione modulare - compilazione C:\masm32\progs>ml /c modules2.asm procs.asm C:\masm32\progs>link16 modules2.obj procsobj,,,,, C:\masm32\progs>modules2 Carattere M: F Carattere m: f 73 / 254
Debug debug.exe e un programma per il debug, la verifica e il test di programmi Sintassi: debug nome-programma.exe al prompt (-) digitare? per ottenere un elenco dei comandi disponibili 74 / 254
Debug /2 75 / 254
Debug /3 Comando g (go) digitando g viene effettuata l esecuzione del programma nell ambiente di debug 76 / 254
Debug /4 Comando r (registers) serve a visualizzare lo stato dei registri 77 / 254
Debug /5 Comando t (trace) permette di eseguire l istruzione corrente molto utile, perche mostra lo stato dei registri ad ogni istruzione 78 / 254
Debug /6 Comando u (unassemble) traduce in assembly i byte contenuti dopo la conclusione del codice sorgente, il comando u continua...... disassemblando tutto quello che incontra (quasi sempre senza senso) 79 / 254
Debug /7 Comando p (proceed) esegue una procedura (call o int) per intero senza entrare nei dettagli delle istruzioni della procedura si usa in alternanza al comando t 80 / 254
Debug /8 Comando d (dump) mostra il contenuto della memoria quando un eseguibile e caricato dal debug mostra la mappa di memoria 81 / 254
Debug /9 Esempio di utilizzo Visualizzare lo stato dei registri mediante il comando trace di debug.model small.stack 100h.data.code start: mov ax, 11h add ax, 22h sub ax, 30h mov ax, 4c00h int 21h end start 82 / 254
Indirizzamento indiretto L indirizzamento diretto non pratico per operazioni sugli array richiede infatti di fornire un nome (label) per ogni elemento dell array la soluzione consiste nell utilizzare un registro come puntatore e modificare il valore del registro questa tecnica si chiama indirizzamento indiretto il registro che memorizza un indirizzo viene detto operando indiretto 83 / 254
Operandi indiretti Un operando indiretto pu essere qualsiasi registro general-purpose (bx, si, di, bp) viene utilizzato racchiudendolo tra parentesi quadre (per esempio, [ax]).data var1 byte 10h.code start: mov si, offset var1 mov al, [si] end start 84 / 254
Operandi indiretti (modalit protetta, a 32 bit) In modalit protetta si possono utilizzare pcome operandi indiretti i registri a 32 bit: eax, ebx, ecx, edx, esi, edi, ebp, esp se l indirizzo punta ad un area esterna al segmento dati del programma si genera un general protection (GP) fault un GP fault si pu verificare anche senza che si intenda modificare la memoria indirizzata il modo migliore per evitare questo tipo di errori consiste nell inizializzare i registri da impiegare per l indirizzamento indiretto i GP fault non si verificano in modalit reale (16 bit) 85 / 254
Utilizzo di ptr con gli operandi indiretti La dimensione di un operando non sempre chiara dal contesto Per esempio: inc [si] ; errore: l operando deve essere dimensionato inc ptr byte [si] ; corretto: si chiarisce il puntamento ad un byte 86 / 254
Array Gli operandi indiretti sono particolarmente utili quando si gestiscono array, perch il valore di un operando indiretto pu essere modificato facilmente in modo analogo all indice di un array, un operando indiretto pu puntare ai diversi elementi di un array Per esempio:.data vettore byte 10h, 20h, 30h.code mov ax, @data mov ds, ax mov si, offset vettore mov al, [si] ; al = 10h inc si mov al, [si] ; al = 20h inc si mov al, [si] ; al = 30h 87 / 254
Array /2 Quando si gestisce un array di interi a 16 bit (word), bisogna incrementare il registro si di 2 per indirizzare i successivi elementi Per esempio:.data vettore word 1000h, 2000h, 3000h.code mov si, offset vettore mov ax, [si] ; ax = 1000h add si, 2 mov ax, [si] ; ax = 2000h add si, 2 mov ax, [si] ; ax = 3000h 88 / 254
Array /3 Quando si gestisce un array di interi a 32 bit (dword), bisogna incrementare il registro si di 4 Per esempio:.data vettore dword 10000h, 20000h, 30000h.code mov si, offset vettore mov ax, [si] ; ax = 10000h add si, 4 mov ax, [si] ; ax = 20000h add si, 4 add ax, [si] ; ax = 30000h 89 / 254
Operandi indicizzati Un operando indicizzato aggiunge una costante ad un registro per produrre un indirizzo in modalit protetta qualsiasi registro a 32 bit pu essere utilizzato come registro indice in modalit reale soltanto i registri si, di, bx o bp possono essere utilizzati come registri indice MASM permette due notazioni: cost[reg] [cost + reg] 90 / 254
Operandi indicizzati /2 E buona consuetudine inizializzare a zero il registro indice.data bvec byte 10h, 20h, 30h.code mov si, 0 mov al, [bvec + si] ; al = 10h 91 / 254
Operandi indicizzati /3.data wvec word 1000h, 2000h, 3000h.code mov si, offset wvec mov ax, [si] ; ax = 1000h mov ax, [si + 2] ; ax = 2000h mov ax, [si + 4] ; ax = 3000h 92 / 254
Puntatori Una variabile che contiene l indirizzo di un altra variabile detta variabile puntatore i puntatori sono essenziali quando si elaborano array e strutture dati MASM prevede l utilizzo di due tipi di puntatori near (16 bit in modalit reale, 32 bit in modalit protetta) far (32 bit in modalit reale, 48 bit in modalit protetta) 93 / 254
Puntatori /2 bvec byte 10h, 20h, 30h, 40h wvec word 1000h, 2000h, 3000h ptrb dword bvec ptrw dword wvec In alternativa: ptrb dword offset bvec ptrw dword offset wvec 94 / 254
Puntatori Definizione mediante typedef L operatore typedef permette di creare un tipo di variabile pu essere utilizzato per creare puntatori Per esempio: pbyte typedef ptr byte Per esempio: pbyte typedef ptr byte.data bvec byte 10h, 20h, 30h, 40h ptr1 pbyte? ; non inizializzato ptr2 pbyte bvec ; punta all array bvec 95 / 254
JMP e LOOP Un trasferimento di controllo, o branch un modo di alterare l ordine in cui le istruzioni vengono eseguite tutti i linguaggi di programmazione presentano istruzioni di branching possibile suddividere queste istruzioni in: trasferimenti incondizionati, per esempio mediante l istruzione JMP trasferimenti condizionati, in cui la ramificazione si verifica soltanto se una certa condizione vera. Per esempio, l istruzione LOOP 96 / 254
Istruzione jmp Provoca un trasferimento incondizionato ad una locazione interna al segmento di codice la locazione destinazione deve essere identificata mediante un etichetta la sintassi : jmp etichetta L istruzione jmp pu essere impiegata per realizzare un loop top:...... jmp top ; attenzione si genera un loop infinito 97 / 254
Istruzione loop Fornisce un modo semplice per ripetere l esecuzione di un blocco di istruzioni per un numero specificato di volte il registro cx viene automaticamente utilizzato come contatore e viene decrementato ogni volta che il ciclo si ripete la sintassi : loop destinazione Per esempio: L1: mov ax, 0 mov cx, 5 inc ax loop L1 98 / 254
Istruzione loop Avvertenze bisogna evitare di inizializzare il registro cx a zero prima di avviare il loop. Se questo avvenisse, l istruzione loop incrementerebbe cx a ffff e itererebbe 65536 volte la destinazione del ciclo deve trovarsi nell intervallo da -128 a +127 rispetto al contatore locale; le istruzioni macchina hanno una dimensione media di 3 byte, quindi un loop pu contenere circa 40 istruzioni una modifica del valore di cx all interno del loop può avere effetti indesiderati 99 / 254
.model small.stack 100h.data str1 byte "Stringa da copiare","0" str2 byte sizeof str1 dup(0).code start: mov si, 0 mov cx, sizeof str1 L1: mov al, str1[si] mov str2[si], al inc si loop L1 mov ax, 4c00h int 21h end start 100 / 254
Gestione della memoria Introduzione I processori IA-32 (Intel Architecture 32 bit, dal 386 in poi) presentano tre modalità fondamentali: protetta 8086 virtuale (un caso particolare di modalità protetta) real-address system management 101 / 254
Gestione della memoria /2 Modalità protetta Si tratta della modalità di esecuzione nativa del processore, nel quale tutte le istruzioni e le possibilità sono consentite Ai programmi vengono assegnate aree di memoria (segmenti) Il processore individua ogni tentativo di accedere ad aree di memoria esterne al segmento assegnato Il processore può accedere a 4 GB di memoria (i registri vengono considerati tutti a 32 bit) 102 / 254
Gestione della memoria /3 Modalità 8086 virtuale Si tratta di un caso particolare della modalità protetta Il processore si comporta come un 8086, ma in un ambiente multitasking Per esempio, un crash non influenza negativamente altri programmi e/o il sistema 103 / 254
Gestione della memoria /4 Modalità real-address Nota anche come modalità reale Questa modalità implementa l ambiente di programmazione del processore Intel 8086 con alcuni elementi ulteriori Tra questi la possibilità di commutare alle altre due modalità Questa modalità è stata introdotta in Windows 98 Si tratta della modalità di avvio di tutti i processori Intel In questa modalità soltanto 1 MB di memoria è accessibile ai programmi (20 bit, da 00000 a FFFFF) 104 / 254
Gestione della memoria /5 Modalità system management Fornisce al sistema operativo un meccanismo per implementare alcune funzionalità come il power management e la sicurezza di sistema 105 / 254
Operazioni sullo stack Introduzione Come si ricorderà, lo stack è una struttura LIFO (Last In First Out) cioè, l ultimo valore inserito è sempre il primo ad essere estratto il runtime stack è un array di memoria gestita direttamente dalla CPU mediante due registri: SS e SP il registro SS indica l indirizzo iniziale del segmento di memoria dedicato allo stack il registro SP contiene un offset a 16 bit relativo a qualche locazione dello stack il registro SP viene manipolato raramente, viene invece esplicitamente modificato da istruzioni come CALL, RET, PUSH e POP il registro StackPointer SP punta all ultimo intero inserito nello stack 106 / 254
Operazioni sullo stack Push Un operazione di push decrementa lo stack pointer di 4 (2 in modalità reale) e copia un valore nella locazione dello stack puntata dallo stack pointer 107 / 254
Operazioni sullo stack Pop Un operazione di pop incrementa lo stack pointer di 4 (2 in modalità reale) e rimuove un valore nella locazione dello stack puntata dallo stack pointer 108 / 254
Operazioni sullo stack Utilità Lo stack viene utilizzato nei programmi per: creare un area temporanea per i registri quando questi vengono utilizzati per qualche scopo salvare l indirizzo di ritorno della procedura corrente al momento dell invocazione dell istruzione call contenere gli argomenti (eventualmente) passati come parametri ad una procedura al momento della sua esecuzione memorizzare le variabili locali di una procedura 109 / 254
Operazioni sullo stack Istruzione push L istruzione push decrementa SP e copia un operando sorgente da 16 o 32 bit nello stack un operando a 16 bit implica un decremento di SP di 2, un operando a 32 bit un decremento di 4 Attenzione: il push di un operando immediato è stato introdotto a partire dalle architetture 80286 push r/m16 push r/m32 push imm32 (imm16 in real mode) 110 / 254
Operazioni sullo stack Istruzione pop L istruzione pop prima copia il contenuto dell elemento dello stack puntato da SP in un operando destinazione a 32 o 16 bit e successivamente incrementa SP se l operando è a 16 bit, SP viene incrementato di 2, se l operando è a 32 bit l incremento di 4 pop r/m16 pop r/m32 111 / 254
Operazioni sullo stack Istruzioni pushfd e popfd (pushf e popf) L istruzione pushfd scrive il registro a 32 bit EFLAGS sullo stack popfd scrive su EFLAGS il contenuto prelevato dallo stack modalità reale: pushf per il push del registro (a 16 bit) FLAGS sullo stack modalità reale: popf per il pop nel registro (a 16 bit) FLAGS dallo stack pushf ; pushfd in modalit\ a protetta ; ; codice... ; popf ; popfd in modalit\ a protetta 112 / 254
Operazioni sullo stack Istruzioni pushad e popad (pusha e popa) L istruzione pushad effettua il push sullo stack di tutti i registri a 32 bit general-purpose l ordine nel quale viene effettuato: EAX, ECX, EDX, EBX, ESP, EBP, ESI e EDI Analogamente, l istruzione popad ripristina lo stato dei registri modalità reale: l istruzione pusha effettua il push di AX, CX, DX, BX, SP, BP, SI e DI modalità reale: l istruzione popa ripristina i predetti registri Attenzione: il push di un operando immediato è stato introdotto a partire dalle architetture 80286 113 / 254
Operazioni sullo stack Esempio: inversione di una stringa (stringa.asm).model small.stack 100h.data str1 byte "ciao","$" str2 byte sizeof str1 dup(0).code start: mov ax, @data mov ds, ax mov si, 0 mov cx, sizeof str1 dec cx L1: mov al, str1[si] push ax inc si loop L1 114 / 254
Operazioni sullo stack Esempio: inversione di una stringa (stringa.asm) / 2 mov cx, sizeof str1 dec cx mov si, 0 L2: pop ax mov str2[si], al inc si loop L2 mov al, "$" inc si mov str2[si], al mov dx, offset str2 mov ah, 9h int 21h mov ax, 4c00h int 21h end start 115 / 254
Elaborazione condizionata Introduzione Le condizioni che permettono di modificare il flusso delle istruzioni Assembly operano in base al valore di alcuni bit del registro FLAGS In particolare vengono settati i flag (bit): Zero: quando il risultato di un operazione è uguale a zero Carry: quando un istruzione genera un riporto Segno: copia del bit più significativo dell operando destinazione Overflow: quando un istruzione genera un risultato con overflow Parità: quando un istruzione produce un numero pari di bit 1 nel byte meno significativo dell operando destinazione 116 / 254
Elaborazione condizionata Istruzione AND Effettua un AND booleano (bitwise, bit a bit) tra i bit di uguale posto di due operandi il risultato viene memorizzato nell operando destinazione AND destinazione, sorgente Le combinazioni permesse di operandi sono: AND reg, reg AND reg, mem AND reg, imm AND mem, reg AND mem, imm 117 / 254
Elaborazione condizionata Istruzione AND / 2 I due operandi possono essere a 8, 16 o 32 bit, ma devono essere della stessa dimensione AND viene spesso utilizzato per eliminare determinati bit e salvarne altri Per esempio: 00111011 AND 00001111 ---------------- 00001011 mov al, 00111011b and al, 00001111b Flags: vengono resettati i bit di Overflow e Carry, modificati i bit di Segno, Zero e Parità 118 / 254
Elaborazione condizionata Istruzione AND / 3 Mediante l istruzione AND è possibile convertire facilmente una lettera minuscola in maiuscola si osservino i codici ASCII di A e a soltanto il bit 5 è differente: 0 1 1 0 0 0 0 1 = 61h ( a ) 0 1 0 0 0 0 0 1 = 41h ( A ) La regola vale per le altre lettere dell alfabeto ponendo in AND una lettera minuscola con 11011111, tutti i bit saranno preservati ad eccezione del bit 5 119 / 254
Elaborazione condizionata Istruzione AND - Esempio ; prog09.asm.model small.stack 100h.code start: mov al, 01100001b and al, 11011111b mov dl, al mov ah, 2h int 21h mov ax, 4c00h int 21h end start 120 / 254
Elaborazione condizionata Istruzione OR L istruzione OR effettua un OR booleano tra ogni coppia di bit (di posto uguale) di due operandi il risultato viene posto nell operando destinazione OR destinazione, sorgente L istruzione OR utilizza le stesse combinazioni di operandi dell AND: OR reg, reg OR reg, mem OR reg, imm OR mem, reg OR mem, imm 121 / 254
Elaborazione condizionata Istruzione OR / 2 I due operandi possono essere a 8, 16 o 32 bit, ma devono essere della stessa dimensione OR viene spesso utilizzato per settare alcuni bit e preservarne altri Per esempio: 00111011 OR 00001111 ------------- 00111111 Flags: vengono resettati i bit di Overflow e Carry, modificati i bit di Segno, Zero e Parità 122 / 254
Elaborazione condizionata Istruzione OR / 3 L istruzione OR viene utilizzata per convertire un byte contenente un intero compreso tra 0 e 9 nel carattere ASCII corrispondente a tale scopo necessario settare i bit 4 e 5 per esempio, 05h in OR con 30h diventa il carattere ASCII 35h 0 0 0 0 0 1 0 1 05h OR 0 0 1 1 0 0 0 0 30h -------------------- 0 0 1 1 0 1 0 1 35h mov dl, 5 or dl, 30h 123 / 254
Elaborazione condizionata Istruzione OR - Esempio ; prog10.asm.model small.stack 100h.code start: mov al, 00000101b or al, 00110000b mov dl, al mov ah, 2h int 21h mov ax, 4c00h int 21h end start 124 / 254
Elaborazione condizionata Istruzione XOR L istruzione XOR effettua un OR booleano esclusivo tra ogni coppia di bit (di posto uguale) di due operandi il risultato viene posto nell operando destinazione XOR destinazione, sorgente L istruzione XOR utilizza le stesse combinazioni di operandi dell AND: XOR reg, reg XOR reg, mem XOR reg, imm XOR mem, reg XOR mem, imm 125 / 254
Elaborazione condizionata Istruzione XOR / 2 Ricordando la tabella di verità di XOR si può vedere che qualsiasi bit in XOR con 0 mantiene il suo valore, mentre in XOR con 1 viene complementato Una caratteristica di XOR è che si annulla quando viene applicato due volte allo stesso operando Infatti x y (x XOR y) (x XOR y) XOR y 0 0 0 0 0 1 1 0 1 0 1 1 1 1 0 1 Questo lo rende uno strumento ideale per le operazioni di cifratura/decifratura di dati. 126 / 254
Elaborazione condizionata Istruzione XOR / 3 XOR viene utilizzato per controllare la parità (pari o dispari) di un numero Infatti: mov al, 10110101b xor al, 0 mov al, 11001100b xor al, 0 ; 5 bit = parita dispari ; flag di parita azzerato (PO) ; 4 bit = parita pari ; flag di parita settato (PE) Flags: l istruzione XOR resetta sempre i bit di Overflow e Carry. Modifica i bit di Segno, Zero e Parità in base al valore dell operando destinazione. 127 / 254
Elaborazione condizionata Istruzione XOR - Esempio ; prog11.asm.model small.stack 100h.code start: mov al, 10110101b xor al, 0 mov al, 11001100b xor al, 0 mov ax, 4c00h int 21h end start 128 / 254
Elaborazione condizionata Istruzione NOT L istruzione NOT complementa tutti i bit di un operando Il risultato è chiamato complemento a 1. Sono permessi i seguenti tipi di operandi: NOT reg NOT mem mov al, 11110000b not al ; al = 00001111b 129 / 254
Elaborazione condizionata Istruzione TEST L istruzione TEST effettua un AND implicito tra ogni coppia di bit (di uguale posto) di due operandi e setta i flag di conseguenza A differenza di AND, l operando destinazione non viene modificato Le combinazioni permesse sono uguali a quelle di AND TEST è utile quando si vuole verificare se determinati bit sono settati. test al, 00001001b ; test dello stato dei bit 0 e 3 di AL 130 / 254
Elaborazione condizionata Istruzione TEST / 2 Per comprendere il comportamento del flag Zero si consideri il seguente esempio: 0 0 1 0 0 1 0 1 valore da verificare 0 0 0 0 1 0 0 1 valore di test 0 0 0 0 0 0 0 1 ZF = 0 0 0 1 0 0 1 0 0 valore da verificare 0 0 0 0 1 0 0 1 valore di test 0 0 0 0 0 0 0 0 ZF = 1 131 / 254
Elaborazione condizionata Istruzione cmp L istruzione cmp (compare) effettua una sottrazione implicita di un operando sorgente da un operando destinazione Nessuno dei due operandi viene modificato. L istruzione cmp è fondamentale perchè fornisce le basi per la maggior parte delle strutture logiche. L istruzione cmp seguita da un istruzione di salto condizionato è equivalente ad un IF. La sintassi è: cmp destinazione, sorgente 132 / 254
Elaborazione condizionata Istruzione cmp / 2 L istruzione cmp modifica i flag di Overflow, Segno, Zero, Carry, Auxiliary Carry e Parità in base al valore che l operando destinazione avrebbe se venisse utilizzata l istruzione sub: Risultato di cmp ZF CF dest < sorgente 0 1 dest > sorgente 0 0 dest = sorgente 1 0 Se i due operandi sono considerati con segno, i flag Segno, Zero e Overflow indicano le seguenti relazioni tra gli operandi: Risultato di cmp Flag dest < sorgente SF!= OF dest > sorgente SF = OF dest = sorgente ZF = 1 133 / 254
Elaborazione condizionata Istruzione cmp / 3 mov ax, 5 cmp ax, 10 ; CF = 1 (10-5 richiede il "prestito") mov ax, 1000 mov cx, 1000 cmp ax, cx ; ZF = 1 mov si, 105 cmp si, 0 ; ZF = 0 e CF = 0 134 / 254
Elaborazione condizionata Istruzione cmp - Esempio ; prog12.asm.model small.stack 100h.code start: mov ax, 5 cmp ax, 10 mov ax, 1000 mov cx, 1000 cmp ax, cx mov si, 105 cmp si, 0 mov ax, 4c00h int 21h end start 135 / 254
Elaborazione condizionata Operazioni sui singoli flag Le operazioni sui singoli flag sono di set e reset. Per esempio: and al, 0 ; ZF = 1 or al, 1 ; ZF = 0 or al, 80h ; SF = 1 and al, 7fh ; SF = 0 stc clc ; set carry flag ; clear carry flag mov al, 7fh ; al = +127 inc al ; al = -128 OF = 1 or ax, 0 ; OF = 0 136 / 254
Elaborazione condizionata Operazioni sui singoli flag - Tabella di debug Set Descrizione Clear Descrizione OV Overflow NV No Overflow DN Direction Down UP Direction Up EI Interrupts Enabled DI Interrupts Disabled NG Sign Flag Negative PL Sign Flag Positive ZR Zero NZ Not Zero AC Auxiliary Carry NA Not Auxiliary Carry PO Odd Parity PE Even Parity CY Carry NC No Carry 137 / 254
Elaborazione condizionata Operazioni sui singoli flag - Esempio ; prog13.asm.model small.stack 100h.code start: and al, 0 or al, 1 or al, 80h and al, 7fh stc clc mov al, 7fh inc al or ax, 0 mov ax, 4c00h int 21h end start 138 / 254
Elaborazione condizionata Istruzione jcond Un istruzione di salto condizionato effettua una ramificazione verso un etichetta destinazione quando la condizione di un flag vera se la condizione sul flag falsa, viene eseguita l istruzione immediatamente successiva La sintassi : Jcond destinazione cond si riferisce alla condizione di un flag. Si pu avere per esempio: jc (jump if carry) jnc (jump if not carry) jz (jump if zero) jnz (jump if not zero) 139 / 254
Elaborazione condizionata Istruzione jcond / 2 MASM richiede che la destinazione del salto sia una label all interno della procedura corrente Ad ogni modo, questa limitazione viene superata utilizzando una label globale indicata dal simbolo :: Per esempio: Jc L1... L1:: In modalità reale, i salti possono avvenire entro un offset di 1 byte (positivo o negativo) in modalità protetta, questa limitazione stata rimossa 140 / 254
Elaborazione condizionata Istruzione jcond / 3 mov ax, 5 cmp ax, 5 je L1 mov ax, 5 cmp ax, 6 jl L1 mov ax, 5 cmp ax, 4 jg L1 ; jump if equal ; jump if less ; jump if greater 141 / 254
Elaborazione condizionata Istruzione jcond / 4 I salti condizionati possono essere raggruppati come segue: in base a specifici valori dei flag in base all uguaglianza tra operandi, oppure al valore del registro cx in base al confronto tra operandi senza segno in base al confronto tra operandi con segno 142 / 254
Elaborazione condizionata Istruzione jcond / 5 Salti condizionati dipendenti dai valori dei flag Simbolo jz jnz jc jnc jo jno js jns jp jnp Descrizione jump if zero jump if not zero jump if carry jump if not carry jump if overflow jump if not overflow jump if sign jump if not sign jump if parity jump if not parity Flags ZF = 1 ZF = 0 CF = 1 CF = 0 OF = 1 OF = 0 SF = 1 SF = 0 PF = 1 PF = 0 143 / 254
Elaborazione condizionata Istruzione jcond / 6 Salti condizionati dipendenti da uguaglianze Simbolo je jne jcxz jecxz Descrizione jump if equal jump if not equal jump if cx = 0 jump if ecx = 0 144 / 254
Elaborazione condizionata Istruzione jcond / 7 Salti condizionati da confronti senza segno Simbolo ja jnbe jae jnb jb jnae jbe jna Descrizione jump if above jump if not below or equal (uguale a ja) jump if above or equal jump if not below (uguale a jae) jump if below jump if not above or equal (uguale a jb) jump if below or equal jump if not above (uguale a jbe) 145 / 254
Elaborazione condizionata Istruzione jcond / 8 Salti condizionati da confronti con segno jg jump if greater jnle jump if not less or equal (uguale a jg) jge jump if greater or equal jnl jump if not less (uguale a jge) jl jump if less jnge jump if not greater or equal (uguale a jl) jle jump if less or equal jng jump if not greater (uguale a jle) 146 / 254
Elaborazione condizionata Istruzione jcond / 9 I salti basati sui confronti con segno vengono utilizzati quando i numeri che si confrontano possono essere interpretati come valori con segno Per esempio, quando si confronta 80h con 7Fh, l interpretazione è differente se si utilizza ja o jg mov al, 7Fh ; 7Fh = +127 cmp al, 80h ; 80h = -128 ja Lab ; non funziona jg Lgr ; funziona 147 / 254
Elaborazione condizionata Istruzione jcond / 10 Istruzioni come AND, OR, NOT, CMP e TEST sono utili quando seguite da istruzioni di salti condizionati che utilizzano i valori del flag di stato per modificare il flusso del programma Per esempio: mov al, status test al, 00100000b ; verifica del bit 5 jnz Label Si supponga di voler verificare lo stato dei bit 0, 1 o 4: mov al, status test al, 00010011b ; verifica dei bit 0, 1, 4 jnz Label 148 / 254
Elaborazione condizionata Istruzione jcond / 11 Si supponga di voler effettuare un salto se i bit 2, 3 e 7 sono tutti contemporaneamente settati: mov al, status and al, 10001100b ; preserva i bit 2, 3 e 7 cmp al, 10001100b ; verifica che siano settati je Label Si supponga di voler confrontare gli interi senza segno in AX e BX e spostare il maggiore in DX mov dx, ax cmp ax, bx jae L1 ; se ax >= bx salta a L1 mov dx, bx ; else bx maggiore L1: ; dx contiene il maggiore 149 / 254
Elaborazione condizionata Istruzione jcond / 12 Si supponga di voler confrontare i valori senza segno memorizzati nelle variabili V1, V2 e V3 il minore dei tre viene poi spostato in ax:.data v1 word? v2 word? v3 word?.code start: mov ax, v1 cmp ax, v2 jbe L1 mov ax, v2 L1: cmp ax, v3 jbe L2 mov ax, v3 L2:... 150 / 254
Elaborazione condizionata Istruzione jcond / 13 Ricerca del primo elemento non nullo in un array.data intvec sword 0, 0, 0, 0, 1, 20, 35, -12, 66, 4, 0 niente byte "Non sono stati trovati valori non nulli",0.code start: mov ax, @data mov ds, ax mov bx, offset intvec mov cx, lengthof intvec L1: cmp word ptr [bx], 0 jnz trovato add bx, 2 loop L1 jmp nontrovato trovato: mov dx, word ptr[bx] add dx, 30h mov ah, 2h int 21h jmp quit nontrovato: mov dx, offset niente mov ah, 9h int 21h quit: mov ax, 4c00h int 21h end start 151 / 254
Elaborazione condizionata Istruzioni di bit testing Le istruzioni BT, BTC, BTR e BTS sono chiamate istruzioni di bit testing. Sono importanti perchè effettuano più operazioni all interno di una singola operazione atomica L istruzione BT (bit test) seleziona l n-esimo bit del primo operando e lo copia nel Carry flag: BT bitbase, n Il primo operando (bitbase) non viene modificato. Gli operandi consentiti sono: BT r/m16, r16 BT r/m32, r32 BT r/m16, imm8 BT r/m32, imm8 152 / 254
Elaborazione condizionata Istruzioni di bit testing / 2 Per esempio:.data semaforo word 10001000b.code... BT semaforo, 7 ; CF = 1 In alternativa (ma molto più rischioso): mov ax, semaforo ; semaforo word 10001000b shr ax, 8 ; CF = 1 ; in modalit reale shift di 1 153 / 254
Elaborazione condizionata Istruzioni di bit testing / 2 - Esempio.model small.stack 100h.data semaforo byte 10001000b.code start: mov dl, semaforo mov cx, 7 L1: shr dl, 1 loop L1 mov ah, 02h int 21h mov ax, 4c00h int 21h end start 154 / 254
Elaborazione condizionata Istruzioni di bit testing / 3 L istruzione BTC (bit test and complement) seleziona il bit n nel primo operando, lo copia nel Carry flag e lo complementa BTC bitbase, n Gli operandi consentiti sono gli stessi dell istruzione BT..data semaforo word 10001000b.code... BTC semaforo, 6 ; CF = 0, semaforo = 11001000b 155 / 254
Elaborazione condizionata Istruzioni di bit testing / 4 L istruzione BTR (bit test and reset) seleziona il bit n nel primo operando, lo copia nel Carry flag e lo azzera BTR bitbase, n Gli operandi consentiti sono gli stessi dell istruzione BT..data semaforo word 10001000b.code... BTR semaforo, 7 ; CF = 1, semaforo = 00001000b 156 / 254
Elaborazione condizionata Istruzioni di bit testing / 5 L istruzione BTS (bit test and set) seleziona il bit n nel primo operando, lo copia nel Carry flag e lo setta BTS bitbase, n Gli operandi consentiti sono gli stessi dell istruzione BT..data semaforo word 10001000b.code... BTS semaforo, 6 ; CF = 1, semaforo = 11001000b 157 / 254
Aritmetica dei numeri interi Operatori di traslazione e rotazione SHL (shift left) SHR (shift right) SAL (shift arithmetic left) SAR (shift arithmetic right) ROL (rotate left) ROR (rotate right) RCL (rotate carry left) RCR (rotate carry right) Lo shift logico riempie di zeri le posizioni che si liberano, mentre lo shift aritmetico riempie le posizioni che si liberano con il bit di segno del numero soggetto a traslazione 158 / 254
Operatori di traslazione e rotazione Istruzione SHL Effettua uno shift logico a sinistra ponendo a zero il bit meno significativo Il bit più significativo viene spostato nel Carry flag, sovrascrivendone il contenuto SHL destination, count Gli operandi consentiti sono: SHL reg, imm8 SHL mem, imm8 SHL reg, CL SHL mem, CL 159 / 254
Operatori di traslazione e rotazione Istruzione SHL / 2 I processori 8086 e 8088 richiedono che imm8 sia uguale a 1 nei modelli più recenti imm8 pu assumere qualsiasi valore CL può contenere un intero utilizzato come contatore (su qualsiasi processore) Le stesse regole si applicano anche agli altri operatori di traslazione e rotazione mov bl, 8Fh ; bl = 1001111b shl bl, 1 ; bl = 0011110b, CF = 1 160 / 254
Operatori di traslazione e rotazione Istruzione SHL / 3 SHL viene utilizzato per la moltiplicazione veloce per potenze di 2 Infatti, shiftare di n bit a sinistra significa moltiplicare l operando per 2 n Per esempio: mov dl, 5 ; dl = 00000101 5 shl dl, 1 ; dl = 00001010 10... mov dl, 10 ; dl = 00001010 10 shl dl, 2 ; dl = 00101000 40 161 / 254
Operatori di traslazione e rotazione Istruzione SHR Effettua uno shift logico a destra ponendo a zero il bit pi significativo Il bit meno significativo viene spostato nel Carry flag, sovrascrivendone il contenuto SHR destination, count mov al, 0d0h ; al = 11010000b shr al, 1 ; al = 01101000b, CF = 0 162 / 254
Operatori di traslazione e rotazione Istruzione SHR / 2 SHR viene utilizzato per la divisione veloce per potenze di 2 Infatti, shiftare di n bit a destra significa dividere l operando per 2 n Per esempio: mov dl, 32 ; dl = 00100000 32 shr dl, 1 ; dl = 00010000 16... mov al, 01000000b ; al = 64 shr al, 3 ; al = 00001000b 8 163 / 254
Operatori di traslazione e rotazione Istruzioni SAL e SAR L istruzione SAL effettua uno shift aritmetico a sinistra identica a SHL L istruzione SAR effettua uno shift aritmetico a destra La sintassi è identica a quella delle istruzioni SHL e SHR mov al, 0f0h ; al = 11110000b (-16) sar al, 1 ; al = 11111000b (-8) CF = 0... mov dl, -128 ; dl = 10000000b (-128) sar dl, 3 ; dl = 11110000b (-16) 164 / 254
Operatori di traslazione e rotazione Istruzione ROL L istruzione ROL effettua una rotazione di tutti i bit verso sinistra Il bit più significativo viene copiato nel Carry flag Si noti che nella rotazione, a differenza dello shift, non si ha perdita di bit La sintassi è identica a quella delle istruzioni SHL e SHR mov al, 40h ; al = 01000000b rol al, 1 ; al = 10000000b CF = 0 rol al, 1 ; al = 00000001b CF = 1 rol al, 1 ; al = 00000010b CF = 0... mov al, 26h rol al, 4 ; al = 62h 165 / 254
Operatori di traslazione e rotazione Istruzione ROR L istruzione ROR effettua una rotazione di tutti i bit verso destra Il bit meno significativo viene copiato nel Carry flag La sintassi è identica a quella delle istruzioni SHL e SHR mov al, 01h ; al = 00000001b ror al, 1 ; al = 10000000b CF = 1 ror al, 1 ; al = 01000000b CF = 0 166 / 254
Operatori di traslazione e rotazione Istruzione RCL L istruzione RCL effettua una rotazione di tutti i bit verso sinistra, copia il Carry flag nel bit meno significativo e copia il bit più significativo nel Carry flag L istruzione CLC resetta il Carry flag clc ; CF = 0 mov bl, 88h ; bl = 10001000b CF = 0 rcl bl, 1 ; bl = 00010000b CF = 1 rcl bl, 1 ; bl = 00100001b CF = 0 167 / 254
Operatori di traslazione e rotazione Istruzione RCR L istruzione RCR effettua una rotazione di tutti i bit verso destra, copia il Carry flag nel bit più significativo e copia il bit meno significativo nel Carry flag L istruzione STC setta il Carry flag stc ; CF = 1 mov ah, 10h ; ah = 00010000b CF = 1 rcr ah, 1 ; ah = 10001000b 168 / 254
Operatori di traslazione e rotazione Moltiplicazione binaria L istruzione SHL consente di effettuare efficientemente moltiplicazioni per potenze di 2 Qualsiasi numero binario può essere espresso come la somma di potenze di 2 Per esempio, la moltiplicazione di AX per 36 può essere vista come la moltiplicazione per 32 + 4, quindi: AX * 36 = AX * ( 32 + 4) = AX * 32 + AX * 4 mov ax, 123 mov bx, ax shl ax, 5 shl bx, 2 add ax, bx 169 / 254
Operatori di traslazione e rotazione Isolamento di stringhe di bit La funzione MS-DOS 57h restituisce la data di un file nel registro DX I bit 0-4 indicano il giorno (1-31), i bit 5-8 indicano il mese, i bit 9-15 l anno La data 20-05-2010 viene quindi indicata come (l anno viene riferito al 1980, cioè 30): 0011110 0101 01010 30 05 20 Per estrarre il giorno: mov al, dl and al, 00011111b mov giorno, al 170 / 254
Moltiplicazione e divisione Istruzione MUL L istruzione MUL moltiplica un operando a 8, 16 o 32 bit per il contenuto dei registri AL, AX o EAX (rispettivamente) MUL accetta quindi un solo operando, con formati: MUL r/m8 MUL r/m16 MUL r/m32 Il prodotto è contenuto in un registro doppio rispetto alle dimensioni del moltiplicando e del moltiplicatore, per garanzia dagli overflow Moltiplicando Moltiplicatore Prodotto AL r/m8 AX AX r/m16 DX:AX EAX r/m32 EDX:EAX 171 / 254
Moltiplicazione e divisione Istruzione MUL / 2 L istruzione MUL setta i flag Carry (CF) e Overflow (OF) soltanto se la metà superiore del prodotto non è zero Per esempio, quando AX viene moltiplicato per un operando a 16 bit, il prodotto viene memorizzato in DX:AX Se DX non è uguale a zero, il Carry flag viene settato mov al, 5h mov bl, 10h mul bl ; CF = 0 mov ax, var1 ; var1 word 2000h mul var2 ; var2 word 0100h; CF = 1 172 / 254
Moltiplicazione e divisione Istruzione IMUL L istruzione IMUL effettua la moltiplicazione tra interi con segno L unica differenza con MUL consiste nel preservare il segno del prodotto Vengono settati i flag Carry e Overflow quando il registro che contiene la parte più significativa del prodotto non è un estensione di segno della parte meno significativa 173 / 254
Moltiplicazione e divisione Istruzione IMUL / 2 ; 1. moltiplicazione con segno 48 * 4 mov al, 48 mov bl, 4 imul bl ; ax = 00c0h, OF = 1 ; (ah non e un estensione di segno di al) ; 2. moltiplicazione con segno -4 * 4 mov al, -4 mov bl, 4 imul bl ; ax = fff0h, OF = 0 ; (ah e un estensione di segno di al) ; 3. moltiplicazione con segno 48 * 4 mov ax, 48 mov bx, 4 imul bx ; dx:ax = 000000c0h, OF = 0 ; (dx e un estensione di segno di ax) 174 / 254
Moltiplicazione e divisione Istruzione DIV L istruzione DIV effettua la divisione di interi a 8, 16 o 32 bit Viene fornito un solo operando, il divisore I formati accettati sono: DIV r/m8 DIV r/m16 DIV r/m32 Il risultato è memorizzato secondo il seguente schema: Dividendo Divisore Quoziente Resto AX r/m8 AL AH DX:AX r/m16 AX DX EDX:EAX r/m32 EAX EDX 175 / 254
Moltiplicazione e divisione Istruzione DIV / 2 mov ax, 0083h mov bl, 2 div bl ; al = 41h, ah = 01h mov dx, 0 mov ax, 8003h mov cx, 100h div cx ; ax = 0080h, dx = 0003h 176 / 254
Moltiplicazione e divisione Istruzioni di conversione L istruzione CBW (Convert Byte to Word) estende il bit di segno di AL nel registro AH L istruzione CWD (Convert Word to Double) estende il bit di segno di AX nel registro DX L istruzione CDQ (Convert Double to Quad) estende il bit di segno di EAX nel registro EDX Questo preserva il segno del numero.data bvar sbyte -101.code mov al, bvar cbw ; 9bh ; al = 9bh ; ax = ff9bh 177 / 254
Moltiplicazione e divisione Istruzioni di conversione / 2.data wvar sword -101.code mov ax, wvar cwd ; ff9bh ; ax = ff9bh ; dx:ax = ffffff9bh.data dvar sdword -101.code mov eax, dvar cdq ; ffffff9bh ; edx:eax = ffffffffffffff9bh 178 / 254
Moltiplicazione e divisione Istruzione IDIV L istruzione IDIV effettua la divisione di interi con segno Gli operandi sono gli stessi dell istruzione DIV Quando si effettua la divisione, bisogna prima estendere il segno del dividendo nel secondo registro (ah per la divisione a 8 bit, dx a 16bit) mov al, bvar ; dividendo (bvar sbyte -48) cbw ; estensione del segno in ah mov bl, 5 ; divisore idiv bl ; al = -9, ah = -3 mov ax, wvar ; dividendo (wvar sword -5000) cwd ; estensione del segno in dx mov bx, 256 ; divisore idiv bx ; quoziente ax = -19, resto dx = -136 179 / 254
Moltiplicazione e divisione Overflow di divisione Se una divisione produce un quoziente troppo grande per essere contenuto nell operando destinazione, viene generato un divide overflow Questo provoca un interrupt di CPU e la terminazione del programma Per esempio: mov ax, 1000h mov bl, 10h div bl ; al = 100h IMPOSSIBILE mov ax, dividendo mov bl, 0 div bl 180 / 254
Moltiplicazione e divisione Overflow di divisione / 2 Una soluzione potrebbe essere l utilizzo di registri più grandi Ma non si tratta di una soluzione che garantisce in tutti i casi Molto meglio verificare sempre prima che, almeno, il divisore non sia nullo mov ax, dividendo mov bl, divisore cmp bl, 0 je DivZero div bl... divzero: ; messaggio di errore per tentata divisione per zero 181 / 254
Moltiplicazione e divisione Espressioni aritmetiche var4 = (var1 + var2) * var3 mov ax var1 add ax, var2 mul var3 jc overflow mov var4, ax jmp prossimo overflow: ; messaggio di errore per overflow 182 / 254
Moltiplicazione e divisione Espressioni aritmetiche / 2 var4 = (var1 * 5) / (var2-3) mov ax var1 mov bx, 5 mul bx mov bx, var2 sub bx, 3 div bx mov var4, bx 183 / 254
Moltiplicazione e divisione Espressioni aritmetiche / 3 var4 = (var1 * -5) / (-var2 % var3) mov ax, var2 neg ax cbw idiv var3 mov bx, dx mov ax -5 imul var1 idiv bx mov var4, dx 184 / 254
Moltiplicazione e divisione Addizione e sottrazione in precisione estesa Permettono di sommare e sottrarre numeri con dimensione (quasi) illimitata a tale scopo si utilizzano le istruzioni ADC (Add with Carry) e SBB (Sub with Borrow) L istruzione ADC somma l operando sorgente e il contenuto del Carry flag ad un operando destinazione I formati consentiti sono identici a quelli dell istruzione MOV ADC reg, reg ADC mem, reg ADC reg, mem ADC mem, imm ADC reg, imm 185 / 254
Moltiplicazione e divisione Addizione e sottrazione in precisione estesa / 2 Per esempio: mov dl, 0 mov al, 0ffh add al, 0ffh ; al = fe adc dl, 0 ; dl = 01 186 / 254
Moltiplicazione e divisione Addizione e sottrazione in precisione estesa / 3 L istruzione SBB sottrae un operando sorgente e il valore del Carry flag da un operando destinazione I possibili operandi sono identici a quelli dell istruzione ADC Per esempio: mov dx, 1 mov ax, 0 sub ax, 1 sbb dx, 0 187 / 254
Moltiplicazione e divisione Aritmetica decimale in formato ASCII La CPU effettua i calcoli in binario, ma è possibile effettuare operazioni aritmetiche su stringhe decimali in formato ASCII A tale scopo sono necessarie istruzioni specifiche che permettano di operare su ogni coppia di cifre ASCII Si consideri per esempio il numero 3402, che può essere rappresentato come: Formato unpacked: 03 04 00 02 Formato ASCII : 33 34 30 32 L aritmetica in formato ASCII è lenta perchè viene effettuata cifra a cifra, ma consente di operare su grandi numeri Infatti i numeri vengono in effetti visti come stringhe di caratteri 188 / 254
Moltiplicazione e divisione Aritmetica decimale in formato ASCII / 2 L istruzione AAA (ASCII adjust after addition) sistema il risultato binario di un istruzione ADD o ADC Il risultato presente nel registro AL viene reso consistente con la rappresentazione ASCII Per esempio: mov ah, 0 mov al, 8 ; ax = 0038h add al, 2 ; ax = 006ah aaa ; ax = 0100h or ax, 3030h ; ax = 3130h = 10 189 / 254
Moltiplicazione e divisione Aritmetica decimale in formato ASCII / 3 L istruzione AAS (ASCII adjust after subtraction) sistema il risultato binario di un istruzione SUB o SBB Il risultato presente nel registro AL viene reso consistente con la rappresentazione ASCII La correzione è necessaria soltanto quando la sottrazione produce un risultato negativo Per esempio: mov ah, 0 mov al, var1 sub al, var2 aas pushf or al, 30h popf ; var1 byte 8 ; ax = 0038h ; var2 byte 9 ; ax = 00ffh ; ax = ff09h ; ax = ff39h 190 / 254
Moltiplicazione e divisione Aritmetica decimale in formato ASCII / 4 L istruzione AAM (ASCII adjust after multiplication) sistema il risultato binario di un istruzione MUL La moltiplicazione deve essere effettuata su numeri decimali unpacked, cioè non su cifre ASCII Per esempio:.data val byte 05h, 06h.code mov bl, val mov al, [val+1] mul bl aam ; primo operando ; secondo operando ; ax = 001eh ; ax = 0300h 191 / 254
Moltiplicazione e divisione Aritmetica decimale in formato ASCII / 5 L istruzione AAD (ASCII adjust before division) sistema il dividendo decimale unpacked in AX prima di una divisione Per esempio:.data quoziente byte resto byte.code mov ax, 0307h aad mov bl, 5 div bl mov quoziente, al mov resto, ah ; dividendo ; ax = 0025h ; divisore 192 / 254
Procedure avanzate Variabili locali Una variabile locale una variabile che viene creata, utilizzata e distrutta all interno di una procedura Tutte le variabili viste in precedenza sono state definite nel segmento data; vengono definite variabili globali statiche: statiche: ciclo di vita di una variabile uguale alla durata del programma globali: visibili da tutte le procedure del programma Le variabili locali presentano una serie di vantaggi: accesso limitatato, perch soltanto un numero ridotto di istruzioni possono accedervi uso efficiente della memoria, perch al termine della procedura vengono distrutte con conseguente risparmio della memoria la stessa variabile pu apparire in due o pi procedure senza creare conflitti di nome 193 / 254
Procedure avanzate Variabili locali / Direttiva LOCAL La direttiva LOCAL dichiara una o pi variabili locali all interno di una procedura deve essere posta immediatamente dopo la direttiva PROC (vedi pi avanti) La sua sintassi : LOCAL lista_var La definizione di ogni variabile assume la forma: label: type 194 / 254
Procedure avanzate Variabili locali / Direttiva LOCAL / 2 Per esempio: MySub PROC LOCAL var1: byte... ENDP BubbleSort PROC LOCAL temp: word, swapflag: byte... ENDP Merge PROC LOCAL pvec: ptr word... ENDP 195 / 254
Procedure avanzate Variabili locali / Direttiva LOCAL / 3 Quando si creano variabili locali bisogna fare attenzione all allocazione dello spazio nello stack In particolare, se le procedure sono annidate, lo spazio necessario sar la somma di tutte le variabili locali Si supponga, per esempio, che Sub1 chiami Sub2, che a sua volta chiama Sub3 Sub1 PROC LOCAL array1[50]: word... Sub2 PROC LOCAL array2[80]: word... Sub3 PROC LOCAL array3[300]: byte ; 200 byte ; 160 byte ; 300 byte Quando inizia l esecuzione di Sub3, le variabili locali occuperanno un totale di 660 byte, pi gli indirizzi di ritorno delle procedure e i registri eventualmente salvati sullo stack 196 / 254
Procedure avanzate Parametri di stack e parametri di registro Definizione: i valori passati ad una procedura da un programma chiamante si dicono argomenti; gli stessi valori, dal punto di vista della procedura invocata, si dicono parametri Esistono due tipi fondamentali di parametri di procedura: i parametri di registro e i parametri di stack I parametri di registro velocizzano l esecuzione dei programmi, ma bisogna salvare lo stato dei registri prima che vengano caricati con i valori degli argomenti I parametri di stack sono i parametri di una procedura che vengono caricati sullo stack dal programma chiamante 197 / 254
Procedure avanzate Parametri di stack e parametri di registro / 2 Esempio di parametri di registro pusha mov si, offset array mov cx, lengthof array mov bx, type array call Sub popa Esempio di parametri di stack push type array push lengthof array push offset array call Sub 198 / 254
Procedure avanzate Parametri di stack e parametri di registro / 3 La direttiva INVOKE automaticamente effettua il push degli argomenti sullo stack e invoca la procedura INVOKE Sub, offset array, lengthof array, type array I tipi di argomenti che si possono utilizzare con INVOKE sono: Tipo Esempio valore immediato 10, 300h, offset lista, type array espressione intera (10 * 20), count nome di variabile lista, array, bvar, wvar espressione di indirizzo [bx + si], [lista + 2] nome di registro ax, bl, ebx ADDR nome ADDR lista 199 / 254
Procedure avanzate Parametri di stack e parametri di registro / 4 L operatore ADDR pu essere utilizzato per passare un puntatore quando si invoca una procedura con la direttiva INVOKE Il passaggio di un indirizzo come argomento di una procedura viene detto passaggio per riferimento Per esempio: INVOKE Subarray, ADDR vec In modalit reale, ADDR restituisce un offset a 16 bit.data vec byte 50 dup(?).code INVOKE Subarray, ADDR vec 200 / 254
Procedure avanzate Direttiva PROC La direttiva PROC permette di dichiarare una procedura seguita da una lista di parametri La sintassi : label PROC, parametro_1, parametro_2,... parametro_n Oppure: label PROC, parametro_1, parametro_2,..., parametro_n 201 / 254
Procedure avanzate Direttiva PROC / 2 Un singolo parametro ha la seguente sintassi: parametro: type parametro un nome arbitrario che si assegna al parametro la sua visibilit limitata alla procedura corrente lo stesso nome di parametro pu essere utilizzato in pi procedure, ma non pu essere il nome di una variabile globale o di una label di codice il tipo di dato pu essere: byte, sbyte, word, sword, dword, sdword, oppure ptr byte, ptr sbyte,..., ptr sdword 202 / 254
Procedure avanzate Direttiva PROC / 3 Somma PROC, val1: dword, val2: dword... Somma ENDP Subvec PROC, pvec: ptr byte... Subvec ENDP ReadFile PROC, pbuffer: ptr byte local filehandle: dword... ReadFile ENDP 203 / 254
Procedure avanzate Direttiva PROTO La direttiva PROTO crea un prototipo per una procedura esistente Un prototipo dichiara il nome di una procedura e la lista dei parametri Permette di invocare una procedura senza bisogno di definirla MASM richiede un prototipo per ogni procedura invocata mediante istruzione INVOKE PROTO deve precedere sempre l istruzione INVOKE relativa 204 / 254
Procedure avanzate Direttiva PROTO Le due possibili implementazioni sono: Sub1 PROTO INVOKE Sub1 Sub PROC... Sub ENDP ; prototipo ; invocazione ; codifica Sub PROC... Sub ENDP INVOKE Sub1 ; codifica ; invocazione 205 / 254
Procedure avanzate Operatore USES L operatore USES, utilizzato insieme alla direttiva PROC permette di elencare i nomi di tutti i registri modificati nel corso dell esecuzione di una procedura Le conseguenze dell utilizzo di USES sono: generare istruzioni push all inizio della procedura generare istruzioni pop alla fine della procedura Per esempio: VecSum PROC USES si, cx mov ax, 0 L1: add ax, [si] add si, 4 loop L1 ret VecSUM ENDP 206 / 254
Procedure avanzate Operatore USES / 2 Esempio (somma di due vettori) VecSum proc uses si, cx, ptrvec: ptr word, sizevec: word mov si, ptrvec mov cx, sizevec cmp cx, 0 je L2 mov ax, 0 L1: add ax, [si] add si, 2 loop L1 L2: ret SumVec endp 207 / 254
Procedure avanzate Passaggio di argomenti per valore Un argomento viene passato ad una procedura per valore quando viene passata una copia della variabile Questa tecnica preserva il valore originale della variabile Funzionamento: la variabile viene copiata sullo stack dalla procedura chiamante la procedura invocata recupera il valore dallo stack e lo utilizza 208 / 254
Procedure avanzate Passaggio di argomenti per valore / 2 Esempio:.data var word 1000h.code main PROC INVOKE Sub1, var exit main ENDP Sub1 PROC dato: word mov dato, 0 ret Sub1 ENDP 209 / 254
Procedure avanzate Passaggio di argomenti per riferimento Alla procedura viene passato l indirizzo di una variabile La procedura invocata ha la possibilit di modificare il valore originale della variabile Come regola generale bisognerebbe utilizzare questa tecnica soltanto quando si vuole che la procedura modifichi il dato trasmesso Eccezione: la trasmissione di strutture dati (array) dovrebbe essere effettuata per riferimento, ma solo per motivi di prestazioni e di occupazione delle risorse 210 / 254
Procedure avanzate Passaggio di argomenti per riferimento / 2 Esempio:.data var word 1000h.code main PROC INVOKE Sub2, addr var exit main ENDP Sub1 PROC datoptr: ptr word mov si, datoptr mov word ptr[si], 0 ret ret Sub2 ENDP 211 / 254
Organizzazione della memoria 212 / 254
Organizzazione della memoria / 2 In modalità reale, i 640K di memoria sono utilizzati sia dal sistema operativo che dai programmi applicativi le locazioni da C0000 a FFFFF sono riservate per la ROM di sistema all interno dell area riservata al sistema operativo, i 1024 byte più bassi (da 00000 a 003FF) contengono una tabella di indirizzi a 32 bit denominata tabella dei vettori di interrupt immediatamente dopo, è presente l area BIOS & DOS area nell area Software BIOS sono presenti le procedure per la gestione dei dispositivi di I/O (tastiera, disk drive, video, porte di I/O) nell area DOS Kernel, Device Drivers sono contenuti i buffer e i driver dei dispositivi nell area Resident command processor è contenuto l interprete dei comandi, caricato dall eseguibile command.com 213 / 254
Organizzazione della memoria / 3 I programmi applicativi possono essere caricati in memoria nel primo indirizzo superiore alla parte residene del processore dei comandi e utilizzare tutta la memoria fino all indirizzo 9FFFF L area di memoria video (VRAM) inizia alla locazione A0000 quando invece viene utilizzata in modalità color text mode la locazione B8000 contiene tutto il testo correntemente mostrato a schermo Lo schermo si dice memory-mapped, nel senso che ogni riga e colonna dello schermo corrisponde ad un word in memoria Un carattere copiato nella memoria video appare immediatamente sullo schermo 214 / 254
Ridirezione I/O I dispositivi noti come standard input e standard output rappresentano la tastiera per l input e il video per l output È possibile ridirigere lo standard input così che venga letto da un file o da una porta hardware piuttosto che dalla tastiera lo standard output può essere ridiretto verso un file, una stampante, un dispositivo di I/O Si consideri per esempio un programma prog.exe Può leggere i dati di input da tastiera oppure da un file Nel secondo caso si può scrivere (da linea di comando): prog.exe < prog-in.txt 215 / 254
Ridirezione I/O / 2 Analogamente, è possibile ridirigere lo standard output prog.exe > prog-out.txt Oppure entrambi prog.exe < prog-in.txt > prog-out.txt Si noti che la scelta dei nomi dei file sui quali effettuare la ridirezione del tutto libera! 216 / 254
Ridirezione I/O / 3 E possibile utilizzare il simbolo di pipe perchè l output di un comando diventi l input del comando posto a destra della pipe Per esempio: dir sort L output del programma sort può essere a sua volta ridiretto (come si potrebbe fare anche per l input del comando dir): dir sort > prn 217 / 254
Funzioni di int 21h L interrupt DOS int 21h presenta numerose funzioni oltre a quelle già viste Una di questa è la funzione 6, che stampa un carattere su standard output mov ah, 6 mov dl, "A" int 21h Si ricordi che: AH = 6, DL = carattere 218 / 254
Funzioni di int 21h / 2 La funzione 40h scrive un array di byte su un file o un dispositivo Si ricordi che: AH = 40h, BX = file o dispositivo (console = 1), CX = numero di byte da scrivere, DX = indirizzo dell array.data msg "Ciao a tutti".code mov ah, 40h mov bx, 1 mov cx, lengthof msg mov dx, offset msg int 21h 219 / 254
Funzioni di int 21h / 3 Esempio.model small.stack 100h.data msg byte "Ciao a tutti", 13, 10.code main PROC mov ax, @data mov ds, ax mov ah, 40h mov bx, 1 mov cx, sizeof msg mov dx, offset msg int 21h mov ax, 4c00h int 21h end main 220 / 254
Funzioni di int 21h / 3a Creazione file con 3ch La funzione 3ch permette di creare/troncare un file Registri DX CX AX Descrizione offset filename (ASCIIZ) Attributi file 0 Normal 1 Read only 2 Hidden 3 System Codici di errore 3 Path not found 4 No handle available (too many files) 5 Access denied 221 / 254
Funzioni di int 21h / 3b Creazione file con 3ch ;f40-creat.asm.model small.stack 100h.data fh byte "provatxt.txt",0.code start: mov ax, @data mov ds, ax mov dx, offset fh mov cx, 0 mov ah, 3ch int 21h... 222 / 254
Funzioni di int 21h / 3c Apertura file con 3dh La funzione 3dh permette di aprire un file già esistente Registri DX AL AX Descrizione offset filename (ASCIIZ) Codice di accesso 0 Read 1 Write 2 Read/Write Codici di errore 2 File not found 3 Path does not exist 4 No handle available (too many files) 5 Access denied 0ch Access code invalid 223 / 254
Funzioni di int 21h / 3d Apertura file con 3dh ; f40-open.asm.model small.stack 100h.data fh byte "provatxt.txt",0.code start: mov ax, @data mov ds, ax mov dx, offset fh mov al, 1 mov ah, 3dh int 21h... 224 / 254
Funzioni di int 21h / 3e Lettura file con 3fh La funzione 3fh permette di leggere da un file (già esistente) Registri BX Descrizione file handle DX offset buffer CX numero di byte da leggere AX numero di byte letti AX 0 Raggiunto EOF AX Codici di errore 5 Access denied 6 Invalid handle or not open 225 / 254
Funzioni di int 21h / 3f Lettura file con 3fh....data buf byte 50 dup( + ),"$", 13, 10... mov bx, ax mov ah, 3fh mov cx, 9 mov dx, offset buf int 21h... 226 / 254
Funzioni di int 21h / 3g Scrittura su file con 40h La funzione 40h permette di scrivere su un file (già esistente) Registri BX Descrizione file handle DX offset buffer CX numero di byte da scrivere AX numero di byte scritti AX 0 Disk full AX Codici di errore 5 Access denied 6 Invalid handle or not open 227 / 254
Funzioni di int 21h / 3h Scrittura su file con 40h....data msg byte "Ciao a tutti"... mov bx, ax mov ah, 40h mov cx, lengthof msg mov dx, offset msg int 21h... 228 / 254
Funzioni di int 21h / 4 La funzione 6 legge un carattere dallo standard input senza attendere A differenza della funzione 1 non si ha attesa in caso di buffer vuoto e non si ha echo del carattere digitato salta: mov ah, 6 mov dl, 0ffh int 21h jz salta mov char, al 229 / 254
Funzioni di int 21h / 5 La funzione 0ah legge una stringa bufferizzata dallo standard input terminata da Enter L invocazione di questa funzione richiede che si passi un puntatore ad una struttura di input avente il seguente formato: count = 80 KEYBOARD struct maxinput byte count inputcount byte? buffer byte count dup(?) KEYBOARD ends ; numero max di caratteri in input ; conta effettiva caratteri ; contenitore caratteri di input 230 / 254
Funzioni di int 21h / 6 Il campo maxinput specifica il numero massimo di caratteri da inserire, compreso Enter E possibile utilizzare Backspace per cancellare caratteri I caratteri non ASCII (per esempio, i tasti funzione e le frecce) vengono ignorati.data kbd KEYBOARD <>.code mov ah, 0ah mov dx, offset kbd int 21h 231 / 254
Funzioni di int 21h / 7 La funzione 0ah viene spesso utilizzata in congiunzione con la funzione 0bh, che restituisce lo stato del buffer di input Se presente un carattere AL = 0ffh, altrimenti AL = 0 mov ah, 0bh int 21h cmp al, 0 je salta ; procedura di acquisizione del carattere salta: 232 / 254
Funzioni di int 21h / 8 La funzione 3fh legge un array di byte da un file o da una dispositivo Può essere utilizzata per l input da tastiera quando il dispositivo in BX viene posto a zero.data inputbuffer byte 127 dup(0) bytesread word?.code mov ah, 3fh mov bx, 0 mov cx, lengthof inputbuffer mov dx, offset inputbuffer int 21h mov byteread, ax 233 / 254
Funzioni di int 21h / 9 Eventuali caratteri in eccesso rimangono nel buffer Invocazioni successive provocano la lettura dei dati dal buffer e non dalla tastiera, quindi è bene vuotare il buffer cleanbuff proc.data unbyte byte?.code pusha L1: mov ah, 3fh mov bx, 0 mov cx, 1 mov dx, offset unbyte int 21h cmp unbyte, 0ah jne L1 popa ret cleanbuff endp 234 / 254
Funzioni di int 21h / 10 Funzioni date/time La funzione 2ah permette di ottenere la data di sistema, mentre la funzione 2bh ne permette la regolazione mov ah, 2ah int 21h mov anno, cx mov mese, dh mov giorno, dl mov giornosett, al... mov ah, 2bh mov cx, nuovoanno mov dh, nuovomese mov dl, nuovogiorno int 21h cmp al, 0 jne fallita 235 / 254
Funzioni di int 21h / 11 Funzioni date/time Analogamente, la funzione 2ch permette di ottenere l ora di sistema, e la funzione 2dh ne permette la regolazione mov ah, 2ch int 21h mov ora, ch mov min, cl mov sec, dh... mov ah, 2bh mov ch, new_ora mov cl, new_min mov dh, new_sex int 21h cmp al, 0 jne fallita 236 / 254
Funzioni di int 21h / 12 Funzioni di I/O da file e directory L interrupt int 21h fornisce una (lunga) serie di servizi per la gestione dell I/O di file e directory Le funzioni utilizzate più di frequente sono: Funzione 716Ch 3Eh 42h 5706h Descrizione Crea o apre un file Chiude l handle di un file Sposta il puntatore al file Ottiene data e ora di creazione del file 237 / 254
Funzioni di int 21h / 13 Funzioni di I/O da file e directory File e directory sono identificati mediante interi a 16 bit denominati handle Esistono 5 handle predefiniti Ad eccezione dell handle 2 (errore) permettono tutti la ridirezione al prompt dei comandi Gli handle disponibili in qualunque momento sono: Numero Descrizione 0 Tastiera (standard input) 1 Console (standard output) 2 Errore 3 Dispositivo ausiliario 4 Stampante 238 / 254
Funzioni di int 21h / 14 Funzioni di I/O da file e directory Codice Tutte le funzioni di I/O generano, in caso di errore, un codice restituito nel registro AX: Descrizione 01 Invalid function number 02 File not found 03 Path not found 04 Too many open files 05 Access denied 06 Invalid handle 07 Memory control blocks destroyed 08 Insufficient memory 09 Invalid memory block address 0A Invalid environment 0B Invalid format 0C Invalid access code 0D Invalid data 0E Reserved 0F Invalid drive was specified 239 / 254
Funzioni di int 21h / 15 Funzioni di I/O da file e directory Codice Continua: Descrizione 10 Attempt to remove current directory 11 Not same device 12 No more files 13 Diskette write-protected 14 Unknown unit 15 Drive not ready 16 Unknown command 17 Data error (CRC) 18 Bad request structure length 19 Seek error 1A Unknown media type 1B Sector not found 1C Printer out of paper 1D Write fault 1E Read fault 1F General failure 240 / 254
Funzioni di int 21h / 16 Funzioni di I/O da file e directory La funzione 716Ch permette di creare un nuovo file o di aprirne uno esistente Lo stato dei registri è: Registro AX BX CX DX SI Stato 716Ch 0 = read, 1 = write, 2 = read/write 0 = normal, 1 = read-only, 2 = hidden 3 = system, 8 = volume ID, 20h = archive 1 = open, 2 = truncate, 10h = create offset filename 241 / 254
Funzioni di int 21h / 16bis Funzioni di I/O da file e directory Esempio: mov ax, 716ch mov bx, 0 mov cx, 0 mov dx, 1 mov si, offset filename int 21h jc fallita mov handle, ax mov azione, cx ; read-only ; attributo normale ; file esistente ; handle del file 242 / 254
Funzioni di int 21h / 18 Funzioni di I/O da file e directory Esempio n. 2 (creazione nuovo file o troncamento file esistente): mov ax, 716ch mov bx, 2 mov cx, 0 mov dx, 10h+02h mov si, offset filename int 21h jc fallita mov handle, ax mov azione, cx ; read-write ; attributo normale ; creazione + troncamento ; handle del file 243 / 254
Funzioni di int 21h / 19 Funzioni di I/O da file e directory Esempio n. 3 (creazione nuovo file o fallimento se esistente): mov ax, 716ch mov bx, 2 mov cx, 0 mov dx, 10h mov si, offset filename int 21h jc fallita mov handle, ax mov azione, cx ; read-write ; attributo normale ; creazione ; handle del file 244 / 254
Funzioni di int 21h / 20 Funzioni di I/O da file e directory La funzione 3eh chiude un handle di file Il contenuto del buffer di scrittura viene scritto su disco Il registro BX deve contenere il file handle mov ah, 3eh mov bx, filehandle int 21h jc fallita 245 / 254
Funzioni di int 21h / 21 Funzioni di I/O da file e directory La funzione 42h sposta il puntatore alla posizione di un file aperto Il registro BX deve contenere il file handle Il registro CX:DX deve contenere il valore dell offset (32 bit) Il contenuto del registro AL pu essere: 0: offset dall inizio del file 1: offset dalla posizione corrente 2: offset dalla fine del file mov ah, 42h mov al, 0 mov bx, filehandle mov cx, offsethi mov dx, offsetlo int 21h 246 / 254
Funzioni di int 21h / 22 Funzioni di I/O da file e directory La funzione 5706h fornisce la data e l ora di creazione di un file Ovviamente, il file deve essere aperto Il registro BX deve contenere il file handle mov ah, 5706h mov bx, filehandle int 21h jc errore mov data, dx mov ora, cx mov msec, si 247 / 254
Funzioni di int 21h / 23 Funzioni di I/O da file e directory - Lettura e copia di un file di testo.data buffersize = 5000 ifile byte "ifile.txt",0 ofile byte "ofile.txt",0 ihandle word? ohandle word? buffer byte buffersize dup(?) bytesread word?.code main PROC mov ax, @data mov ds, ax mov ax, 716ch ; apertura file di input mov bx, 0 ; read-only mov cx, 0 ; normal mov dx, 1 ; open mov si, offset ifile int 21h jc esci mov ihandle, ax 248 / 254
Funzioni di int 21h / 24 Funzioni di I/O da file e directory - Lettura e copia di un file di testo / 2 mov ah, 3fh mov bx, ihandle mov cx, buffersize mov dx, offset buffer int 21h jc esci mov bytesread, ax mov ah, 40h mov bx, 1 mov cx, bytesread mov dx, offset buffer int 21h jc esci mov ah, 3eh mov bx, ihandle int 21h jc esci ; lettura file di input ; handle file di input ; max byte da leggere ; puntatore al buffer ; scrittura su file o device ; console ; chiusura file 249 / 254
Funzioni di int 21h / 24 Funzioni di I/O da file e directory - Lettura e copia di un file di testo / 3 mov ax, 716ch mov bx, 1 mov cx, 0 mov dx, 12h mov si, offset ofile int 21h jc esci mov ohandle, ax mov ah, 40h mov bx, ohandle mov cx, bytesread mvo dx, offset buffer int 21h jc esci ; creazione/apertura file ; write-only ; normal ; creazione/troncamento ; scrittura su file o device ; file handle mov ah, 3eh mov bx, ohandle int 21h 250 / 254
Funzioni di int 21h / 24 Funzioni di I/O da file e directory - Lettura e copia di un file di testo / 4 esci: mov dl, 13 mov ah, 2h int 21h mov dl, 10 mov ah, 2h int 21h mov ax, 4c00h int 21h main endp 251 / 254
Esempio Conversione di un numero da base decimale a base binaria.model small.stack 100h.data ni byte 10 dup(?) nf byte 10 dup(?).code start: mov ax, @data mov ds, ax mov si, 0 mov bl, 2 mov ax, 0 mov al, 29... Li: div bl mov ni[si], ah or ni[si], 30h inc si cmp al, 2 jc Lf mov ah, 0 jmp Li Lf: mov ni[si], al or ni[si], 30h... 252 / 254
Esempio Conversione di un numero da base decimale a base binaria (cont.)... mov di, 0 Lv: mov bl, ni[si] mov nf[di], bl mov bh, nf[di] inc di dec si cmp si, 0 jge Lv...... mov ah, 09h mov dx, offset ni int 21h mov dx, offset nf int 21h mov ax, 4c00h int 21h end start 253 / 254
Bibliografia K. Irvine, Assembly Language for Intel-Based Computers, 5th edition - Pearson/Prentice Hall - ISBN: 0-13-238310-1 Lyla B. Das, The x86 Microprocessor - Architecture, Programming and Interfacing, Pearson - ISBN: 978-81-317-3246-5 254 / 254