Corso ASM n.1 Corso ASM n.2 Le istruzioni JMP
Particelle, piccole parti di quel teatrino scuola che ciascun insegnante è chiamato a recitare, talvolta a soggetto, talvolta replicandole come i vecchi cantastorie. Particelle evoca anche gli enormi sconvolgimenti che possono essere provocati da frammenti di materia opportunamente manipolati. Noi ci accontentiamo del significato letterale: piccole parti. Proprio così, le istruzioni JMP e non l'istruzione JMP, perchè dietro l'espressione mnemonica JMP, usata dall'assembler, si celano in effetti ben tre tipi di JMP che chiameremo: short, long, far.
I primi due tipi (short e long) agiscono in intorni di memoria limitati, e per questo sono detti anche NEAR. Il tipo short agisce in un intorno di +/- 128 byte, ossia è in grado di raggiungere locazioni di memoria che distano non più di 128 byte dall'istruzione stessa. Il tipo long agisce all'interno di un segmento (64 Kb), ossia è in grado di raggiungere qualsiasi locazione di memoria purchè all'interno dello stesso segmento di appartenenza.
I due tipi NEAR sono anche chiamati relativi perchè calcolano la distanza della locazione da raggiungere con riferimento a se stessi; pertanto sono anche autorilocabili.
L'ultimo tipo (far) è in grado di raggiungere qualunque locazione di memoria all'interno del MegaByte indirizzabile da un 8086. E' anche chiamato assoluto perchè utilizza, all'interno del suo codice, l'indirizzo completo della locazione da raggiungere; pertanto non è una istruzione autorilocabile.
La tabella seguente riassume ed esemplifica alcune delle caratteristiche principali delle istruzioni JMP.

MNEMOTIPOOPCODEBYTEESEMPICODIFICACOMMENTI
JMPshortEB ..23000 JMP 3020EB 1ESalto Relativo in avanti
    3000 JMP 2FE0EB DESalto Relativo all'indietro
JMPlongE9 .. ..33000 JMP 4000E9 FD 0FSalto Relativo in avanti
    3000 JMP 2000E9 FD EFSalto Relativo all'indietro
JMPfarEA .. .. .. ..53000 JMP F030:105BEA 5B 10 30 F0Salto Assoluto

Un elemento si dice bistabile quando può assumere, nel tempo, 2 soli stati stabili; ad esempio il normale interruttore della luce permane in uno dei suoi due stati possibili (acceso / spento) finchè una causa esterna (l'uomo) non ne commuta lo stato.
          L'attuale tecnologia costruttiva utilizza come componenti di base per le memorie dei dispositivi bistabili caratterizzati dal fatto di potere assumere 2 soli stati, chiamati convenzionalmente 1 e 0. Questi elementi bistabili consentono soltanto la memorizzazione di fatti elementari (Si-No, Acceso-Spento, Vero-Falso, 1-0, Bianco-Nero, Testa-Croce).
          Associando però tra loro più elementi bistabili è possibile realizzare degli insiemi di bistabili e far aumentare rapidamente la capacità di memorizzazione. E` facile dimostrare, con il calcolo combinatorio, che il numero di informazioni NI che un insieme di bistabili può rappresentare è dato da
NI = 2n
dove n è il numero degli elementi bistabili dell'insieme; si tratta delle disposizioni con ripetizione di 2 oggetti su n posti.
NI = 21 = 2      0      1       
NI = 22 = 4    00    01    10    11    
NI = 23 = 8  000  001  010  011  100  101  110  111
NI = 24 = 1600000001001000110100010101100111
10001001101010111100110111101111

A sinistra il calcolo del numero di informazioni, a destra lo sviluppo delle possibili configurazioni di bit. Come si può notare, NI cresce rapidamente con n, e già per n=10 si ottiene NI=1024. Tra l'altro il valore 1024 gioca, nella terminologia dei computer, un ruolo simile al numero 1000 nella terminologia scientifica, come, infatti si dice 1 Kilometro (Km) per indicare 1000 metri, così si dirà 1 Kilobit (Kbit) per indicare 1024 bit o 1 Kilobyte (Kbyte) per indicare 1024 byte o 1 Kiloword (Kword) per indicare 1024 word.

          Il fatto che il computer sia costituito internamente, in prevalenza, con elementi bistabili determina la scelta di un sistema di numerazione in base 2, scelta che se da una parte complica, e non poco, il dialogo con l'utente, dall'altra consente di avere una rappresentazione delle informazioni conforme al modo con cui esse sono mantenute all'interno della macchina.

          Alcuni insiemi di bistabili sono da considerarsi notevoli perchè hanno assunto un ruolo particolarmente importante nella progettazione e nell'uso dei computer, i motivi sono diversi e legati spesso alla scelta del sistema di numerazione in base 2, non a caso molti degli insiemi notevoli di bistabili sono multipli l'uno dell'altro.

BIT    E' caratterizzato da  NI = 21 = 2  informazioni. Rappresenta l'informazione più piccola presente all'interno del computer ed è costituita da una unità dati chiamata bit (dalla contrazione di BInary digiT = cifra binaria). Ciò discende direttamente dall'impiego dei dispositivi bistabili. In realtà il bit da solo non sarebbe di molto aiuto dal momento che esso è in grado di discriminare soltanto una tra due possibili informazioni, convenzionalmente indicate con 0 e 1. In questo ruolo viene utilizzato all'interno del microprocessore in una struttura chiamata Flag (bandiera) per segnalare se un dato evento è accaduto oppure no.

NIBBLE    E' caratterizzato da  NI = 24 = 16  informazioni. Detto anche semibyte è formato da 4 bit, questa unità di informazione rappresenta generalmente o una cifra in codice BCD (una cifra in base dieci) o una cifra in codice esadecimale.

BYTE    E' caratterizzato da  NI = 28 = 256  informazioni. E` l'unità di informazione maggiormente impiegata, probabilmente perchè il numero di stati possibili (256), non troppo basso e nemmeno troppo alto, ha consentito la realizzazione di diversi codici per la rappresentazione dei simboli alfanumerici comunemente usati nella comunicazione interpersonale; formata da 8 bit serve per rappresentare o un carattere alfanumerico, o un numero compreso tra 0 e 255, o due numeri in codice BCD oppure 8 Flag. Spesso il termine carattere è usato al posto di byte grazie alla corrispondenza tramite il noto codice ASCII (American Standard Code for Information Interchange).

WORD    E' caratterizzato da  NI = 216 = 65.536  informazioni. Correntemente si usa tale termine per designare una unità di informazione composta di 16 bit, dal momento che ci occupiamo del microprocessore a 16 bit 8086, ma si tenga comunque presente che con il termine word si indica generalmente una unità di informazione formata da un numero fissato, ma arbitrario, di bit pari al parallelismo del microprocessore, ossia il numero di bit che vengono elaborati simultamneamente dalla CPU. Viene largamente impiegata per rappresentare sia indirizzi sia numeri compresi tra 0 e 65535.

DOUBLE WORD    E' caratterizzato da  NI = 232 = 4.294.967.296  informazioni. Talvolta viene utilizzato anche il termine DWORD, per indicare una unità di informazione di 32 bit, tipicamente per memorizzare indirizzi estesi.

La tavola seguente riassume la capacità di informazione (espressa in N. di stati) per ciascuna unità e i valori minimi e massimi assunti da ipotetici contatori esadecimali associati alle informazioni.

UNITA'
 
N. BIT
 
NUMERO DI INFORMAZIONI
(dec.)
VALORE MINIMO
(hex.)
VALORE MASSIMO
(hex.)
BIT1 2 0 1
NIBBLE4 16 0 F
BYTE8 256 00 FF
WORD16 64 K = 65.536 0000 FFFF
DWORD32 4 G = 4.294.967.296 0000 0000 FFFF FFFF
QWORD64 4 G  *  4 G 0000 0000 0000 0000 FFFF FFFF FFFF FFFF

Il neofita dell'informatica, il giovane in particolare, è molto attratto dalla possibilità di poter comporre sul video delle immagini. Ora, se lo scopo di questo interesse è la costruzione di una immagine ben fatta, dal punto di vista fotografico ed artistico, si utilizzi uno degli appositi corredi di strumentazione hardware e software già disponibili e si dedichino tutte le proprie energie all'immagine in sé. Ma se la molla di questo interesse è la conoscenza di come possa essere realizzato elettronicamente, da parte della CPU, il mosaico di puntini colorati (pixel) presente sul video di un computer, allora seguitemi un po' in questa avventura tecnologica, cercheremo di capire con la parola e con l'esempio come si fa a ... tracciare un puntino colorato, e poi puntino dopo puntino ...
Se incontrerete, come sarà inevitabile, qualche termine nuovo o non ancora definito, fate uso del Glossario presente in questo stesso sito.

    Ebbene sì, come in tutte le storie dovremmo iniziare "ab ovo", ma saltiamo per il momento i preliminari ed andiamo al dunque. Una parte della memoria RAM del computer è dedicata alla rappresentazione delle informazioni presenti sul monitor, queste possono essere fondamentalmente di due tipi: caratteri alfanumerici (char) e puntini colorati (pixel). Tramite i servizi BIOS è possibile commutare la modalità di funzionamento del video in modo che sia possibile trattare entrambi i tipi di informazione.

    Anche se per inciso, notiamo che un carattere è, a sua volta, composto da un insieme di pixel, tuttavia quando si sa, a priori, che la totalità delle informazioni presenti sul video è di tipo char risulta più utile e più veloce commutare il video in modalità char. In questo caso infatti l'elettronica presente a bordo della scheda video si prenderà cura, e con maggiore velocità, di tracciare i pixel colorati che compongono ciascun carattere piuttosto che impegnare la CPU nell'esecuzione certosina della tracciatura software (pixel per pixel) della matrice del carattere. Una di queste modalità char è individuata dai servizi BIOS con il codice 03h e comporta:
  • la suddivisione del video in un insieme di caselle per caratteri organizzato in 80 colonne e 25 righe, numerate rispettivamente da 0 a 79 e da 0 a 24;
  • la possibilità di usare 16 colori (da 0 a 15) per il carattere e 8 colori (da 0 a 7) per lo sfondo di ciascun carattere.

    Per quanto attiene la modalità grafica, per semplicità di lavoro inizialmente, utilizzeremo quella che porta il codice BIOS 13h che comporta:
  • la suddivisione del video in un insieme di pixel organizzato in 320 colonne e 200 righe, numerate rispettivamente da 0 a 319 e da 0 a 199;
  • la possibilità di scegliere per ciascun pixel uno fra 256 colori possibili, numerati da 0 a 255.

        Troverete nella libreria LBVGA13H.IAS le routine SetVga13h e SetVgaTxt che servono a commutare il video in una delle due modalità appena descritte. Oppure nella libreria LBVGA13H.IMA la macro @SetModeVga che serve per commutare il video in una delle modalità desiderate; attenzione in questo secondo caso, utilizzare sempre codici di modalità ben conosciute e documentate per prevenire malfunzionamenti del video o danni peggiori. Se volete iniziare a provare l'emozione di qualche programmino per VGA provate i seguenti:

  • VGA13001.ASM
        Traccia 1 pixel di colore e coordinate preassegnate. Preview.
  • VGA13002.ASM
        Traccia 4 pixel di colori preassegnati ai vertici dello schermo, ed uno al centro. Preview.
  • VGA13003.ASM
        Traccia un rettangolo di colore preassegnato e di dimensioni massime. Preview.
  • VGA13004.ASM
        Traccia una serie di rettangoli concentrici con colori diversi. Preview.
  • VGA13005.ASM
        Traccia tre rettangoli pieni di dimensioni e colori preassegnati. Preview.
  • VGA13006.ASM
        Scrittura di una riga di testo con colori preassegnati. Preview.

    Per provare uno di questi programmi occorre:

  • Prelevarlo dal sito (o con File/Salva, o con Taglia/Incolla);
  • Rinominarlo con il nome originale, riportato anche nel listato stesso alla voce "Titolo originale";
  • Prelevare la libreria LBVGA13H.IAS e rinominarla;
  • Prelevare, se serve, la libreria LBVGA13H.IMA e rinominarla;
  • Accertarsi di essere in modalità "Linea di comando" detta anche "DOS"
  • Eseguire il comando TASM nomefile e verificarne l'assenza di errori;
  • Eseguire il comando TLINK /t nomefile e verificarne l'assenza di errori;
  • Mandare in esecuzione il programma con il comando NOMEFILE

    Buon Lavoro.
    L'informatica è il mondo dei codici, e spesso ci si perde solo per piccole difficoltà legate all'interpretazione dei codici. Il computer tipico odierno (marzo 2000) consente una scelta di colori che normalmente si aggira attorno a 16.000.000. Ovviamente ognuno dei colori ha il suo codice numerico e sarebbe impensabile associare mentalmente ciascun colore con il rispettivo codice. Ma all'inizio non c'era così tanta ricchezza di scelta e ci fu un tempo in cui 16 colori costituivano già un lusso. Ecco la tabella delle corrispondenze dei 16 colori, riportata con codici espressi in vari sistemi di numerazione:

      DEC HEX BIN
    NERO   0 0 0 0 0 0
    BLU *   1 1 0 0 0 1
    VERDE *   2 2 0 0 1 0
    CELESTE   3 3 0 0 1 1
    ROSSO *   4 4 0 1 0 0
    FUCSIA   5 5 0 1 0 1
    ARANCIONE   6 6 0 1 1 0
    BIANCO SCURO (grigio chiaro)   7 7 0 1 1 1
    NERO CHIARO (grigio scuro)   8 8 1 0 0 0
    BLU CHIARO **   9 9 1 0 0 1
    VERDE CHIARO ** 10 A 1 0 1 0
    CELESTE CHIARO 11 B 1 0 1 1
    ROSSO CHIARO (rosa) ** 12 C 1 1 0 0
    FUCSIA CHIARO 13 D 1 1 0 1
    ARANCIONE CHIARO (giallo) 14 E 1 1 1 0
    BIANCO 15 F 1 1 1 1
          I R G B

    Osservate adesso i tre colori con un asterisco (ROSSO, VERDE, BLU), essi costituiscono i tre colori fondamentali e convenzionalmente vengono indicati con la sigla RGB (Red, Green, Blue). Nell'ultima colonna, contrassegnata in basso, con la scritta IRGB (Intensity, Red, Green, Blue), notate che i tre colori fondamentali riportano la cifra "1" solo in corrispondenza del proprio colore, e ancora che i colori con il doppio asterisco differiscono dai tre fondamentali solo per l'attivazione della cifra "1" in corrispondenza dell'intensità. I primi otto colori hanno il bit di intensità spento, gli ultimi otto colori hanno lo stesso codice dei primi otto, ma con in più attivato il bit di intensità. In sostanza la chiave di tutta la tabella può essere sintetizzata con lo schemino seguente:

    I R G B
    x x x x

    Sostituendo ad "x" il valore "1" oppure "0" possiamo attivare o disattivare il componente di colore corrispondente (Intensity, Red, Green, Blue) ottenendo uno dei 16 colori della tabella grande. Il Giallo, ad esempio, si ottiene mescolando il rosso e il verde e tenendo alta l'intensità di luminosità. Il codice che ne deriva è
    1 1 1 0
    che letto in esadecimale diventa E, corrispondente al decimale 14. Questi codici di colore sono validi, per esempio, nella modalità video 03h, per la rappresentazione dei caratteri; in particolare ogni carattere può assumere uno dei 16 colori della tabella, mentre il suo sfondo corrispondente (background) può variare in uno dei primi 8 colori della tabella. Pertanto un codice esadecimale del tipo 4E sta ad indicare che il carattere verrà tracciato col colore E (giallo) su sfondo 4 (rosso).
    La rappresentazione di un carattere sul video sembra la cosa più naturale del mondo per chi è abituato a usare il computer. Ma per chi deve occuparsene in linguaggio assembly le cose non sono così immediate. Esistono due modi fondamentali per conservare in memoria la struttura di un carattere:
  • Bit mapped
  • True type
        Qui ci occupiamo del primo modo, detto anche a mappa di bit, che è più semplice da gestire pur con delle inevitabili limitazioni. La seconda modalità consente, tra l'altro, l'ingrandimento in scala del carattere, ma comporta maggiori difficoltà nell'uso.
        Un carattere a mappa di bit è composto da una matrice rettangolare larga 8 pixel e alta tipicamente 12 pixel. L'altezza può assumere diversi valori, standard o scelti del programmatore, ma rimane costante per tutto l'insieme dei caratteri definiti. Per esempio, per la lettera "A" può aversi una situazione del tipo:

    . . . . . . . .      0 0 0 0 0 0 0 0      00h
    . . x x x . . .      0 0 1 1 1 0 0 0      38h
    . x . . . x . .      0 1 0 0 0 1 0 0      44h
    . x . . . x . .      0 1 0 0 0 1 0 0      44h
    . x . . . x . .      0 1 0 0 0 1 0 0      44h
    . x x x x x . .      0 1 1 1 1 1 0 0      7Ch
    . x . . . x . .      0 1 0 0 0 1 0 0      44h
    . x . . . x . .      0 1 0 0 0 1 0 0      44h
    . x . . . x . .      0 1 0 0 0 1 0 0      44h
    . x . . . x . .      0 1 0 0 0 1 0 0      44h
    . . . . . . . .      0 0 0 0 0 0 0 0      00h
    . . . . . . . .      0 0 0 0 0 0 0 0      00h

    dove a sinistra abbiamo segnato con la "x" i pixel attivi e con "." i pixel spenti o con il colore di sfondo (background color), al centro abbiamo convertito in binario la situazione precedente, e a destra abbiamo rappresentato in esadecimale ogni riga binaria. Con questi passaggi l'intera matrice 8 x 12, costituita da 96 pixel, viene rappresentata solamente con i 12 byte seguenti:

    00h 38h 44h 44h 44h 7Ch 44h 44h 44h 44h 00h 00h

        Costruendo 256 matrici, una per ogni simbolo dell'intero codice ASCII, si ottiene una tabella di mappe di bit che consente di tenere in memoria la rappresentazione di tutti i caratteri con soli 3072 (12 x 256) byte. Chiaramente al variare dell'altezza del carattere la tabella subirà delle variazioni nelle dimensioni.
    Si notino i pixel spenti attorno al carattere, servono per potere accostare le varie matrici tra di loro mantenendo qualche pixel spento tra un carattere e l'altro e tra una riga e l'altra; al limite sarebbe sufficiente lasciare spenti un lato verticale ed uno orizzontale per consentire una buona leggibilità del testo sul video.
        Poichè è abbastanza noioso costruire tabelle di questo tipo, occorre sapere o dove reperirne di già collaudate e funzionanti o dove trovare degli editor che ne consentano la costruzione.
    Il luogo più naturale per cercare queste tabelle è nella scheda grafica, ma un modo più semplice per ottenerne una idonea alla modalità grafica correntemente impostata è quello di andare a consultare il puntatore di 4 byte che si trova in posizione 43h nella cosiddetta Tavola degli Interrupt, ossia all'indirizzo 0000h:010Ch della Low Memory (4*43h=010Ch). In queste quattro locazioni troviamo il puntatore che indica l'inizio della tabella cercata. Questa informazione, da sola, non è sufficiente per usare le mappe di bit perchè occorre conoscere anche l'altezza di ciascun carattere, ossia quanti sono i byte che lo rappresentano. Questa seconda informazione è reperibile ancora nella Low Memory, al byte individuato dall'indirizzo 0000h:0485h.
        Questa tecnica è stata usata per costruire la funzione PutChar presente nella libreria LBVGA13H.IAS e usata nell'esercizio VGA13006.ASM per la scrittura di un carattere e di una riga di testo con colori preassegnati (Preview). La funzione PutChar, richiamata dalla PutStringZ, consente anche la preselezione del Font tramite il contenuto del registro CH: se questo vale zero viene attivata la tabella interna INT 43h, altrimenti la tabella utente FNT8x10MOD, inclusa in LBVGA13H.IAS. Si comprende come, modificando opportunamente la libreria, sia possibile estendere il numero di font utente fino ad un massimo di 255, basta averne a disposizione e magari caricabili da file al bisogno per alleggerire la quantità di memoria RAM impegnata.
    Non stiamo per parlare delle classiche strutture dati usate in informatica, quanto piuttosto dell'importanza che una detereminata struttura dati può avere nella soluzione di un problema.
    Si vuole, per esempio, scrivere un piccolo programma, in assembly 8086, che accetti in input una cifra variabile da 0 a 9 e produca su video l'emissione di un messaggio corrispondente al codice colori usato per le resistenze in elettronica. La soluzione del problema dipende da come si costruisce la tabella di corrispondenza cifra/colore. Prendiamo in esame due modalità tipiche rappresentate nello schema seguente:


       TabColor    DB    "NERO",0
                   DB    "MARRONE",0 
                   DB    "ROSSO",0
                   DB    "ARANCIONE",0
                   DB    "GIALLO",0
                   DB    "VERDE",0
                   DB    "AZZURRO",0
                   DB    "VIOLA",0
                   DB    "GRIGIO",0
                   DB    "BIANCO",0
    
    Struttura dati n. 1
       TabColor    DB    "NERO     "
                   DB    "MARRONE  "               
                   DB    "ROSSO    "
                   DB    "ARANCIONE"
                   DB    "GIALLO   "
                   DB    "VERDE    "
                   DB    "AZZURRO  "
                   DB    "VIOLA    "
                   DB    "GRIGIO   "
                   DB    "BIANCO   "
    
    Struttura dati n. 2

    La struttura dati n.1 richiede un terminatore (carattere nul) per ogni elemento, mentre la struttura dati n.2 si basa sulla costanza della lunghezza di ogni elemento. Il programma "STRUD001.ASM risolve il problema posto utilizzando la struttura n.1, mentre STRUD002.ASM risolve il caso per la struttura n. 2.
    Prima di ricompilare i programmi ricordarsi di prelevare la libreria LBTXT03H.IAS da includere in fase di compilazione.
    Possono essere fatte le seguenti considerazioni finali:
    • Il risultato, nel corso dell'esecuzione, appare identico nei due casi. Come desiderato in sede di progetto.
    • La struttura n. 1 comporta la scansione sequenziale della tabella TabColor e quindi i tempi di accesso variano a seconda della posizione del dato. Ma la costruzione della tabella richiede un minor quantitativo di memoria e la sua eventuale estensione risulta più agile.
    • La struttura n. 2 ha il vantaggio di un tempo di accesso costante cioè che risulta indipendente dalla posizione del dato. Richiede però un maggior quantitativo di memoria e la sua estensione è complicata dalla necessità di dover tenere conto della dimensione del dato più grande utilizzato.
    Dovendo risolvere problemi analoghi, ma con una mole diversa di dati si tengano presenti le considerazioni precedenti a seconda che sia più importante il risparmio di memoria o la velocità di accesso ai dati.

    Vale la pena ricordare, a questo punto, l'espressione sintetica utilizzata da Niklaus Wirth, inventore dei linguaggi Pascal e Modula, a proposito della definizione dei programmi informatici:

    Algoritmi + Strutture Dati = Programmi

    a sottolineare, qualora ce ne fosse ancora bisogno, l'interdipendenza tra gli algoritmi e le strutture dati. Spesso la migliore soluzione di un problema dipende da una accorta scelta della strutturazione dei dati da elaborare.