Assembly IV

[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.
torna a modulo III  
 
 

Assembly modulo IV operazioni con bit e byte.