Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
programmazione Assembly
Prof. Orazio Gambino
A causa del modo in cui vengono sommati l'indirizzo del segmento e l'offset, un singolo indirizzo
lineare può essere mappato fino a 212 = 4096 segmenti distinti: coppie di offset. Ad esempio,
l'indirizzo lineare 08124h può avere gli indirizzi segmentati 06EFh: 1234h, 0812h: 0004h, 0000h:
8124h, ecc. (si legge segmento:offset)
prof. Orazio Gambino
I registri del del μP 8086:
segmentazione (4)
Sembra complicato. Ma non facevano prima a tentare di creare un registro MAR a 20 bit? No.
• Le operazioni relative ai dati o allo stack possono essere eseguite in diversi segmenti.
• È possibile aumentare la dimensione della memoria dei dati del codice o impilare segmenti
prof. Orazio Gambino
oltre i 64 KB assegnando più di un segmento per ogni area.
I registri del μP 8086
Registri Indice o Registri Puntatore
DATI
CODICE
EXTRA
prof. Orazio Gambino
Struttura di un programma Assembly 8086
• Lo stack segment costituisce quella zona della RAM in cui può
essere fatto il push dei dati (funzionamento LIFO, Last In First
Out)
• Il data segment contiene le dichiarazioni delle variabili
statiche (spazio di memoria allocato al momento della
compilazione)
• Il code segment contiene le istruzioni e le direttive del
programma da eseguire
• L’ extra segment viene definito dall’utente e di solito viene
usato per dati addizionali
• I tipi dei segmenti sono ottenuti associando ai registri SS, DS,
CS e ES l’indirizzo di partenza dei segmenti definiti
• Per un programma Assembly e compilato con TASM, occorre
definire
prof. Orazio Gambino il modello di memoria, lo stack ed il segmento codice
Assembly 8086: sintassi delle istruzioni
Ogni istruzione è composta in generale da:
• Permette di definire:
– il nome
– il tipo
– il contenuto delle variabili in memoria.
prof. Orazio Gambino
Direttiva .data
nome tipo espressione [, espressione] ...
• nome – etichetta del dato
• tipo – viene interpretato come lunghezza del
dato (se scalare) o di ogni elemento del dato
(se array) - i tipi più utilizzati sono:
DB riserva uno o più byte (8 bit)
DW riserva una o più word (16 bit)
DD riserva una o più doubleword (32 bit)
prof. Orazio Gambino
Direttiva .data
• espressione - contenuto iniziale del dato:
– un' espressione costante
– una stringa di caratteri (solo DB; char=byte)
– un punto di domanda (nessuna inizializzazione)
– un'espressione che fornisce un indirizzo
(solo DW e DD, near o far address)
– un'espressione DUPlicata per la quale si usa il
comando DUP per la generazione multipla di
gruppi di dati
prof. Orazio Gambino
Direttiva .data
.data
ByteVar DB 0 ; 1 byte inizializzato a 0
ByteArray DB 1,2,3,4 ; array di 4 byte
String DB '8','0','8','6' ; array di 4 caratteri
String DB '8086' ; equivale al precedente
Titolo DB 'Titolo',ODH,0AH ; ovvero 13 e 10 stringa che contiene
anche una coppia di caratteri CR/LF (Carriage Return/Line
Feed)
Zeros DB 256 dup (0) ; array di 256 byte inizializzati a 0
Tabella DB 50 dup (?); array di 50 byte non inizializzati
WordVar DW 100*50 ; scalare di una word (2 byte)
Matrix DW 1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0 ; array di 16 word
Matrix DW 4 dup (1, 3 dup (0)) ; equivale al precedente
NearPointer DW Matrix; contiene l'offset di Matrix
DoubleVar DD ? ; scalare di una double word (4 byte)
FarPointer DD Matrix; contiene l'offset e l'indirizzo del
prof. Orazio Gambino
segmento di Matrix
Direttiva .code
• Segmento per la scrittura del codice.
• Qualunque codice si scriva, deve avere lo stesso finale:
.code
start: ;etichetta
………
………
;the closing
MOV AX,4C00H ;queste 3 righe
INT 21H ;di chiusura
RET ;sono obbligatorie
end start
prof. Orazio Gambino
Struttura di un programma Assembly
8086
• La struttura di un programma Assembly 8086 è la seguente
con le direttive dell’assemblatore:
.code
Label_inizio_codice
…
..
End Label_inizio_codice
prof. Orazio Gambino
Esempio di un programma essenziale
in Assembly 8086
.model small ;seleziona il modello di memoria
.stack 100H ;definisce la dimensione dello stack
.data ;dichiarazioni di variabili ed array
.code
start: ;label di inizio codice
;the closing
MOV AX,4C00H ; ultime due righe obbligatorie
INT 21H ;interrupt 21H del S.O. MsDos
end start
prof. Orazio Gambino
Assembly 8086: tipi di istruzioni
MOV CL, BYTE_ Array[2] ;Gets the 3rd element of the BYTE_TABLE
MOV CL, BYTE_ Array + 2 ;Gets the 3rd element of the BYTE_TABLE
MOV CX, WORD_ Array[3] ;Gets the 4th element of the WORD_TABLE
MOV CX, WORD_ Array + 3 ;Gets the 4th element of the WORD_TABLE
– Copia nel registro il valore nell’array indicizzato. Da
notare due diversi tipi di sintassi entrambe valide.
.data
Message DB ‘Hi Mom!’
MessageNullT DB ‘Hi Mom!’, 0
DOSMessage DB ‘Hi Mom!’, ‘$’
call <NomeProcedura>
prof. Orazio Gambino
Subroutine: chiamata alla subroutine
• Codice che chiama la subroutine:
– Salvataggio dell’indirizzo di ritorno nello stack
(invisibile al programmatore)
– Passaggio dei parametri
• Subroutine che viene chiamata:
– Estrazione dell’indirizzo di ritorno dallo stack
(invisibile al programmatore)
– Prelevamento dei parametri
– Esecuzione del codice
– Salvataggio dei risultati nell’output
– Ritorno al normale flusso di esecuzione (ret)
prof. Orazio Gambino
Rappresentazione della chiamata a
subroutine
mov dx,offset message
call Print
mov ax,4C00h
………
Print Proc
….
ret
Print Endp
• … ma anche svantaggi.
– Il nome del registro non è autoesplicativo del suo
contenuto: l’uso del commento diventa vitale per la
comprensione del contenuto di un registro.
– Il numero dei registri è limitato: se ci vogliono molti
parametri come si fa? Si adottano i tipi di passaggi che
seguono.
prof. Orazio Gambino
Subroutine: Passaggio tramite registri
ProcReg.asm
.model small PrintChar PROC
.code
push bx ; save registers to be destroyed
push cx
Start:
xor bh,bh ; clear bh - video page 0
mov dh,4 ;row to print character on mov ah,2 ; function 2 - move cursor
mov dl,5 ;column to print character on int 10h ; row and col are already in dx
; altri due modi di scrivere
; 45 nel registro dx pop bx ; restore bx
; mov dx,0000001000000101b
; mov dx,0405h xor bh,bh ; display page - 0
mov al,254 ; ascii value of block to mov ah,9 ; write char & attrib
display
mov cx,1 ; display it once
mov bl,4 ; colour to display character
int 10h ; call bios service
Row db ?
xor bh,bh ; clear bh - video page 0
Col db ?
Colour db ? mov ah,2 ; function 2 - move cursor
Char db ? mov dh,Row
mov dl,Col
.code int 10h ; call Bios service
Start:
mov al,Char
mov Row,4 ; row to print character mov bl,Colour
mov Col,5 ; column to print character on xor bh,bh ; display page - 0
mov Char,254 ; ascii value of block to mov ah,9 ; function 09h write char & attrib
display
mov Colour,4 ; colour to display character mov cx,1 ; display it once
int 10h ; call bios service
call PrintChar ; print our character
mov ax,4C00h ; terminate program pop bx cx ax ; restore registers
int 21h
end Start
.data
vet dw 1000h,2000h,3000h,4000h
.code
start:
mov ax, vet
mov bx, vet[1]
mov cx, vet[2]
carry
mov dx, vet[3] x
ax x x x x x x x x x x x x x x x x adc bx x x x x x x x x x x x x x x x x add
add bx, dx
adc ax, cx
cx x x x x x x x x x x x x x x x x = dx x x x x x x x x x x x x x x x x =
mov ax,4C00H x x x x x x x x x x x x x x xx x x x x x x x x x x x x x x x x
int 21H
prof. Orazio Gambino
end start
Sottrazione: sub e subb
• L'istruzione sub esegue la sottrazione tra due
operandi con o senza segno e posiziona il
risultato della sottrazione nel primo operando.
• La sua sintassi è:
sub dest,source
• Il primo operando può essere un registro o
una locazione di memoria, il secondo può
essere un registro, una locazione di memoria o
un valore immediato
• dest = dest - source
prof. Orazio Gambino
Sottrazione: sub e subb
• i due operandi devono avere la stessa
dimensione.
• Inoltre i due operandi NON possono essere
entrambi locazioni di memoria.
• In base al risultato vengono settati i seguenti
flag:
– ZF : ha il valore 1 se il risultato è zero;
– SF : ha il valore 1 se il risultato è negativo;
– CF : ha il valore 1 se si è verificato un riporto (carry)
sul bit più significativo.
; ***sottrazione a 32 bit***
.data
vet dw 1000h,2000h,3000h,4000h
.code
start:
mov ax, vet
mov bx, vet[1]
mov cx, vet[2]
mov dx, vet[3]
mov ax,4C00H
int 21H
end start
.data
wvar dw 5000
.code
start:
neg wvar
mov ax, wvar ; dividendo (wvar sword -5000)
cwd ; estensione del segno in dx
;The CWD (convert word to doubleword) instruction
;extends the sign bit of AX into the DX register
mov bx, 256 ; divisore
idiv bx ; quoziente ax = -19, resto dx = -136
mov ax,4C00H
int 21H
end start
vet_h db 1,2,3,4
vet_v db 5,6,7,8 mov ax,4C00H
risultato db 00h,00h,'$' int 21H
.code
start: print proc
mov ax,@data ; Initialize DS
mov bl, 10 ; Base 10 -> divisor
mov ds,ax ; Initialize DS
mov ax,0001h ;lea di, DEC_END
mul vet_h mov di,offset risultato+2
mul vet_v ; ax=1*vet_h[0]*vet_v[0] L1:
add risultato,al dec di ; fill the decimal-string
in reverse order
mov ax,0001h
xor ah, ah ; Clear AH for division
mul vet_h[1]
mul vet_v[1] ; div bl ; AL = AX / BL Remainder AH
ax=1*vet_h[1]*vet_v[1] or ah, 30h ; Convert AH to ASCII
add risultato,al mov BYTE PTR [di], ah ;
Save AH in the decimal-string
mov ax,0001h test al, al ; AL == 0?
mul vet_h[2]
jnz L1 ; No: once more
mul vet_v[2] ;
ax=1*vet_h[2]*vet_v[2] mov ah, 09h ; WRITE STRING TO
add risultato,al STANDARD OUTPUT
mov dx, di ; Result of al2dec
mov ax,0001h int 21h
mul vet_h[3] ret ; Return DS:DI Pointer to the
mul vet_v[3] ; decimal-string
ax=1*vet_h[3]*vet_v[3]
prof. Orazio Gambino
print endp
add risultato,al
ProdLoop.asm
.model small print proc
.stack mov bl, 10 ; Base 10 -> divisor
.data mov di,offset risultato+2
vet_h db 1,2,3,4 L1:
vet_v db 5,6,7,8 dec di ; fill the decimal-string in
risultato db 00h,00h,'$' ; reverse order
xor ah, ah ; Clear AH for division
.code div bl ; AL = AX / BL Remainder AH
start: or ah, 30h ; Convert AH to ASCII
mov ax,@data ; Initialize DS mov BYTE PTR [di], ah ;
mov ds,ax ; Initialize DS Save AH in the decimal-string
mov bx,0000h test al, al ; AL == 0?
mov cx,04h jnz L1 ; No: once more
mov ah, 09h
Ciclo: ; WRITE STRING TO STANDARD OUTPUT
mov ax,0001h mov dx, di ; Result saved into dx
mul vet_h[bx] int 21h
mul vet_v[bx] ; ax=1*vet_h[bx]*vet_v[bx] ret ng
add risultato,al
print endp
inc bx
loop Ciclo
end start
mov al,[risultato]
call print
prof. Orazio Gambino
strinv.asm
.model small L2:
.stack 100h pop ax
.data mov str2[si], al
str1 db "ciao","$" inc si
str2 db 5 dup(0) loop L2
.code mov al, "$"
start: inc si
mov ax, @data mov str2[si], al
mov ds, ax mov dx, offset str2
mov si, 0 mov ah, 9h
mov cx, 5 int 21h
dec cx ;the closing
L1: MOV AX,4C00H
mov al, str1[si] INT 21H
push ax end start
inc si
loop L1
mov cx, 5
dec cx
mov si, 0
prof. Orazio Gambino
Istruzioni di salto - Jmp
• Provoca un trasferimento incondizionato ad una
locazione interna al segmento di codice
• la locazione destinazione deve essere identicata
mediante un'etichetta
• la sintassi : jmp <etichetta>
• Esempio:
top:
...
...
jmp top ; attenzione si genera un loop infinito
- JE : salta se Operando1=Operando2
- JNE : salta se Operando1<>Operando2
.code
START:
MOV AX,@data ;Data viene trasferito nel registro AX
MOV DS,AX ;il registro AX viene trasferito nel reg. di segmento DS
MOV bl,01H
CMP bl,00H
JE EQUAL
EQUAL:
MOV DX,OFFSET msg2
MOV AH,09H ;richiesta di stampa: 09H nel registro alto AH
INT 21H ;interrupt per la stampa
EXIT:
MOV AX,4C00H
INT 21H
END START
prof. Orazio Gambino
Flags e salti condizionati
• Ecco alcuni dei flag coinvolti nelle istruzioni
di salto condizionato:
– CF(Carry Flag, flag di Riporto): viene forzata a 1 se
una somma/sottrazione ha prodotto riporto/prestito;
influenza i seguenti salti condizionati: JC (salta
se CF=1), JNC (salta se CF=0), JB (salta
se CF=1), JAE (salta se CF=0), JA (salta
se CF=0 e ZF=0), JBE (salta se CF=1 o ZF=1).
– PF(Parity Flag, flag di Parità): viene forzata a 1 se il
risultato di un'operazione contiene un numero pari
di 1
– AF(Auxiliary Flag, flag di Riporto Ausiliario): viene
forzata a 1 se un'operazione ha prodotto riporto tra il
primo (bit0÷bit3) e il secondo nibble (bit4÷bit7).
prof. Orazio Gambino
Flags e salti condizionati
– ZF(Zero Flag, flag di Zero): viene forzata a 1 se
un'operazione ha dato risultato nullo; influenza i
seguenti salti condizionati: JZ (salta se ZF=1), JNZ (salta
se ZF=0), JE (salta se ZF=1), JNE (salta
se ZF=0), JG (salta se ZF=0 e SF=OF), JLE (salta
se ZF=1 o SF<>OF), JA (salta se ZF=0 e CF=0), JBE (salta
se ZF=1 o CF=1).
– SF(Sign Flag, flag di Segno): viene forzata al valore
corrente del bit più significativo del risultato di
un'operazione; come è noto nei numeri con
segno 0 significa positivo e 1 significa negativo;
influenza i seguenti salti condizionati: JS (salta
se SF=1), JNS (salta se SF=0), JG (salta
se SF=OF e ZF=0), JGE (salta se SF=OF), JL (salta
se SF<>OF), JLE (salta se SF<>OF o ZF=1).
prof. Orazio Gambino
Flags e salti condizionati
– OF(Overflow Flag, flag di Overflow): viene forzata
a 1 se un'operazione ha prodotto trabocco, cioè ha
superato il numero massimo per il registro coinvolto
(256=100H a 8bit, 65536=10000H a 16bit, ecc);
influenza i seguenti salti condizionati: JO (salta
se OF=1), JNO (salta se OF=0).
.code
start:
mov ax,@data ; Initialize DS
mov ds,ax ; Initialize DS
xor si,si
ciclo:
mov bl,message[si]
cmp bl,'$' ; verifica che la stringa sia finita
je exit
inc si
cmp bl,'w' ; sostituiamo la w con W
jne ciclo
mov message[si-1],'W'
exit:
mov dx,offset message
mov ah,9 ; DOS Function call to print a message
int 21h
prof.
endOrazio Gambino
start
copia$.asm
.model small exit:
.data mov ah,9 ; DOS
str1 db “ciao","$" Function call to
str2 db ? print a message
mov dx,offset str2
.code int 21h