Programmazione Assembly Note su Microsoft Assembler

Programmazione Assembly
Note su Microsoft Assembler
Giacomo Fiumara
[email protected]
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
eax
ebx
ecx
edx
esi
edi
esp
ebp
eip
eflags
Nome
Accumulator
Base
Counter
Data
Source Index
Destination Index
Stack Pointer
Base Pointer
Instruction Pointer
Flag
16/8 bit
ax, ah, al
bx, bh, bl
cx, ch, cl
dx, dh, dl
si
di
sp
bp
ip
flag
Descrizione
Arithmetic and Logic
Arrays
Loops
Arithmetics
Strings and arrays
Strings and arrays
Top of stack
Base of stack
Points to next instruction
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
220 = 1.048.576 byte
Cioè dall’indirizzo 00000H all’indirizzo fffffH
La memoria è vista come suddivisa in quattro segmenti:
Segmento
Segmento
Segmento
Segmento
dati
codice
stack
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
small
compact
medium
large
Num. segmenti codice
1
1
più di 1
più di 1
Num. segmenti dati
1
più di 1
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
int
mov
mov
int
ah, 1h
21h
dl, al
ah, 2h
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
mov ah, 1h
int 21h
mov bl, al
.model small
.stack 100h
mov dl, ’ ’
mov ah, 2h
int 21h
.code
mov dl, bl
start:
mov ah, 2h
int 21h
mov dl, ’>’
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
;
mov bl, al
mov dl, 13d
mov ah, 2h
int 21h
.model small
.stack 100h
mov dl, 10d
mov ah, 2h
int 21h
.code
start:
mov dl, ’>’
mov ah, 2h
int 21h
mov ah, 1h
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
;
mov dx, offset stringa
mov ah, 9h
int 21h
.model small
.stack 100h
.data
stringa db ’Ciao a tutti’, 13, 10, ’\$’
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
Indirizzamento
Indirizzamento
Indirizzamento
Indirizzamento
Indirizzamento
Indirizzamento
mediante registri
immediato
diretto
indiretto mediante registri
relativo mediante registri
indicizzato
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
mov
mov
mov
al, 33h
cx, 1234h
al, ’c’
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
mov
mov
mov
ax, [1234h]
[5678h], al
var1, al
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
mov
add
add
mov
di, 0
al, array[di]
al, 07h
di, 05h
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
mov
mov
add
mov
bx,
di,
al,
al,
di,
offset array
0
[bx + di]
35h
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
numero
numero
numero
BYTE
BYTE
BYTE
BYTE
01100101b
65h
101
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
var2
var3
var4
var5
dvar1
dvar2
dvar3
dvar4
dvar3
WORD
WORD
WORD
WORD
WORD
DWORD
DWORD
DWORD
DWORD
DWORD
-1
0
32767
65535
-32768
0
-1
4294967295
-2147483648
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
char2
str1
str2
BYTE
BYTE
BYTE
BYTE
’g’
"g"
’ciccio’
"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
0001
0002
0003
Valore
10
20
30
40
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
mov ax, 4c00h
int 21h
.model small
.stack 100h
.data
ostr db 50 dup(’*’)
;;;;;;;;;;;;;;;;;;
; subroutine puts
puts:
.code
start:
mov ax, @data
mov ds, ax
mov dx, offset ostr
call 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
MOV
MOV
MOV
MOV
reg, reg
mem, reg
reg, mem
mem, imm
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
...
mov al,
mov al,
mov al,
byte 10h, 20h, 30h, 40h, 50h
vettore
[vettore+1]
[vettore+2]
; al = 10
; al = 20
; 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
mov si, offset
mov si, offset
mov si, offset
bvar
wvar
dvar1
dvar2
;
;
;
;
si
si
si
si
=
=
=
=
4000
4001
4003
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
mov ax, word ptr var
mov ax, byte ptr var
mov ax, word ptr [var + 2]
;
;
;
;
SBAGLIATO
ax = 5678h
ax = 78h
ax = 1234h
65 / 254
Operatore type
Restituisce la dimensione in byte di un singolo elemento di
una variabile
Per esempio:
.data
var1 byte ?
var2 word ?
var3 dword ?
; type = 1
; type = 2
; 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
vec1
vec2
vec3
str1
byte 10, 20, 30
word 30 dup(?),0,0
word 5 dup(3 dup(?))
dword 1, 2, 3, 4
byte "12345678",’\$’
;
;
;
;
;
lengthof
lengthof
lengthof
lengthof
lengthof
=
=
=
=
=
3
32
5*3
4
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
main proc
mov ax, @data
mov ds, ax
mov dx, offset istr
invoke puts
invoke getc
.stack 100h
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
.data
istr db ’Carattere M: $’
ostr db ’Carattere m: $’
.code
getc proto
putc proto
puts proto
put1310 proto
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
.code
mov ax,
mov ds,
mov si,
mov al,
inc si
mov al,
inc si
mov al,
byte 10h, 20h, 30h
@data
ax
offset vettore
[si] ; al = 10h
[si]
; al = 20h
[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
.code
mov si,
mov ax,
add si,
mov ax,
add si,
mov ax,
word 1000h, 2000h, 3000h
offset vettore
[si] ; ax = 1000h
2
[si] ; ax = 2000h
2
[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
.code
mov si,
mov ax,
add si,
mov ax,
add si,
add ax,
dword 10000h, 20000h, 30000h
offset vettore
[si] ; ax = 10000h
4
[si] ; ax = 20000h
4
[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
wvec
ptrb
ptrw
byte 10h, 20h, 30h, 40h
word 1000h, 2000h, 3000h
dword bvec
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:
mov ax, 0
mov cx, 5
L1:
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
AND
AND
AND
AND
reg,
reg,
reg,
mem,
mem,
reg
mem
imm
reg
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
OR
OR
OR
OR
reg,
reg,
reg,
mem,
mem,
reg
mem
imm
reg
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
XOR
XOR
XOR
XOR
reg,
reg,
reg,
mem,
mem,
reg
mem
imm
reg
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
0
0
1
1
y
0
1
0
1
(x XOR y)
0
1
1
0
(x XOR y) XOR y
0
0
1
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
xor
mov
xor
al,
al,
al,
al,
10110101b
0
11001100b
0
;
;
;
;
5 bit =
flag di
4 bit =
flag di
parita’
parita’
parita’
parita’
dispari
azzerato (PO)
pari
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
0 0 0 0 1 0 0 1
0 0 0 0 0 0 0 1
valore da verificare
valore di test
ZF = 0
0 0 1 0 0 1 0 0
0 0 0 0 1 0 0 1
0 0 0 0 0 0 0 0
valore da verificare
valore di test
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
dest < sorgente
dest > sorgente
dest = sorgente
ZF
0
0
1
CF
1
0
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
dest < sorgente
dest > sorgente
dest = sorgente
Flag
SF != OF
SF = OF
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
or al, 1
; ZF = 1
; ZF = 0
or al, 80h
and al, 7fh
; SF = 1
; SF = 0
stc
clc
; set carry flag
; clear carry flag
mov al, 7fh
inc al
or ax, 0
; al = +127
; al = -128
; OF = 0
OF = 1
136 / 254
Elaborazione condizionata
Operazioni sui singoli flag - Tabella di debug
Set
OV
DN
EI
NG
ZR
AC
PO
CY
Descrizione
Overflow
Direction Down
Interrupts Enabled
Sign Flag Negative
Zero
Auxiliary Carry
Odd Parity
Carry
Clear
NV
UP
DI
PL
NZ
NA
PE
NC
Descrizione
No Overflow
Direction Up
Interrupts Disabled
Sign Flag Positive
Not Zero
Not Auxiliary Carry
Even Parity
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
; jump if equal
mov ax, 5
cmp ax, 6
jl L1
; jump if less
mov ax, 5
cmp ax, 4
jg L1
; 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
Flags
ZF = 1
ZF = 0
CF = 1
CF = 0
OF = 1
OF = 0
SF = 1
SF = 0
PF = 1
jump if not parity
PF = 0
143 / 254
Elaborazione condizionata
Istruzione jcond / 6
Salti condizionati dipendenti da uguaglianze
Simbolo
je
jne
jcxz
Descrizione
jump if equal
jump if not equal
jump if cx = 0
jecxz
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
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
jna
jump if not above (uguale a jbe)
145 / 254
Elaborazione condizionata
Istruzione jcond / 8
Salti condizionati da confronti con segno
jg
jnle
jge
jnl
jl
jnge
jle
jng
jump
jump
jump
jump
jump
jump
jump
jump
if
if
if
if
if
if
if
if
greater
not less or equal (uguale a jg)
greater or equal
not less (uguale a jge)
less
not greater or equal (uguale a jl)
less or equal
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
cmp al, 80h
ja Lab
jg Lgr
;
;
;
;
7Fh = +127
80h = -128
non funziona
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
jnz Label
; verifica del bit 5
Si supponga di voler verificare lo stato dei bit 0, 1 o 4:
mov al, status
test al, 00010011b
jnz Label
; verifica dei bit 0, 1, 4
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
and
cmp
je
al, status
al, 10001100b
al, 10001100b
Label
; preserva i bit 2, 3 e 7
; verifica che siano settati
Si supponga di voler confrontare gli interi senza segno in AX e
BX e spostare il maggiore in DX
mov
cmp
jae
mov
L1:
dx, ax
ax, bx
L1
dx, bx
; se ax >= bx salta a L1
; else bx maggiore
; 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
cmp
jbe
mov
L1: cmp
jbe
mov
L2: ...
?
?
?
ax,
ax,
L1
ax,
ax,
L2
ax,
v1
v2
v2
v3
v3
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
BT
BT
BT
r/m16,
r/m32,
r/m16,
r/m32,
r16
r32
imm8
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
SHL
SHL
SHL
reg,
mem,
reg,
mem,
imm8
imm8
CL
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
shl bl, 1
; bl = 1001111b
; 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 2n
Per esempio:
mov
shl
...
mov
shl
dl, 5
dl, 1
; dl = 00000101
; dl = 00001010
5
10
dl, 10 ; dl = 00001010
dl, 2 ; dl = 00101000
10
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
shr al, 1
; al = 11010000b
; 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 2n
Per esempio:
mov
shr
...
mov
shr
dl, 32
dl, 1
; dl = 00100000
; dl = 00010000
al, 01000000b
al, 3
32
16
; al = 64
; 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
sar
...
mov
sar
al, 0f0h
al, 1
; al = 11110000b
; al = 11111000b
(-16)
(-8) CF = 0
dl, -128
dl, 3
; dl = 10000000b
; dl = 11110000b
(-128)
(-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
rol
rol
rol
...
mov
rol
al,
al,
al,
al,
40h
1
1
1
al, 26h
al, 4
;
;
;
;
al
al
al
al
=
=
=
=
01000000b
10000000b
00000001b
00000010b
CF = 0
CF = 1
CF = 0
; 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
ror al, 1
ror al, 1
; al = 00000001b
; al = 10000000b
; al = 01000000b
CF = 1
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
mov bl, 88h
rcl bl, 1
rcl bl, 1
;
;
;
;
CF
bl
bl
bl
=
=
=
=
0
10001000b
00010000b
00100001b
CF = 0
CF = 1
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
mov ah, 10h
rcr ah, 1
; CF = 1
; ah = 00010000b
; ah = 10001000b
CF = 1
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
mov
shl
shl
add
ax,
bx,
ax,
bx,
ax,
123
ax
5
2
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
AL
AX
EAX
Moltiplicatore
r/m8
r/m16
r/m32
Prodotto
AX
DX:AX
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
mov ax, var1
mul var2
; CF = 0
; var1 word 2000h
; 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
AX
DX:AX
EDX:EAX
Divisore
r/m8
r/m16
r/m32
Quoziente
AL
AX
EAX
Resto
AH
DX
EDX
175 / 254
Moltiplicazione e divisione
Istruzione DIV / 2
mov ax, 0083h
mov bl, 2
div bl
; al = 41h, ah = 01h
mov
mov
mov
div
dx, 0
ax, 8003h
cx, 100h
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
.data
dvar sdword -101
.code
mov eax, dvar
cdq
; ff9bh
; ax = ff9bh
; dx:ax = ffffff9bh
; 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
cbw
mov bl, 5
idiv bl
;
;
;
;
dividendo (bvar sbyte -48)
estensione del segno in ah
divisore
al = -9, ah = -3
mov ax, wvar
cwd
mov bx, 256
idiv bx
;
;
;
;
dividendo (wvar sword -5000)
estensione del segno in dx
divisore
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
mov
mul
mov
sub
div
mov
ax var1
bx, 5
bx
bx, var2
bx, 3
bx
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
ADC
ADC
ADC
ADC
reg,
mem,
reg,
mem,
reg,
reg
reg
mem
imm
imm
185 / 254
Moltiplicazione e divisione
Addizione e sottrazione in precisione estesa / 2
Per esempio:
mov
mov
add
adc
dl,
al,
al,
dl,
0
0ffh
0ffh
0
; al = fe
; 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
mov
sub
sbb
dx,
ax,
ax,
dx,
1
0
1
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’
add al, ’2’
aaa
or ax, 3030h
;
;
;
;
ax
ax
ax
ax
=
=
=
=
0038h
006ah
0100h
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
push
push
call
type array
lengthof array
offset array
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
valore immediato
espressione intera
nome di variabile
espressione di indirizzo
nome di registro
ADDR nome
Esempio
10, 300h, offset lista, type array
(10 * 20), count
lista, array, bvar, wvar
[bx + si], [lista + 2]
ax, bl, ebx
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
; prototipo
; invocazione
Sub PROC
...
Sub ENDP
; 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
mov ax,
L1:
add ax,
add si,
loop L1
ret
VecSUM ENDP
USES si, cx
0
[si]
4
206 / 254
Procedure avanzate
Operatore USES / 2
Esempio (somma di due vettori)
VecSum proc uses si, cx,
ptrvec: ptr word,
sizevec: word
mov si,
mov cx,
cmp cx,
je L2
mov ax,
L1: add ax,
add si,
loop L1
L2: ret
SumVec endp
ptrvec
sizevec
0
0
[si]
2
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
mov
mov
mov
int
ah,
bx,
cx,
dx,
21h
40h
1
sizeof msg
offset msg
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
Descrizione
offset filename (ASCIIZ)
CX
0
1
2
3
AX
3
4
5
Attributi file
Normal
Read only
Hidden
System
Codici di errore
Path not found
No handle available (too many files)
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
mov
mov
int
dx, offset fh
cx, 0
ah, 3ch
21h
. . .
222 / 254
Funzioni di int 21h / 3c
Apertura file con 3dh
La funzione 3dh permette di aprire un file già esistente
Registri
DX
Descrizione
offset filename (ASCIIZ)
AL
0
1
2
AX
2
3
4
5
0ch
Codice di accesso
Read
Write
Read/Write
Codici di errore
File not found
Path does not exist
No handle available (too many files)
Access denied
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
mov
mov
int
. . .
dx, offset fh
al, 1
ah, 3dh
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
CX
AX
AX
AX
offset buffer
numero di byte da leggere
numero di byte letti
Raggiunto EOF
Codici di errore
Access denied
Invalid handle or not open
0
5
6
225 / 254
Funzioni di int 21h / 3f
Lettura file con 3fh
. . .
.data
buf byte 50
. . .
mov bx,
mov ah,
mov cx,
mov dx,
int 21h
. . .
dup(’+’),"$",’13’,’10’
ax
3fh
9
offset buf
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
CX
AX
AX
AX
offset buffer
numero di byte da scrivere
numero di byte scritti
Disk full
Codici di errore
Access denied
Invalid handle or not open
0
5
6
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
mov ah, 6
mov dl, 0ffh
int 21h
jz salta
mov char, al
salta:
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
int
mov
mov
mov
mov
...
mov
mov
mov
mov
int
cmp
jne
ah, 2ah
21h
anno, cx
mese, dh
giorno, dl
giornosett, al
ah, 2bh
cx, nuovoanno
dh, nuovomese
dl, nuovogiorno
21h
al, 0
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
int
mov
mov
mov
...
mov
mov
mov
mov
int
cmp
jne
ah, 2ch
21h
ora, ch
min, cl
sec, dh
ah, 2bh
ch, new_ora
cl, new_min
dh, new_sex
21h
al, 0
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
0
1
2
3
4
Descrizione
Tastiera (standard input)
Console (standard output)
Errore
Dispositivo ausiliario
Stampante
238 / 254
Funzioni di int 21h / 14
Funzioni di I/O da file e directory
Tutte le funzioni di I/O generano, in caso di errore, un codice
restituito nel registro AX:
Codice
01
02
03
04
05
06
07
08
09
0A
0B
0C
0D
0E
0F
Descrizione
Invalid function number
File not found
Path not found
Too many open files
Access denied
Invalid handle
Memory control blocks destroyed
Insufficient memory
Invalid memory block address
Invalid environment
Invalid format
Invalid access code
Invalid data
Reserved
Invalid drive was specified
239 / 254
Funzioni di int 21h / 15
Funzioni di I/O da file e directory
Continua:
Codice
10
11
12
13
14
15
16
17
18
19
1A
1B
1C
1D
1E
1F
Descrizione
Attempt to remove current directory
Not same device
No more files
Diskette write-protected
Unknown unit
Drive not ready
Unknown command
Data error (CRC)
Bad request structure length
Seek error
Unknown media type
Sector not found
Printer out of paper
Write fault
Read fault
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
mov
mov
mov
mov
int
ah,
al,
bx,
cx,
dx,
21h
42h
0
filehandle
offsethi
offsetlo
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,
mov bx,
mov cx,
mov dx,
int 21h
jc esci
; scrittura su file o device
; console
40h
1
bytesread
offset buffer
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
; 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,
mov bx,
mov cx,
mvo dx,
int 21h
jc esci
40h
ohandle
bytesread
offset buffer
;
;
;
;
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
mov
int
mov
mov
int
dl,
ah,
21h
dl,
ah,
21h
13
2h
10
2h
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
mov
mov
mov
si,
bl,
ax,
al,
0
2
0
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
mov
int
mov
int
ah, 09h
dx, offset ni
21h
dx, offset nf
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