|
[La logica di presentazione degli argomenti
di questo modulo si ispira a Linguaggio Assembly per pc IBM
di Peter Norton]
Istruzioni di salto condizionato - istruzione cmp
Le istruzioni di salto condizionato possono
servire a controllare lo stato dei flag [vedi modulo
precedente] ; ad esempio: JC [salto se il riporto e' 1] e'
un'istruzione che si realizza nel caso, in seguito ad un'operazione
aritmetica, il CF fosse stato impostato. JC salta ad una etichetta
se FC=1, JC salta ad un'altra etichetta se FC=0 mediante l'istruzione
di salto condizionato JNC. In questo caso il normale corso del
programma si interrompere per saltare ad altre istruzioni scritte
successivamente ad etichetta, e solo dopo aver eseguito tali istruzioni,
nel caso, ritornare al programma principale.
Vedremo i vari salti condizionati man mano che ci si presenti
l'esigenza di utilizzarli.
Finora abbiamo visto come stampare un carattere ascii e come rilevare,
stampandola, la codifica binaria di un numero esadecimale.
Ora quello che ci proponiamo di fare, e' stampare un numero esadecimale.
Per fare questo ci serviremo dei salti condizionati. La metodologia
pe realizzare questa operazione non e' troppo differente da quella
utilizzata per la stampa di 1 e 0 che abbiamo visto a pproposito
della verifica di stato del flag CF.
Per prima cosa osserviamo che essendo numeri esadecimali dovremo
stampare insiemi di caratteri alfanumerici, ovvero composti al
contempo da cifre e da lettere. Osserviamo allora una tabella
dei codici esadecimali Codici
dei caratteri ascii, e
ricordiamo che i caratteri esadecimali hanno questo tipo di progerssione:
0123456789ABCDEF.
Possiamo osservare che i caratteri ascii che vanno da 0 a 9 corrispondono
ai numeri esadecimali che vanno dal 30 al 39, mentre i caratteri
ascii da A a F corrispondono agli esadecimali che vanno dal 41
al 46.
facciamo subito un esempio; i caratteri ascii che compongono la
cifra esadecimale 2c5f tradotti in esadecimale corrispondono a
32-43-35-46. Il nostro programma, quindi, dovra' rilevare ogni
singola cifra del numero esadecimale [ogni carattere ascii] e
trovare un metodo per trasformarlo in umero esadecimale.
Abbiamo detto trovare un metodo intendendo dire trovare una strategia
che renda il programma adatto alla traduzione di un qualsiasi
numero con un meccanismo il piu' economico possibile. Potremo
infatti realizzare una serie di comparazioni [1=prima cifra?;
2=seconda cifra?... n=n cifra?] che una volta individuato il carattere
ascii traduca tale carattere nella cifra corrispondente esadecimale.
Tuttavia questa procedura sarebbe troppo lunga.
Ecco un metodo meno meccanico che evita la scrittura di codice
troppo lungo e noioso:
|
mov
ah,02
|
;
|
| mov
dl,bl |
;
fai una copia di bl e rendi il numero
stampabile [ah=02 e int 21] |
| add dl,30 |
;
addiziona dl a 30 per trasformarlo in un carattere esadecimale |
| cmp dl,3a |
;
compara dl a 3a, ovvero alla cifra successiva al numero esadecimale
che |
|
;
rappresenta il carattere ascii 9 |
| jl etichetta |
;
se inferiore a 3a stampalo [etichetta = istruzione INT 21]
altrimenti... [segue |
|
;
l'istruzione successiva] |
| add dl,
07 |
;
addiziona
7 a dl per raggiuingere le cifre esadecimali corrispondenti
ai caratteri ascii
|
|
;
superiori a 40
e
poi stampalo [grazie alle istruzioni successive]
|
| int 21 |
; |
| int 20 |
; |
Inseriamo Fh nel registro bl. A quanto
sostiene il programma dovremmo ottenere non piu' l'ascii F nella
stampa [ovvero ¤ se avessimo utilizzato la procedura descritta
nel modulo II] ma il suo corrispettivo
in esadecimale ovvero f.
Una semplice prova ce lo potra' confermare:
|
mov ah,02
mov dl,f
int 21
int 20
|
Questo programma restituisce il valore
¤.
Torniamo invece al programma precedente e vediamo quali elementi
nuovi esso incorpora: l'struzione cmp e il salto condizionato
jl.
L'istruzione cmp (compare) opera una sottrazione tra i due operandi
[in questo caso tra il registro DL e 30h]. La sottrazione compiuta
da cmp non prevede, come nel caso di sub, che il risultato finisca
nel registro di destinazione, quindi DL resta inalterato. A verificare
l'ordine di grandezza dei due operandi c'e' l'istruzione di salto
condizionato jl [salto se minore]. Se DL e' < di 3a si realizza
l'istruzione di salto e il controllo del programma si trasferisce
su etichetta. Se DL e' > di 3a allora l'istruzione di salto
non verra' presa in considerazione e il programma continuera'
dall'istruzione immediatamente successiva a jl.
Il nostro programma lavora su singole cifre esadecimali [abbiamo
infatti considerato l'esempio di f]. Se volessimo lavorare su
piu' cifre esadecimali dovremmo apportare delle modifiche al programma.
Istruzioni shr - and
Il problema
e' di questo tipo: abbiamo visto che per stampare una cifra dobbiamo
far si che il nostro registro DL contenga una sola cifra per volta.
Se inserissimo 5Fh in DL otterremo sempre f, ovvero il programma
non prenderebbe in considerazione la cifra esadecimale 5.
Per stampare la cifra esadecimale 5h dobbiamo far ruotare tale
cifra alla sua destra cosi' da andare a prendere il posto della
cifra esadecimale Fh.
Abbiamo visto precedentemente una istruzione simile: rcl. ora
vedremo l'istruzione shr con cui e' possibile ruotare i 4 bit
superiori del nostro byte verso destra inserendo, come per rcl,
degli zeri, questa volta a sinistra. Per segnalare a shr quanti
bit vogliamo spostare utilizziamo il contatore CL: nel nostro
caso, esso va impostato a 4.
Ecco il nostro programma modificato [in
grassetto le modifiche rispetto alla versione precedente]:
|
mov
ah,02
|
;
|
| mov
dl,bl |
;
fai una copia di bl e rendi il numero
stampabile [ah=02 e int 21] |
| mov cl,04 |
;
muovi in CL, 4h per una rotazione di 4 bit |
| shr dl,cl |
;
ruota, quindi, a destra DL di 4 bit [sposta la seconda cifra
a dstra] |
| add dl,30 |
;
addiziona dl a 30 per trasformarlo in un carattere esadecimale |
| cmp dl,3a |
;
compara dl a 3a, ovvero alla cifra successiva al numero esadecimale
che |
| |
;
rappresenta il carattere ascii 9 |
| jl etichetta |
;
se inferiore a 3a stampalo [etichetta = istruzione INT 21]
altrimenti... [segue
|
| |
;
l'istruzione successiva]
|
| add dl, 07 |
;
addiziona
7 a dl per raggiuingere le cifre esadecimali corrispondenti
ai caratteri ascii |
| |
;
superiori a 40
e
poi stampalo [grazie alle istruzioni successive]
|
| int 21 |
; |
| int 20 |
; |
Inserendo 5F in BL adesso otterremmo la
stampa di 5. Cio' e' giusto perche' se vogliamo l'esadecimale
5F dobbiamo prima stampare il 5 e poi la F, ovvero la prima operazione
da compiere e' quella di spostare il 5 a destra e poi quella di
stampare la F.
Prima di dare la versione definitiva del programma vediamo un'altra
istruzione: and.
And e' un'istruzione che potremmo definire logica in quanto appartenente
alle condizioni logiche and, or, not, eccetera. Soffermiamoci
su and.
La cosiddetta messa in and di due numeri equivale a:
|
A
|
B
|
risultato
|
|
0
|
0
|
0
|
|
0
|
1
|
0
|
|
1
|
0
|
0
|
|
1
|
1
|
1
|
Cio' equivale a dire che quando due numeri
sono messi in and il risultato e' vero [1] solo se entrambi gli
operandi sono veri [1]. Ad esempio, la messa in and di 0100 e di
1100 = 0100. Sfruttando questo principio, possiamo realizzare procedere
all'isolamento di un semibyte. Nel nostro esempio 5F equivale al
numero binario 001011111b se lo mettiamo in and con il numero 00001111b
quello che otterremo e' la cancellazione di 5 lasciando inalterato
la F [questo vale per qualunque numero binario a due cifre]: 001011111b
and 00001111b = 00001111b.
Ecco allora come procederemo:
|
mov
ah,02
|
;
|
| mov
dl,bl |
;
fai una copia di bl e rendi il numero
stampabile [ah=02 e int 21] |
| mov cl,04 |
;
muovi in CL, 4h per una rotazione di 4 bit |
| shr dl,cl |
;
ruota, quindi, a destra DL di 4 bit [sposta la seconda cifra
a dstra] |
| add dl,30 |
;
addiziona dl a 30 per trasformarlo in un carattere esadecimale |
| cmp dl,3a |
;
compara dl a 3a, ovvero alla cifra successiva al numero esadecimale
che |
| |
;
rappresenta il carattere ascii 9 |
| jl etichetta |
;
se inferiore a 3a stampalo [etichetta = la prima istruzione
INT 21] altrimenti...
|
| |
;
segue l'istruzione successiva]
|
| add dl, 07 |
;
addiziona
7 a dl per raggiuingere le cifre esadecimali corrispondenti
ai caratteri ascii |
| |
;
superiori a 40
e
poi stampalo [grazie alle istruzioni successive]
|
| int 21 |
;
stampa il primo numero |
| mov dl,
bl |
;
muovi nuovamente DL [nel nostro caso 5Fh] in DL |
| and dl,
0Fh |
;
isola la seconda cifra a destra nel nostro caso Fh con la
procedura di messa in and |
| add dl,30 |
;
addiziona 30h alla seconda cifra |
| cmp dl,3a |
;
compara il risultato ottenuto con 3a [vedi sopra] |
| jl etichetta |
;
se inferiore a 3a stampalo [etichetta = la seconda istruzione
INT 21] altrimenti... |
| add dl,
07 |
;
vedi sopra |
| int 21 |
; |
| int 20 |
; |
Ora il risultato di questo programma e' la stampa esadecimele delle
due cifre inserite all'interno del registro BL. Si noti come e'
divenuta chiara l'operazione mov DL, BL: non abbiamo operato direttamente
su BL per non compromettere definitivamente la cifra originaria
e poterla riutilizzare ogni volta lo riteniamo necessario. |