|
[Da questo momento i moduli seguiranno,
revisionadolo e aggiungendo i commenti estesi, il progetto del
testo Linguaggio Assembly per pc IBM di Peter Norton e
John Socha per la costruzione di un programma per la visualizzazione
e l'editor del contenuto dei settori dei dischi]
Output esadecimale
Quella che segue e' la prima procedura
creata per il programma DSKPATCH proposto dal testo Linguaggio
Assembly per pc IBM di Peter Norton e John Socha per la lettura
e l'editing dei settori di un disco.
Il primo passo proposto dal testo prevede il perfezionamento della
procedura di output dei caratteri esadecimali letti.
| code_seg |
|
segment |
;
nome del segmento di codice |
|
assume |
cs:code_seg |
;
indicazione del nome del segmento di codice |
| |
org 100h |
|
;
inizio alla locazione di memoria 100 |
| |
|
|
|
| |
|
|
|
| |
|
|
|
| |
public
test_write_hex
|
|
;
procedura di test per provare le procedure |
| |
|
|
;
che seguono |
| |
|
|
|
| test_write_hex |
proc |
near |
|
| |
mov
dl, 3fh |
|
;
numero di prova |
| |
call
write_hex |
|
;
chiama la procedura write_hex |
| |
int 20h |
|
|
| test_write_hex |
endp |
|
|
| |
|
|
|
| |
|
|
|
| |
|
|
|
| |
public
write_hex
|
|
;
procedura di isolamento delle due cifre in DL: |
| |
|
|
;
prima la cifra di sinistra poi quella di destra |
| |
|
|
|
| write_hex
|
proc |
near |
|
| |
mov
dh, dl |
|
;
muovi DL in DH per avere una copia di DL |
| |
|
|
;
non trattata |
| |
mov
cx, 4 |
|
;
carica il contatore CX |
| |
shr
dl, cl |
|
;
slitta il contenuto di DL a destra per il valore |
| |
|
|
;
decimale contenuto nel registro CL [0004] |
| |
|
|
;
nel nostro caso -> 03h in modo da isolare la |
| |
|
|
;
prima cifra esadecimale del numero 3fh in DL |
| |
call
write_hex_digit |
|
;
richiama la procedura di controllo/conversione |
| |
|
|
;
lettere/numeri |
| |
mov
dl, dh |
|
;
muovi la copia di DL contenuta in DH in DL |
| |
and
dl, 0fh |
|
;
azzera la prima cifra con la messa in and |
| |
|
|
;
00111111 and 00001111 = 00001111 ovvero 0Fh |
| |
|
|
;
per isolare la seconda cifra |
| |
call
write_hex_digit |
|
;
vai alla procedura di conversione lettere/numeri |
|
|
ret |
|
;
ritorna alla chiamata test_write_hex
|
| |
|
|
;
e fine [int 20h] |
| write_hex
|
endp |
|
|
| |
|
|
|
| |
|
|
|
| |
|
|
|
|
public
write_hex_digit |
|
;
procedura di controllo per cifre esadecimali da |
| |
|
|
;
convertire in numeri [< Ah] o lettere [> Ah] |
|
|
|
|
| write_hex_digit |
proc |
near |
|
|
push
dx |
|
;
metti il contenuto di DX nello stack cosi' da |
| |
|
|
;
salvare il contenuto originario di DL nel |
| |
|
|
;
nostro caso 3Fh |
|
cmp
dl, 10 |
|
;
compara DL al decimale 10 che corrisponde |
| |
|
|
;
all'esadecimale A per determinare se |
| |
|
|
;
trasformarlo in lettera o numero |
| |
jae
hex_letter |
|
;
se superiore o uguale trasforma in lettera |
| |
|
|
;
saltando ad hex_letter |
| |
add
dl, "0" |
|
;
altrimenti e' un numero, quindi addiziona "0" per |
| |
|
|
;
trasformarlo in 3 decimale e... |
| |
jmp
short write_digit |
|
;
vai alla chiamata di stampa write_digit per |
|
|
|
;
procedura di stampa write_char |
| hex_letter: |
|
|
;
questa entrata e' per la trasformazione |
| |
|
|
;
in lettera della cifra hex |
|
add
dl, "A" -10 |
|
;
addiziona cifra [> di A ] ad Ah e sottrai 10 dec |
| |
|
|
;
nel nostro caso [F]: Fh + Ah = 19h. 19h e' pari a |
| |
|
|
;
25d [decimale] - 10d = 15d pari a Fh |
| write_digit: |
|
|
;
questa entrata e' per l'invio alla |
| |
|
|
;
procedura di stampa |
| |
call
write_char |
|
;
vai a stampare cifra inviata |
| |
pop
dx |
|
;
recupera il valore originario di DX e... |
| |
ret |
|
;
ritorna alla chiamata call write_hex_digit |
| write_hex_digit |
endp |
|
|
| |
|
|
|
| |
|
|
|
| |
|
|
|
| |
public
write_char |
|
;
procedura di stampa |
| |
|
|
|
| write_char |
proc |
near |
|
| |
mov
ah, 2h |
|
|
| |
int
21h |
|
|
| |
ret |
|
;
ritorna a call write_char |
| write_char |
endp |
|
|
| code_seg |
ends |
|
|
| |
end |
test_write_hex |
|
|
|
|
|
Le tre procedure [esclusa quella test]
si occupano di:
-
write_hex si occupa di isolare le singole
cifre esadecimali mediante un shr e un and;
- write_hex_digit
si occupa di controllare le cifre inviate da write_hex
e convertile in numeri e lettere a seconda che siano > o <
di Ah;
- write_char si
occupa di stampare una dopo l'altra le cifre inviate da write_hex_digit.
Le chiamate alle procedure funzionano in questo modo:
test_write_hex
chiama write_hex.
Una volta isolata
la prima cifra write_hex chiama write_hex_digit per il controllo.
La procedura write_hex_digit per prima cosa salva nello stack
DX che ci servira' integro al ritorno a
write_hex
per l'isolamento della seconda cifra. Cosi' facendo, write_hex_digit
puo' utilizzare il registro DL per la somma di "0" e
di "A" -10 senza perdere il numero hex di prova. Isolato
il primo numero e convertito in lettera o in numero, write_hex_digit
chiama write_char per la stampa
del numero ottenuto dalla conversione. La procedura write_char
torna a
write_hex_digit, preleva il numero
test originario dallo stack e torna a write_hex
per l'isolamento della seconda cifra. Questa subira' lo stesso
trattamento della prima ma quando infine
write_hex_digit
tornera' a write_hex
il ret di quest'ultima procedura rimandera' a
test_write_hex
dove sotto la call troveremo l'int 20h per restituire
i comandi a dos e il programma terminera'.
Output decimale
Ripartiamo dal programma appena visto per aggiungere una nuova
procedura per la scrittura di un numero in notazione esadecimale.
La nuova procedura deve essere inserita al di sotto della procedura
di test.
Cambia la procedura di controllo che diventa test_decimal,
viene introdotta la nuova procedura write_decimal
al posto di test_write_hex
e viene eliminta a la procedura
write_hex.
Ora la procedura principale ha il nome di test_decimal
quindi l'end diventa end test_decimal.
| code_seg |
|
segment |
;
nome del segmento di codice |
|
assume |
cs:code_seg |
;
indicazione del nome del segmento di codice |
| |
org 100h |
|
;
inizio alla locazione di memoria 100 |
| |
|
|
|
| |
|
|
|
| |
|
|
|
| |
public
test_decimal
|
|
;
procedura di test per provare le procedure |
| |
|
|
;
che seguono |
| |
|
|
|
| test_decimal |
proc |
near |
|
| |
mov
dx, 12345 |
|
;
numero di prova |
| |
call
write_decimal |
|
;
chiama la procedura write_decimal |
| |
int 20h |
|
|
| test_decimal |
endp |
|
|
| |
|
|
|
| |
|
|
|
| |
|
|
|
| |
public write_decimal |
|
|
| |
|
|
|
| |
|
|
|
| write_decimal |
proc |
near |
|
|
mov ax,
dx |
|
;
copia di DX perche' l'istruzione div [dividi] |
| |
|
|
;
opera sul registro AX |
| |
mov si,10 |
|
;
muove nel registro SI il numero 10 |
|
|
|
;
sfruttera' la correlazione div, AX, [SI], DX |
| |
|
|
;
al posto di SI per la divisionepoteva usare altri |
| |
|
|
;
registri d'uso generale non impegnati. |
|
xor cx,
cx |
|
;
azzera il contenuto del registro CX per usarlo |
| |
|
|
;
come contatore per i numeri inviati allo stack |
| non_zero: |
|
|
|
|
xor dx,dx |
|
;
azzera il contenuto di DX per ricevere il resto |
| |
|
|
;
della divisione |
|
div si |
|
;
divide il contenuto di AX per il numero |
| |
|
|
;
contenuto nel registro SI |
|
push dx |
|
;
inserisci resto in DX nello stack |
|
inc cx |
|
;
incrementa di 1 il contatore CX per i loop finali |
|
or ax,ax |
|
;
verifica AX se il numero e' stato diviso |
| |
|
|
;
completamente |
|
jne non_zero |
|
;
se diverso vai a non_zero per ripetere ulteriori |
| |
|
|
;
divisioni, se uguale... |
| write_digit_loop: |
|
|
|
| |
pop dx |
|
;
estrai un "numero resto" dallo stack e... |
|
call write_hex_digit |
|
;
vai alla procedura di controllo e poi stampalo |
| |
loop write_digit_loop |
|
;
esegui i loop per CX numero di volte |
|
|
|
;
decrementa il contatore CX e |
| |
|
|
;
vai ad estrarre un nuovo "numero resto" |
| |
|
|
;
all'istruzione pop dx del loop write_digit_loop |
| end_decimal: |
|
|
|
|
ret |
|
;
torna a test_decimal e fine |
| write_decimal |
endp |
|
|
| |
|
|
|
| |
|
|
|
| |
|
|
|
|
public
write_hex_digit |
|
;
procedura di controllo per cifre esadecimali da |
| |
|
|
;
convertire in numeri [< Ah] o lettere [> Ah] |
|
|
|
|
| write_hex_digit |
proc |
near |
|
|
push
dx |
|
;
metti il contenuto di DX nello stack cosi' da |
|
cmp
dl, 10 |
|
;
compara DL al decimale 10 che corrisponde |
| |
|
|
;
all'esadecimale A per determinare se |
| |
|
|
;
trasformarlo in lettera o numero |
| |
jae
hex_letter |
|
;
se superiore o uguale trasforma in lettera |
| |
|
|
;
saltando ad hex_letter |
| |
add
dl, "0" |
|
;
altrimenti e' un numero, quindi addiziona "0" |
| |
jmp
short write_digit |
|
;
vai alla chiamata di stampa write_digit per |
|
|
|
;
procedura di stampa write_char |
| hex_letter: |
|
|
;
questa entrata e' per la trasformazione |
| |
|
|
;
in lettera della cifra hex |
|
add
dl, "A" -10 |
|
;
addiziona cifra [> di A ] ad Ah e sottrai 10 dec |
| write_digit: |
|
|
;
questa entrata e' per l'invio alla |
| |
|
|
;
procedura di stampa |
| |
call
write_char |
|
;
vai a stampare cifra inviata |
| |
pop
dx |
|
;
recupera il valore originario di DX e... |
| |
ret |
|
;
ritorna alla call write_decimal |
| write_hex_digit |
endp |
|
|
| |
|
|
|
| |
|
|
|
| |
|
|
|
| |
public
write_char |
|
;
procedura di stampa |
| |
|
|
|
| write_char |
proc |
near |
|
| |
mov
ah, 2h |
|
|
| |
int
21h |
|
|
| |
ret |
|
;
ritorna a call write_char |
| write_char |
endp |
|
|
| code_seg |
ends |
|
|
| |
end |
test_decimal |
|
|
|
|
|
Puoi scaricare deci.zip,
la versione asm del programma appena scritto.
Le istruzioni nuove utilizzate in questo programma sono:
- XOR, ovvero or esclusivo e' una
operazione logica che funziona secondo questa regola:
|
A
|
B
|
risultato
|
|
0
|
0
|
0
|
|
0
|
1
|
1
|
|
1
|
0
|
1
|
|
1
|
1
|
0
|
il risultato e' vero solo se un solo bit
e' vero, quindi un numero messo in xor con se stesso produce sempre
bit non veri 00000000.
- Div, l'istruzione per dividere
il cui funzionamento e' stato illustrato nei commenti al programma;
in sintesi:
operando sorgente ad un byte AX/sorgente: AH = quoziente, AL =
resto. Operando sorgente una parola [16 bit] AX/sorgente: AX =
quoziente, DX = resto.
- OR e' un'operazione logica che
funziona secondo questa regola:
|
A
|
B
|
risultato
|
|
0
|
0
|
0
|
|
0
|
1
|
1
|
|
1
|
0
|
1
|
|
1
|
1
|
1
|
il risultato e' vero se solo un bit e'
0 o se sono tutti e due veri. Un numero messo in or con se stesso
restituisce lo stesso numero. Nel nostro caso se il numero e'
stato completamente diviso 00000000 messo in relazione con se
stesso 00000000 restituisce 00000000 e quindi sapremo che il numero
e' stato completamente diviso.
|