Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella...

93
Il Processore e il Debugger IL PERSONAL COMPUTER Il Personal Computer nel nostro mondo Chissà... Forse qualcuno tra i miei amati lettori ha ancora timore di questo strano elettrodomestico, a metà tra un televisore e una macchina per scrivere... Io credo che le cose che intimoriscono siano solo quelle che non si conoscono.... ma nel 99% dei casi si tratta di un timore infondato; basta un niente per rendersi conto di aver sciupato gli anni più belli solo per non aver osato abbastanza.. Il Personal Computer (PC) appartiene, per molti, alla categoria dei tabù, agli oggetti che è meglio evitare... Ma in questo caso più lo conosci, meno lo eviti... Il nostro PC è un eccellente, fedele, amico di lavoro... Quello più affidabile e più sincero. Non è particolarmente intelligente (di solito riflette la nostra intelligenza...) ma sa sempre dove trovare le cose e nessuno come lui è in grado di farle meglio..; come ai veri (pochi) amici non fargli mai mancare il rispetto e le attenzioni che merita... Prova a vederlo sotto questa luce.. e imparerai a condividere con lui una parte del tuo tempo. Bene... è ora che il nostro... diventi di nuovo un oggetto, importante e utile, ma senza anima... Vediamo di conoscerlo meglio. E' inutile perder tempo a descrivere la sua storia... Ci sono molti altri siti che se ne occupano con molta dovizia di particolari; tra questi mi piace ricordare computer museum , per l'amore che il suo autore ha riservato alla documentazione di moltissimi modelli... La descrizione estetica di un Personal Computer non merita più tempo di quanto ne serva per prendere atto che, vicino al monitor, insieme a tastiera e mouse, c'è una scatola di metallo più o meno grande; è in questo contenitore (Case, in inglese) che trova posto il centro di calcolo vero e proprio... Dentro il Case c'è la scheda madre, una piastra relativamente grande che ospita il processore e la memoria, insieme a tutti i circuiti elettronici di supporto, come la scheda video (dalla quale esce il cavo per il monitor) e la scheda audio (alla quale si collegano le casse acustiche, le cuffie e il microfono,... ma anche il nostro impianto HiFi, all'occorrenza) o la scheda modem (alla quale si porta la linea telefonica e il telefono). Se ci capita di passare in un negozio di computer tutti sanno tutto, commessi e clienti...; non ti fare intimorire.. spesso è mestiere, talvolta è esibizione e, ahimè qualche volta è superficialità. No! con ciò non voglio dire che, nell'immediato, siano informazioni di facciata o inutili: i primi fanno bene il loro lavoro: si informano e cercano (se non sono arroganti..) di aiutare a scegliere... i secondi fanno bene la loro parte: si informano e cercano di non farsi fregare... Non invidiare chi ti sembra esperto di computer: in gran parte non lo è più di te.. Si tiene informato, legge qualche articolo e, sulla base dell'opinione altrui, fa opinione a sua volta... Il mondo dei computer è effimero e precario: quello che è certezza oggi domani è carta straccia... Tutto invecchia e muore in tempi assurdamente veloci. 1

Transcript of Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella...

Page 1: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

  Il Processore e il Debugger IL PERSONAL COMPUTER

Il Personal Computer nel nostro mondo

Chissà... Forse qualcuno tra i miei amati lettori ha ancora timore di questo strano elettrodomestico, a metà tra un televisore e una macchina per scrivere...Io credo che le cose che intimoriscono siano solo quelle che non si conoscono.... ma nel 99% dei casi si tratta di un timore infondato; basta un niente per rendersi conto di aver sciupato gli anni più belli solo per non aver osato abbastanza..Il Personal Computer (PC) appartiene, per molti, alla categoria dei tabù, agli oggetti che è meglio evitare... Ma in questo caso più lo conosci, meno lo eviti...Il nostro PC è un eccellente, fedele, amico di lavoro... Quello più affidabile e più sincero.Non è particolarmente intelligente (di solito riflette la nostra intelligenza...) ma sa sempre dove trovare le cose e nessuno come lui è in grado di farle meglio..; come ai veri (pochi) amici non fargli mai mancare il rispetto e le attenzioni che merita...Prova a vederlo sotto questa luce.. e imparerai a condividere con lui una parte del tuo tempo.Bene... è ora che il nostro... diventi di nuovo un oggetto, importante e utile, ma senza anima... Vediamo di conoscerlo meglio.E' inutile perder tempo a descrivere la sua storia... Ci sono molti altri siti che se ne occupano con molta dovizia di particolari; tra questi mi piace ricordare computer museum, per l'amore che il suo autore ha riservato alla documentazione di moltissimi modelli...La descrizione estetica di un Personal Computer non merita più tempo di quanto ne serva per prendere atto che, vicino al monitor, insieme a tastiera e mouse, c'è una scatola di metallo più o meno grande; è in questo contenitore (Case, in inglese) che trova posto il centro di calcolo vero e proprio...Dentro il Case c'è la scheda madre, una piastra relativamente grande che ospita il processore e la memoria, insieme a tutti i circuiti elettronici di supporto, come la scheda video (dalla quale esce il cavo per il monitor) e la scheda audio (alla quale si collegano le casse acustiche, le cuffie e il microfono,... ma anche il nostro impianto HiFi, all'occorrenza) o la scheda modem (alla quale si porta la linea telefonica e il telefono).Se ci capita di passare in un negozio di computer tutti sanno tutto, commessi e clienti...; non ti fare intimorire.. spesso è mestiere, talvolta è esibizione e, ahimè qualche volta è superficialità.No! con ciò non voglio dire che, nell'immediato, siano informazioni di facciata o inutili:

i primi fanno bene il loro lavoro: si informano e cercano (se non sono arroganti..) di aiutare a scegliere... i secondi fanno bene la loro parte: si informano e cercano di non farsi fregare...

Non invidiare chi ti sembra esperto di computer: in gran parte non lo è più di te.. Si tiene informato, legge qualche articolo e, sulla base dell'opinione altrui, fa opinione a sua volta...

Il mondo dei computer è effimero e precario: quello che è certezza oggi domani è carta straccia... Tutto invecchia e muore in tempi assurdamente veloci.Solo una cosa è positiva: le regole di mercato vogliono che il prezzo non cambi: con gli stessi soldini oggi compri un computer molto più potente di quello che avresti potuto comprare ieri (... ieri, non un anno fa...).Per questo non dobbiamo sottostare ad alcuna frustrazione, quando parliamo e sentiamo parlare di computer: se ne deve parlare come si parla degli accessori di un bagno... chi può compra quelli placcati in oro (?!), altri si accontentano di quelli in acciaio inossidabile, ma tutti sanno come usare un rubinetto e non si sono mai chiesti come funziona il miscelatore dell'acqua calda con quella fredda....Si tratta solo di tenersi aggiornati.. e di scegliere una delle numerose riviste che occhieggiano nelle edicole; non sottovalutarti... per sapere quello di cui si riempie la bocca la gran parte della gente basta poco...Scegliere tra 2 schede audio o (addirittura!!) tra 2 schede madri è come scegliere tra 2 frigoriferi o 2 lavatrici... ci si informa... si impara... si sceglie!

La conoscenza commerciale delle cose ci aiuta a ottenere il massimo con la minor spesa, in funzione dell'uso che vogliamo fare dell'oggetto acquistato... Per molti basta questo e, spesso, avanza... per farli ritenere esperti. Vedi che non è il caso di temerli?

Lo scopo di un Tutorial sulla programmazione dei processori non lascia spazio alla descrizione dei dettagli costruttivi delle singole parti componenti di un computer.Del resto, per quanto detto poco fa:

decantare le eccellenti prestazioni di alfa rispetto a beta sarebbe tempo perso, per la effimera vitalità di etrambe; domani, probabilmente, dovremo rifare tutto da capo per gamma e delta...

la consapevolezza di usare una memoria DDRAM PC2100 invece di una SDRAM PC133 (... classica badilata di ... dei ben pensanti...) non intacca il principio per il quale o una o l'altra deve comunque essere

1

Page 2: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

presente nel sistema...... e non buttiamo la croce addosso ai ben pensanti... c'è il rischio che prima o poi si possa entrare a far

parte di questo circolo di eletti..Se desideriamo saperne di più c'è sempre mamma rete; ...per esempio collegandoci con uno dei fornitori di elettronica on-line come Essedi o Chl (...caffè pagato al bar, per la citazione), benemerite per fare i loro interessi con un occhio di riguardo per i loro clienti: di solito ogni articolo è corredato di utili e soddisfacenti schede descrittive!Ecco... la filosofia di questo Capitolo sarà quella di badare ai principi funzionali (eterni) piuttosto che agli oggetti che li implementano (fatui e mortali).

Il Personal Computer: cos'è....Per descrivere funzionalmente un Computer di solito si ricorre al modello di Von Neumann, secondo il quale un apparato elaboratore è costituito da 3 parti:

l'unità di calcolo vera e propria, in sintesi, il microprocessore. la memoria. i dispositivi di ingresso e di uscita.

Dunque, riemergono termini e parole familiari...

Il microprocessore (o, sinteticamente, il processore, o ancora più in sintesi, CPU, Central Processing Unit, unità centrale di processo) è l'oggetto dello studio di questo Capitolo: ne parleremo in lungo e in largo; il suo compito è quello di controllare e decidere, quello di eseguire e di elaborare, ... quello di obbedire sempre e comunque al nostro pensiero!Tutta l'elaborazione viene eseguita nella CPU.La memoria è il luogo nel quale il processore trova conforto: la sua grande capacità, le sue enormi potenzialità sono niente senza la memoria.Il processore senza memoria esterna è un cervello senza corpo, affascinante (?!) da vedere ma assolutamente inutile; la prima cosa che fa, senza saperlo e senza volerlo, per istinto, è saltare in una locazione di memoria, alla ricerca di qualche cosa da fare...Dunque, la memoria è indispensabile in un computer perché contiene il programma (in linguaggio macchina) che il processore è chiamato ad eseguire......e perchè si presta a conservare i dati eventualmente elaborati dal processore, almeno fino a quando si riterrà opportuno salvarli in qualche punto più sicuro.Si, perchè la memoria (almeno quella che si occupa di custodire i dati elaborati e/o modificati dal processore) è volatile, cioè mantiene l'informazione solo fino a quando rimane alimentata; tutti gli utenti di un computer hanno inzuppato il fazzoletto almeno una volta perchè ...è andata via la corrente!  ... o perchè, pur consapevoli del potenziale rischio, non hanno salvato il loro lavoro. 

Salvato dove? Ma sul disco fisso (HardDisk) o su un dischetto (FloppyDisk)... Spesso si tende a confondere questi oggetti con la memoria; tecnicamente non è cosi:

la memoria vera e propria è la RAM (Random Access Memory) ed è inserita a moduli direttamente nei rispettivi alloggiamenti della scheda madre. Gli HD e i FD sono dispositivi di input/Output (che vedremo tra poco...): solo per affinità sono ritenuti memoria, ma per distinguerli da quella vera sono detti memoria di massa.

Beh.. ora il segreto è svelato; non è pensabile che un computer degno di questo nome possa essere privo di oggetti in cui salvare (o assumere) informazioni: gli HD e i FD sono periferiche di input/output, perché possono essere lette e scritte dal processore.

2

Page 3: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

Ma non è nemmeno immaginabile poter lavorare senza un monitor (periferica di uscita) e una tastiera o un mouse (periferiche di ingresso).I moderni sistemi operativi, con interfaccia grafica (come Windows), ci hanno abituati bene... Prima di accendere il computer provate a togliere il cavetto del mouse e poi accendete... questo piccolo sorcio bianco vi mancherà da morire!

Spesso le credenze popolari tendono a confondere il microprocessore con il computer... La cosa è tanto più vera se ad essere coinvolto è un microcomputer, del tipo di quelli montati sulle accensioni elettroniche della tua macchina o nella tua lavatrice...Non è così: il primo è parte fondamentale del secondo; il secondo senza il primo non è nulla.

3

Page 4: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

  Il Processore e il Debugger I BUS DEI PROCESSORI

I Bus del Personal Computer

Le 3 componenti della macchina di Von Neumann sono strettamente collegate tra loro.E’ indubbio che il controllo risiede nella CPU ma sembra ragionevole pensare che esso possa essere esercitato solo in presenza di una struttura di interscambio, uno o più canali delegati alla trasmissione e al controllo dell'informazione che la CPU deve scambiare sia con la memoria che con i dispositivi di Input/Output.Questa struttura è nota con il nome di bus di sistema; si tratta in sostanza di gruppi di fili, di solito in numero piuttosto elevato, ciascuno dei quali può assumere uno dei 2 livelli logici possibili, rappresentati da presenza ("1") o assenza ("0") di tensione elettrica.In questo modo a ciascun filo è affidata un'informazione elementare (bit) che assume una certa importanza, rapportata alla quantità dei fili stessi.Un bus a 16 bit è dunque formato da 16 fili, e così via...

Un computer possiede 3 tipi di bus: il bus dati il bus degli indirizzi il bus di controllo

Tutti e 3 i bus hanno origine dentro il microprocessore e il loro fili vengono poi riproposti anche al di fuori, sotto forma di minuscole piste, stampate sulla scheda madre, al fine di raggiungere ogni oggetto che ne ha bisogno.Spesso i disegni tecnici sono appesantiti dalla presenza di questi numerosi gruppi di fili paralleli: oltre ad essere ingombranti la loro presenza in dettaglio non è particolarmente necessaria; è questa la ragione per la quale gli schemi funzionali rappresentano i bus con delle voluminose larghe tracce rettangolari sulle quali si evidenziano delle frecce, che stanno ad indicare il senso dell'informazione che corre nei fili.Il disegno della pagina precedente è piuttosto eloquente e, per comodità, lo riproponiamo qui sotto:

Il nome associato ai fili di ciascuno dei 3 bus può essere anche diverso, da processore a processore; dopotutto sono numerosi i produttori di questi preziosi oggetti e, di norma, ciascuno di loro mantiene la sua autonomia e la sua architettura.Ma la cosa non ci tocca... ciascun filo manterrà comunque invariato il compito e la funzione che gli è affidata, indipendentemente dal tipo di CPU presente nel computer.L'analisi di questi onerosi incarichi sarà oggetto delle prossime pagine.

Il Bus DATI

Il Bus Dati è la struttura di scambio principale di un computer; è così importante che è diventato uno strumento per distinguerli tra di loro.Il numero di linee (bit) del bus dati viene utilizzato per qualificare il processore a cui appartiene, per cui è frequente parlare di processore a 32 bit o di CPU a 64 bit, intendendo implicitamente la dimensione del suo bus dati.

4

Page 5: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

La cosa non stupisce se si pensa che più grande è il numero di linee del bus dati maggiore è la quantità d'informazione che è possibile scambiare in un colpo solo.. e quindi la CPU e il computer che la ospita sono più veloci.Basta pensare al tempo necessario a prelevare 8 bytes (64 bit) tutti insieme, piuttosto che uno alla volta.Il disegno seguente mostra un tipico bus dati:

Possiamo notare che in tutti e 4 i rami del Bus sono presenti delle frecce e un numero:

dalla Cpu le frecce entrano ed escono: la cosa non sorprende perchè, nell'ambito di un computer, chi decide letture e scritture è proprio la Cpu.

il senso delle frecce precisa che la memoria è un dispositivo in grado di essere letto e scritto, mentre alcuni dispositivi di I/O potranno essere solo scritti (quelli di output, come il monitor) o solo letti (quelli di Input, come la tastiera).

in realtà esistono dispositivi di I/O che possono essere sia letti che scritti (come gli HD) per i quali vale il disegno della pagina precedente.

Il numero indicato dentro la traccia rettangolare (che d'ora in poi chiameremo bus...) è quello dei fili che rappresenta, nel nostro esempio 16, tipico del bus dati di un 8086.In conclusione, il Bus dati è una struttura bidirezionale gestita esclusivamente dal processore; il fatto che il flusso possa entrare o uscire a piacere della CPU anticipa un concetto fondamentale della vita di un computer: non sembra possibile che l'informazione possa entrare ed uscire contemporaneamente: questo ci suggerisce la necessità della presenza di sincronismi.Un processore (e quindi il computer) non può vivere e lasciar vivere senza la presenza di un cadenzatore d'eventi, che stimoli e orienti le sue risorse in operazioni organizzate e successive, una all'altra...Questo dispositivo è il generatore di clock (spesso detto orologio di sistema, nell'estremo sforzo di italianizzare proprio tutto..) che, insieme alla dimensione del bus dati, diventa un altro importante metro per misurare la potenza globale di un computer.Nella ventina d'anni di vita dei personal computer i progettisti sono stati molto occupati, nella certezza di renderli ogni volta più utili e potenti... Certo, dai primi processori (8 bit), a quelli del primo PC (1980, 16 bit), ad oggi (2002, 64 bit) se n'è fatta di strada e ...l'avvenire merita di essere vissuto.La tabella seguente ricorda queste tappe, con riferimento alla famiglia 80x86:

Processore Register Size Data Bus Size8088 8  bit 8  bit

80188 8  bit 8  bit8086 16  bit 16  bit

80186 16  bit 16  bit80286 16  bit 16  bit

80386SX 32  bit 16  bit80386DX 32  bit 32  bit

80486 32  bit 32  bitPentium 32  bit 64  bit

Pentium II 32  bit 64  bitPentium III 32  bit 64  bitPentium IV 32  bit 64  bit

Naturalmente la misura del bus indica la dimensione massima dei dati che possono essere scambiati tra i vari componenti in un sistema di elaborazione, ma il progettista del programma può coinvolgere la CPU in operazioni in grado di elaborare anche dati di dimensione inferiore.

5

Page 6: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

Per certi versi è anche quello che faremo noi, nelle varie parti del tutorial: quasi certamente possiamo disporre di computer di ultima generazione ma, per mantenere lo studio in termini semplici e tradizionali, faremo finta di avere a che fare con un 8086, il padre riconosciuto di tutti i successivi modelli.La cosa non deve stupire, supportata com'è dalle seguenti considerazioni:

le moderne CPU mantengono la portabilità verso il basso, cioè devono garantire ai vecchi software di poter girare senza problemi (sebbene, spesso, il fatto di girare non sia sufficiente per assicurare la loro godibilità, in genere a causa dell'elevata velocità a cui sono costretti).

le caratteristiche funzionali dell'8086 sono un sottoinsieme di quelle degli attuali processori, per cui progettare con riferimento alle prime significa solo rinunciare (un po' masochisticamente..) ai vantaggi garantiti dalle seconde.

riferirsi al set d'istruzioni e ai registri dell'8086 è solo una scelta di comodo, didatticamente molto diffusa e, forse, più immediata; certamente l'appassionato neofita, una volta svezzato, saprà percorrere da solo i nuovi sentieri, forse più impervi ma pieni di fascino e di rinnovati stimoli.

Il Bus degli INDIRIZZI

In ogni computer il bus dati è dunque indispensabile al processore per trasferire i comandi e le richieste ai suoi fedeli sudditi esterni, e per riceverne eventuale risposta.Ma siccome la CPU non ha occhi, ne bocca, ne dita da inserirvici (...per richiamare la loro attenzione con un fischio alla Trap..) appare subito evidente la necessità di disporre di uno strumento che le consenta di chiamare le periferiche e la memoria, senza pericolo di confonderle tra loro..Siccome la lingua dei processori rimane ineluttabilmente il binario, i nomi di periferiche e di locazioni di memoria saranno comunque e sempre numeri binari (come per esempio: 0000001110100110).Fortunatamente la conoscenza del sistema di numerazione esadecimale ci darà una mano ad esprimere informazioni di questo tipo (nell'esempio di prima: 03A6H), quando saranno richieste nei programmi assembly.Il problema di farsi riconoscere è stato risolto con un secondo bus, fisicamente uguale al bus dati, cioè anch'esso composto da numerosi fili paralleli, ciascuno in grado di supportare uno dei bit necessari per esprimere il nome esadecimale della periferica o della locazione di memoria desiderata.Si tratta del Bus Address (o Bus degli Indirizzi); la figura seguente mette in evidenza che questo bus, a differenza del bus dati è monodirezionale; d'altro canto il suo compito è limitato a individuare chi deve intervenire in un rapporto di scambio... ed è la CPU che impartisce l'ordine, per cui esso (o meglio, il numero che corrisponde all'oggetto che deve intervenire) potrà solo uscire dal processore.

Anche in questo caso la struttura a bus evidenzia questo fatto con una freccia rivolta verso chi è chiamato a ricevere il comando, così come il numero specificato dentro il bus rappresenta ancora la quantità di fili paralleli coinvolti.Ora però ci colpisce una differenza: nell'esempio di figura i fili che escono dalla CPU e quelli che entrano nella memoria sono 20, mentre quelli che entrano nei 2 dispositivi di I/O sono solo 10.Riprenderemo tra poco questa apparente incongruenza, non riscontrabile nell'altro bus... Per ora è importante fissare bene in mente che i 2 bus non vanno assolutamente confusi tra loro..

6

Page 7: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

E' importante distinguere con sicurezza il bus dati dal bus address; entrambi hanno origine nella CPU ma il primo è il vero canale dell'informazione, mentre il secondo serve solo per individuare con certezza l'interlocutore della CPU. Non confondiamo dati con indirizzi!

Il Bus degli INDIRIZZI con la Memoria

Adesso è il momento di entrare nel merito; non ci è ancora chiaro come possa un numero esadecimale individuare senza ambiguità una locazione di memoria o una periferica...Nel primo caso l'immagine è forse più evidente: ogni dispositivo di memoria è formato da una pila di cassetti (locazioni) uno sotto l'altro, disponibili a contenere 8 bit (un byte) ciascuno.Per accedere ad una di queste locazioni si usano le linee del Bus Address e, poichè ciascuna di esse può assumere un livello logico binario è facile pensare che:

con una linea d'indirizzo (ADD0) potremo localizzare 2 celle di memoria,  la prima quando la linea vale 0 e la seconda quando vale 1.

con 2 linee (ADD0 e ADD1) si potranno controllare 4 celle di memoria,  la prima con ADD0=0 e ADD1=0, la seconda con 01, la terza con 10 e l'ultima con 11.Il meccanismo si può facilmente generalizzare: con 3 linee le celle saranno 23=8 e con n linee potremo controllare 2n locazioniDunque la massima dimensione della memoria indirizzabile dipende dalla quantità di fili disponibile nel bus address... Più alto è questo numero, maggiore è il numero di locazioni di memoria controllabili, in lettura o in scrittura, da parte della CPU.Per fissare le idee possiamo considerare il bus address dell'8086.Quando questo processore venne presentato, con le sue 20 linee d'indirizzo assicurava la disponibilità di 1 Mega di memoria, per l'esattezza 220=1.048.576 locazioni.La cosa faceva faville! Qualunque altro computer precedente poteva disporre al massimo di 64k (216=65536 locazioni) di memoria. Sembrava che il problema fosse risolto per sempre.... Sembrava!Ben presto questa disponibilità si sarebbe rivelata assolutamente insufficiente, così come l'aumento a 16 Mega (=224), assicurato dall'aggiunta di altre 4 linee di indirizzo, con l'avvento di '286 e '386.I moderni processori dispongono di 36 linee d'indirizzo e i potenziali 65536 Mega (=236) garantiti sono per ora sufficienti.Nelle configurazioni che vanno di moda oggi la quantità normale di ram installata è di 128M con tendenza ai 256M (raramente ne viene installata in misura maggiore, se non in presenza di centri di calcolo particolarmente bisognosi, come server o work station industriali).Il futuro ci riserverà certamente bus address ancora più capaci: le architetture già prevedono una probabile espandibilità a 48 linee...I processori della famiglia 80x86 hanno visto aumentare velocemente nel tempo anche la dimensione di questo bus; vediamo il dettaglio:

Processore Data Address Size Dimensione Max Memoria8088 20  bit 220 =  1  Mbytes

80188 20  bit 220 =  1  Mbytes8086 20  bit 220 =  1  Mbytes

80186 20  bit 220 =  1  Mbytes80286 24  bit 224 = 16  Mbytes

80386SX 24  bit 224 = 16  Mbytes80386EX 25  bit 225 = 32  Mbytes80386DX 32  bit 232 =  4  Gbytes

80486 32  bit 232 =  4  GbytesPentium 32  bit 232 =  4  Gbytes

Pentium II 36  bit 236 =  64 GbytesPentium III 36  bit 236 =  64 GbytesPentium IV 36  bit 236 =  64 Gbytes

Il bus address è nato per indirizzare (come fa capire il suo nome..) cioè per consentire al processore di chiamare in causa una ben precisa locazione di memoria, ma anche una determinata periferica; il numero dell'indirizzo, posto sul bus, arriva di norma sia alla prima che alla seconda, ma solo una delle 2 risponderà al processore! Come è possibile?

7

Page 8: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

La cosa non ha nulla di magico: insieme al bus address, si fa pervenire ad entrambe un filo di controllo. Se il livello presente su di esso è 1 sarà la memoria ad intervenire, mentre se 0 sarà il dispositivo di I/O.Questa tecnica è praticata fin dai primi processori che, con un secondo filo di controllo (o con 2 fili distinti) possono far sapere a chi riceve l'indirizzo se deve dare (read) o ricevere (write) dati.Sul processore 8086 la prima linea di controllo si chiama MEM/IO (MEMoria o Input/Output) e le altre 2 RD e WR (entrambe attive basse); combinando tra loro questi segnali (con opportuni piccoli circuiti, detti di decodifica) viene evitato ogni conflitto e il processore potrà disporre a suo piacere o dell'una o dell'altro, in lettura o in scrittura.Ma chi si incaricherà di suggerire al processore i valori logici con cui impostare le linee di controllo e dove prenderà il numero binario da mettere sul bus address?Una delle magie dei processori è quella di interpretare ed eseguire i programmi... Basterà quindi costringerlo ad eseguire l'istruzione giusta.Di solito la lettura o la scrittura di una locazione di memoria si realizza facendo eseguire l'istruzione MOV; spetta alla posizione degli operandi stabilire il flusso dei dati.L'istruzione MOV è una tra le più varie e multiformi; fissiamo le idee con un paio tra i numerosi possibili esempi, lasciando al lettore la possibilità di cimentarsi con altri.Nelle descrizioni seguenti sono citati concetti (come indirizzo fisico o registri) che non ti sono ancora noti, ma il senso delle operazioni sembra accettabile.Anche se il tono della trattazione è decisamente tecnico (e ti sarà chiaro solo al termine di questo paragrafo dedicato al processore...) desidero proportelo lo stesso, per darti la possibilità di confrontarti con la reale sequenza di eventi che si susseguono nelle operazioni di lettura scrittura e della sua memoria.

l'istruzione MOV AL,ES:[DI] si legge così: metti in AL il contenuto della locazione puntata da ES:DI. si tratta dunque di un'operazione di lettura di memoria. obbliga il processore a scrivere sul bus address l'indirizzo fisico ottenuto combinando il contenuto

dei suoi 2 registri ES e DI. non appena l'indirizzo è stabile il processore mette MEM/IO a 1 e RD a 0, obbligando la memoria

a copiare sul bus dati il contenuto della locazione puntata dall'indirizzo predisposto sul bus address (come vedi i 2 bus sono e hanno compiti diversi!)

il processore si mette in attesa sul bus dati per catturare l'informazione in arrivo e, non appena è disponibile, la scrive nel suo registro AL.

se il processore fosse un 8086 e il contenuto dei suoi registri fosse ES=B800H e DI=0000H, sul bus address verrebbe posto l'indirizzo fisico B8000H (appunto a 20 bit) e sul bus dati (e poco dopo, in AL) verrebbe a trovarsi il byte (8 bit) contenuti nella prima locazione della RamVideo.

l'istruzione MOV DS:[SI], AL si legge così: metti nella locazione puntata da DS:SI il contenuto del registro AL.

si tratta dunque di un'operazione di scrittura di memoria. obbliga il processore a scrivere sul bus address l'indirizzo fisico ottenuto combinando il contenuto

dei suoi 2 registri DS e SI. poiché il dato gli appartiene (provenendo da un suo registro, AL) il processore lo copia

immediatamente sul bus dati, a disposizione della memoria dopo qualche istante (non appena indirizzo e dato sono stabili) il processore mette MEM/IO a 1 e

WR a 0, obbligando la memoria a prelevare il dato dal bus dati e a copialo nella locazione puntata dall'indirizzo predisposto sul bus address.

se il processore fosse un 8086 e il contenuto dei suoi registri fosse DS=1234H e SI=0000H, sul bus address verrebbe posto l'indirizzo fisico 12340H (sempre a 20 bit) e sul bus dati (e poco dopo, anche dentro la locazione) verrebbe a trovarsi il byte (8 bit) contenuto nel registro AL.

Il Bus degli INDIRIZZI con i Dispositivi di I/O

In chiusura della pagina precedente abbiamo sottolineato che il processore è in grado di distinguere tra memoria e dispositivo di I/O, semplicemente fissando uno dei 2 livelli logici possibili sulla sua linea di controllo MEM/IO.Sulla base di questa premessa vediamo di analizzare ora il problema dell'indirizzamento delle periferiche; di certo la CPU deve poterle coinvolgere quando lo ritiene necessario e non può permettersi canali privilegiati, cosicché il medesimo bus degli indirizzi utilizzato per la memoria sarà usato anche per chiamare in lettura (con le linee di controllo MEM/IO e RD entrambe a 0) e/o in scrittura (con MEM/IO e WR entrambe a 0) i dispositivi di I/O.I progettisti dei processori 80x86 hanno stabilito fin dall'inizio di destinare per questo scopo solo una parte delle linee di indirizzo disponibili: attualmente solo le prime 16 (poco meno della metà...) vengono coinvolte

8

Page 9: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

nelle operazioni di IN/OUT, per cui è facile prevedere la possibilità di gestire fino a 65536 (216) dispositivi d'ingresso ed altrettanti d'uscita. Nei primi modelli (tra cui l'8086) le linee d'indirizzo coinvolte erano per altro solo 10, per cui il numero di dispositivi gestibili era ridotto a 1024 (210) d'ingresso ed altrettanti d'uscita.E' dunque chiaro che, per programmare un dispositivo a basso livello, è necessario conoscere il suo nome binario, il suo indirizzo base.Ad ogni oggetto, presente sulla scheda madre del tuo Computer o raggiungibile attraverso le sue porte di I/O, viene affidato un numero esadecimale a 16 bit, in grado di farlo riconoscere; al processore basterà, per poterlo controllare, mettere questo numero sul bus address.

Non tutte le linee del bus address sono coinvolte nelle operazioni verso i dispositivi di Input e di Output.

Sebbene non sia un'affermazione assoluta, nella gran parte dei casi l'indirizzo del dispositivo concorrente sarà predisposto nel registro DX che, con i sui 16 bit è più che sufficiente per esprimerlo; in senso figurato si può parlare di nome del dispositivo, sottolineando che ogni periferica sarà identificabile con un numero esadecimale unico e dedicato.Come per la lettura o la scrittura della memoria anche quella dei dispositivi si realizza facendo eseguire al processore un'istruzione specifica.Ora però il flusso dei dati è legato all'istruzione stessa: la periferica fornisce il dato al processore con l'istruzione IN, e lo riceve con l'istruzione OUT:

l'istruzione IN AL,DX si legge così: metti in AL il dato proveniente dalla periferica il cui indirizzo è indicato dal contenuto di DX.

si tratta dunque di un'operazione di lettura di periferica. obbliga il processore a scrivere sui primi 16 bit del bus address l'indirizzo fisico ottenuto dal

contenuto del suo registro DX. non appena l'indirizzo è stabile il processore mette MEM/IO  a 0 e RD a 0, obbligando il

dispositivo a copiare la sua informazione sul bus dati. il processore si mette in attesa sul bus dati per catturare l'informazione in arrivo e, non appena è

disponibile, la trascrive nel suo registro AL. se la periferica è lenta potrebbe anche fornire in ritardo questo dato: la CPU infatti non rimane in

attesa all'infinito; per questa ragione, nelle operazioni di IN dai dispositivi,  possono essere necessarie interfacce più efficienti.

se il processore fosse un 8086 e il contenuto del suo registro DX  fosse 0379H , sul bus address verrebbe posto il numero  fisico 00379H (a 20 bit) e sul bus dati (e poco dopo, in AL) verrebbe a trovarsi il byte (8 bit) proveniente dal Registro d'ingresso della porta parallela .

l'istruzione OUT DX, AL si legge così: spedisci alla periferica il cui indirizzo è indicato dal contenuto di DX il dato contenuto nel registro AL.

si tratta dunque di un'operazione di scrittura di periferica. obbliga il processore a scrivere sui primi 16 bit del bus address l'indirizzo fisico ottenuto dal

contenuto del suo registro DX. poichè il dato gli appartiene (provenendo da un suo registro, AL) il processore lo copia

immediatamente sul bus dati, a disposizione del dispositivo d'uscita dopo qualche istante (non appena indirizzo e dato sono stabili) il processore mette MEM/IO  a 0

e WR a 0, avvisando la periferica che il dato è pronto sul bus dati, a sua disposizione

se la periferica è lenta potrebbe anche perdere questo dato: esso non è infatti disponibile all'infinito; per questa ragione, nelle operazioni di OUT verso i dispositivi,  possono essere necessarie interfacce più efficienti.

se il processore fosse un 8086 e il contenuto del suo registro DX  fosse 0378H , sul bus address verrebbe posto il numero  fisico 00378H (a 20 bit) e sul bus dati (assunto da AL) verrebbe a trovarsi il byte (8 bit) destinato al Registro d'uscita della porta parallela

La potenza indiscussa dell'Assembly rispetto ad ogni altro linguaggio di programmazione sta nella sua capacità di intervenire nei punti più sensibili del personal computer, mediante l'indirizzamento diretto dei dispositivi.L'uso diretto di questo strumento va comunque esercitato con molta attenzione e con la consapevolezza di quello che si andrà a fare...L'elenco degli indirizzi dei principali dispositivi di un PC è disponibile cliccando qui

Il Bus di CONTROLLO

9

Page 10: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

Il microprocessore è la vita del tuo computer; con i suoi bus chiama (address) e parla (dati) al resto del (suo) mondo.Per questo la maggior parte dei suoi piedini è destinata ad assicurare questi 2 importanti canali di comunicazione; tutti i rimanenti piedini sono dedicati alle linee di controllo, cioè ai segnali che esso genera per chiarire il servizio che desidera dalla sua memoria e dai numerosi dispositivi di input/output ad esso collegati.Nelle pagine dedicate alla descrizione del bus address abbiamo già avuto modo di constatare che il numero posto su di esso non basta per dare o assumere informazioni dal bus dati: il processore deve essere certo di collegarsi con l'oggetto giusto e, per farsi capire, non può che utilizzare l'unica lingua che conosce, il codice binario.Per questo mette degli 1 o degli 0 su una o più linee di controllo: gli oggetti che li ricevono (che parlano la stessa lingua del processore...) devono a loro volta essere in grado di decifrare (decodificare) i bit su queste linee, ignorando i comandi che non li riguardano ed eseguendo (senza potersi rifiutare) quelli a loro destinati.Dunque il cosiddetto bus di controllo non è un vero e proprio bus, cioè tale da raccogliere e organizzare linee dello stesso tipo (come data e address), ma piuttosto una raccolta di linee specializzate e funzionalmente molto diverse tra loro.Le linee del bus di controllo sono in parte generate dal processore, come RD, WR e MEM/IO, viste nelle pagine precedenti; ma alcune sono fornite alla CPU dall'esterno, cioè sostanzialmente da noi.La più significativa è la linea di CLK, sulla quale è presente un'onda quadra (clock) la cui frequenza dà la vita al processore; la spinta tecnologica ha portato a traguardi assolutamente straordinari: la velocità base dei processori ha superato il GigaHertz e chissà dove ci fermeremo. La tabella mostra l'evoluzione dei processori da questo punto di vista:

Processore Clock Max(in MHz)

8086/8088 580186/80188 10

80286 2580386 3380486 100

Pentium 233Pentium II 450

Pentium III 800Pentium IV 2200

L'architettura dei processori si è evoluta enormemente nel tempo e, sebbene in misura superficiale, anche la loro dimensione esterna e il loro numero di piedini può, in qualche modo, esprimere questa evoluzione:

Processore Numero Piedini Tipo di Contenitore

8086/8088 40 DIP (Dual InLine Package)

80186/80188 68 PGA (Pin Grrid Array)

80286 68 PGA (Pin Grid Array)PLCC (Plastic Leaded Chip Carrier)

80386 132 DX-PGA (Pin Grid Array)

80486 168 PGA (Pin Grid Array)

Pentium 296 SPGA (Staggered Pin Grid Array)

Pentium II 370 BGA615 (Ball Grid Array)

Pentium III 370 FC-PGA (Flip-Chip Pin Grid Array)

Pentium IV 478 FC-PGA2 (Flip-Chip Pin Grid Array 2)

10

Page 11: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

  Il Processore e il Debugger PROCESSORE 80x86

Il Pin-Out della CPU 8086Il modo migliore per tentare di saperne di più sulle linee di controllo è quello di osservare il pin-out di un processore, cioè la disposizione dei suoi piedini.Poichè l'analisi dei 478 piedini del Pentium 4 sembra improponibile, analizzeremo quelli del vecchio padre 8086 (che per altro abbiamo adottato anche per lo sviluppo dei prossimi programmi in Assembly).In quel tempo i componenti integrati avevano ancora la forma snella e allungata dei contenitori Dual-in-Line (cioè con piedini in linea su 2 file) e la dimensione dei più grandi era proprio di 40 pin (20+20) come quella del nostro... Vediamola:

11

Page 12: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

SHAPE \* MERGEFORMAT

I limiti di questa struttura hanno subito imposto scelte obbligate ai progettisti; il conto è presto fatto: 20 linee d'indirizzo, più 16 di dato, più 2 per l'alimentazione (Vcc e GND)... fanno 38 piedini!Avendone solo 40 a disposizione si doveva inventare qualcosa: per recuperare spazio 16 sono stati destinati sia a tutte e 16 le linee del bus dati che alle prime 16 (su 20) linee del bus address.

12

Page 13: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

Per questo già con il processore successivo (descritto nella prossima pagina) la struttura del suo contenitore è cambiata da DIP (Dual InLine Package) a 40 pin alla più capiente PLCC (Plastic Leaded Chip Carrier) o PGA (Pin Grid Array), da 68 pin, più che sufficienti per ospitare tutti i segnali necessari.Ma torniamo al nostro 8086: la presenza su quei piedini (AD0 - AD15) di segnali così diversi non può essere contemporanea, per cui il processore pone su di essi, in tempi diversi, prima la parte bassa dell'indirizzo necessario e poi il dato a 16 bit.Il problema è ora scaricato sulle spalle del progettista che si trova nella necessità di memorizzare l'indirizzo poco dopo la sua apparizione sul bus, per mantenerlo stabile e visibile anche quando sarà sostituito dal dato da coinvolgere con la  memoria o con il dispositivo di I/O corrispondente a quel indirizzo; per questa operazione è indispensabile un segnale di controllo, ALE (Address Latch Enable), che entra in gioco nel seguente modo:

il processore porta ALE a 1 (a riposo questo segnale vale 0) e subito dopo mette su AD0 - AD15 l'indirizzo che, con le rimanenti linee "libere", AD16 - AD19, punta la locazione (o il dispositivo) desiderata.

quando l'indirizzo è stabile sul suo bus, il processore porta ALE a 0: questo fronte di discesa dovrà essere utilizzato per memorizzare localmente (per esempio con 2 74LS374) il numero a 16 bit dell'indirizzo.

poco dopo (con ALE sempre a 0) leva l'indirizzo dal bus e mette al suo posto il dato, attivando quasi contemporaneamente WR, cioè portandolo a 0 dallo stato di riposo, 1.

dopo qualche istante riporta prima WR a 1 e poi toglie anche il dato, sperando che la memoria abbia avuto il tempo di riceverlo...Quello ora descritto è un ciclo di scrittura memoria e, per tutto il tempo necessario (circa 4 cicli di clock), il segnale MEM/IO è stato tenuto a 1.Poichè lo scopo del Tutorial è quello di imparare a programmare questi preziosi oggetti, non ritengo opportuno continuare nella descrizione degli altri segnali di controllo; se si presenterà l'occasione magari potremo riparlarne nella Sezione Hardware, progettando l'intera struttura...

Il Pin-Out della CPU 80286Prima di passare ai dettagli funzionali del processore 8086 desidero mostrare la struttura esterna del 80286; il limitato contenitore DIP (Dual InLine Package) a 40 pin ha lasciato il posto al più capiente PLCC (Plastic Leaded Chip Carrier) o PGA (Pin Grid Array), da 68 pin.Ora i piedini sono disposti su 4 lati (17 per ogni lato del quadrato) e sono sostanzialmente tutti quelli già notati nel pin-out dell'8086.Notiamo, in particolare, la presenza di 4 linee in più per il bus address, mentre il bus dati è ancora a 16 bit; comunque ciascuno di essi ha la propria dignitosa autonomia e il fastidioso procedimento di memorizzazione illustrato al termine della pagina precedente, non è ora più necessario.

13

Page 14: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

Anche in questo caso evitiamo coscientemente ogni descrizione legata a problemi Hardware, rimandando gli appassionati ai manuali di elettronica o ... a tempi migliori

GeneralitàAbbiamo visto, nelle pagine precedenti, non a caso, l'aspetto funzionale di 2 storici processori, 8086 e 80286; 2 oggetti ancora a misura d'uomo...Oggi le case produttrici, come Intel (per la classe dei Pentium o Celeron) o la Advanced Micro Devices (AMD, per gli Athlon o Duron), fanno a gara per superarsi e conquistarsi una fetta di un mercato sempre più frequentato.Per onore di completezza dobbiamo citare anche la Cyrix, una società della National Semiconductor che, talvolta in collaborazione con l'IBM, ha prodotto processori ben presto soffocati dalla esuberante presenza delle altre 2 case produttrici.Le architetture moderne sono sempre più potenti e veloci, attente alle sempre più esose richieste degli applicativi; basti pensare alla moderna esigenza delle animazioni e post-produzioni largamente impiegate nella cinematografia...Dopo tutto, come detto all'inizio di questa serie di lezioni, anche nell'ambiente domestico si comincia a considerare il computer come un frigo o una lavastoviglie, forse un po' più divertente da usare ma pur sempre un potente strumento di lavoro e di svago..Dunque: il processore è il cuore pulsante del tuo Computer e abbiamo imparato che, comunque, da solo non saprebbe come cavarsela......tanta energia potenziale repressa e inutilizzabile; vediamolo ora un po' più da vicino.La rete è abbastanza generosa di siti che si occupano di processori dal punto di vista storico o di attualità; per questo trovo inutile ritagliarmi uno spazio che è già soddisfacentemente occupato da altri; desidero segnalarne almeno uno (Lithium.it), molto attento nel proporre un dossier sulla storia dei processori x86 veramente interessante e dettagliato.Le CPU passate, presenti e future sono effettivamente oggetti unici, caratterizzati da una personale unica architettura; ma al lato pratico sono chiamate a compiere tutte il medesimo lavoro: leggere ed interpretare numeri binari per eseguire pochi, semplici, compiti: operazioni aritmetiche (somme, differenze, prodotti...), operazioni logiche (and, or, xor...), operazioni "decisionali" (verifica dei risultati precedenti, al fine di prendere decisioni).

14

Page 15: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

E' interessante capire che il processore potrà prendere decisioni solo binarie, e lo farà sempre saltando da un punto ad un altro della memoria di programma; in altri termini: "esegui un sottoprogramma se il risultato è 1, oppure un altro sottoprogramma se il risultato è 0.Da tempo le CPU sono dotate di processore matematico, in grado di interpretare ed eseguire istruzioni specializzate, orientate al calcolo numerico in virgola mobile, Floating Point, mentre solo recentemente sono state integrate con circuiti specializzati nell'elaborazione di dati multimediali, cioè di tipo audio e video, a loro volta destinati ad interpretare il set delle istruzioni MMX (MultiMedia eXtension).La scelta di un Computer è spesso legata alla CPU che lo controlla; sebbene (come detto..) tutti sappiano tutto, martellati da recensioni e benchmark (test realizzati per misurare l'efficienza dei processori) di ogni tipo, il confronto tra processori, pur a parità di caratteristiche, rimane comunque difficile perchè fortemente influenzato dal tipo di lavoro che si andrà ad eseguire (basti pensare alla grande necessità di risorse necessarie in grafica o nell'esecuzione dei moderni giochi, piuttosto che il tranquillo tran tran di un ufficio..)In ogni caso la scelta va fatta e la conoscenza delle caratteristiche principali di una CPU, può aiutare; la tabella seguente raccoglie quelle già viste nelle pagine precedenti, integrata con qualche ulteriore informazione:

ProcessoreAnno Numero

TransistorRegister

SizeData

Bus SizeAddressBus Size

MemoriaMax

Bus Speed(in MHz)

Clock Max(in MHz)

NumeroPiedini Contenitore micron

8088 1979 29.000 8 bit 8 bit20 bit 1  Mbytes

5-840 DIP 3

8086 1978 29.000 16 bit 16 bit 5-10

80188 1982   8 bit 8 bit20 bit 1  Mbytes

5-1068 PGA 3

80186 1982   16 bit 16 bit 6-10

80286 1982 134.000 16 bit 16 bit 24 bit 16  Mbytes 6-20 68 PGA - PLCC 1.580386SX 1985

275.00032 bit 16 bit 24 bit 16  Mbytes 16-33

132 DX-PGA 1.580386DX 1988 32 bit 32 bit 32 bit 4  Gbytes 16-4080486DX 1989 1.200.000

32 bit 32 bit 32 bit 4  Gbytes

33 25-50 168 PGA 180486SX 1991 1.185.000 25 16-33 196 PQFP 1

80486DX2 1992 1.200.000 25-33 50-66168 PGA

0.880486DX4 1994 1.600.000 25-33 75-100 0.6

Pentium1993 3.100.000

32 bit 64 bit 32 bit 4  Gbytes 6660-100

273 PGA0.8

1996 3.300.000 120-200 0.35Pentium Pro 1995 5.500.000 32 bit 64 bit 36 bit 64  Gbytes 66 150-200 296 SPGA 0.6

Pentium MMX 1997 4.500.000 32 bit 64 bit 32 bit 4  Gbytes 66 166-233 321 SPGA 0.35

Pentium II1997

7.500.000 32 bit 64 bit 36 bit 64 Gbytes66 233-300

370 BGA6150.35

1998 100 266-450 0.25Celeron 1999 7.500.000 32 bit 64 bit 36 bit 64  Gbytes 66 266-533  370 PGA370 0.25

Pentium III1999 9.500.000

32 bit 64 bit 36 bit 64 Gbytes100-133

450-600370 FC-PGA

0.251999 28.000.000 533-1130 0.182001 44.000.000 133 1000-1400 0.13

Celeron SSE2000 28.000.000

32 bit 64 bit 36 bit 64 Gbytes66 533-1100

 370 FC-PGA0.18

2002 44.000.000 100 1000-1300 0.13

Pentium IV2001 42.000.000

32 bit 64 bit 36 bit 64 Gbytes 2661300-2000 423

FC-PGA20.18

2002 55.000.000 1600-2200 478 0.13

15

Page 16: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

Le scelte

La presenza di una Cpu piuttosto di un'altra è spesso legata ai criteri della scelta del Computer da essa controllato; con un occhio ai numeri della Tabella della pagina precedente è facile, ora, tentare una classificazione di massima delle Cpu, sulla base delle sue caratteristiche principali.Al di là dei dati tecnici, per altro importanti, è interessante notare la vera chiave di lettura dell'evoluzione di questi oggetti straordinari: il livello di integrazione dei microcircuiti interni, misurata in micron (1μm = 10-6 m = un millesimo di millimetro) e indicata dall'ultima colonna a destra della Tabella proposta nella pagina precedente.Con l'evolversi della tecnologia e delle tecniche di integrazione i percorsi dei collegamenti interni si riducono anno dopo anno, rendendo possibili frequenze di clock sempre più elevate, e consentendo inoltre l'inserimento di un maggior numero di transistor Cmos (Complementary Metal Oxide Semiconductor) sul chip del microprocessore.Come abbiamo detto in molte altre occasioni il futuro ci riserverà imprevedibili piacevoli sorprese!Dunque un primo parametro è la frequenza di clock: a prima vista sembra il numero più emblematico per stabilire l'effettiva velocità del computer, anche se è bene essere consapevoli che quest'ultima è fortemente influenzata anche da altri, tra i parametri elencati in questa analisi.Il clock (orologio, anche se la traduzione non è altrettanto snella e ...onomatopeica, come l'originale inglese) è l'incubo e la vita di una CPU: i circuiti che se ne occupano generano una forma d'onda quadra che, con i suoi fronti di salita e di discesa, punzecchieranno il processore per tutta la sua esistenza, scandendo e organizzando ogni sua azione; senza clock (nel senso di forma d'onda) il processore è inutilmente addormentato.La frequenza del clock è il numero delle ....punzecchiature al secondo, cioè il numero dei fronti di salita (o di discesa) che l'onda quadra fornirà alla CPU in ogni secondo; si misura in Herz (HZ, impulso al secondo) e, fin dai tempi della sua prima apparizione, è sempre stato dell'ordine del milione (1000000 Hz =1 MHz).Osservando la tabella della pagina precedente possiamo concludere che, da questo punto di vista, le moderne CPU sono 440 volte più veloci (2200 MHz) delle prime (5 MHz).Il processore organizza ogni sua operazione misurandola in cicli T, cioè in intervalli uguali al periodo della forma d'onda di clock: in pratica un tempo numericamente pari all'inverso del numero della frequenza.Ad una frequenza di 1 MHz corrisponde un ciclo T di 1 microsecondo; poichè per eseguire un'istruzione sono sempre necessari più di un ciclo T, si fa presto a concludere che una moderna CPU è in grado di svolgere milioni di operazioni al secondo!Anche questo può diventare un metro di misura, sebbene non molto popolare: l'unità di misura dei milioni di istruzioni eseguite al secondo è il MIPS, million of instructions per second.Un altro importante parametro di confronto è, come già accennato, la dimensione della sua parola, di solito uguale a quella dei suoi registri interni; l'unità di misura parola è per altro un modo improprio, tipico dei processori, di misurare l'informazione.In effetti l'informazione si misura, di solito, in bytes, per cui possiamo notare come nel tempo la parola sia raddoppiata, dai 2 bytes (16 bit) dei primi processori agli attuali 4 bytes (32 bit).Poichè la dimensione e la velocità del bus dati rappresenta la quantità di informazione che può essere scambiata simultaneamente è facile pensare che possa costituire un buon metro di confronto; il bus dati (esterno) degli attuali processori è di 64 bit e la sua velocità è, di norma, ancora molto inferiore a quella del processore, attualmente al massimo 233MHz, anche se cominciano a farsi strada i primi bus a 533MHz..

La Memoria Cache

Anche la memoria cache (=ripostiglio) presente su un computer può costituire un elemento di scelta, consapevoli che nessun computer può, oggi, farne a meno.Il problema nasce dal fatto che, sebbene il processore abbia velocità di elaborazione galattiche (dell'ordine del GHz, quella di clock), la memoria di sistema lavora con velocità decisamente inferiore, quella del bus (attualmente 233MHz .. tendenti ai 533MHz).Quando la veloce CPU è chiamata ad elaborare dati è, quindi, costretta ad aspettare che questi arrivino, con comodo..., dai suoi lenti bus e dalla sua lenta memoria esterna di sistema; in questo modo le prestazioni complessive degradano inevitabilmente..Per questo è stata inventata la cache memory, che trova posto tra il primo e la seconda; si tratta di una memoria di piccole dimensioni ma particolarmente veloce; la sua velocità può variare infatti da quella di clock (se di primo livello) a valori comunque superiori a quella del bus.Il trucco consiste nel pre-caricare in cache il maggior numero possibile di istruzioni (o meglio, di codici operativi e di bytes di dato) che il processore prevede di eseguire in una determinata sessione di lavoro; non appena la CPU tenta di comunicare con la sua memoria esterna i dati richiesti (e una buona parte di quelli vicini ad essi) sono trasferiti nella cache.

16

Page 17: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

In questo modo, almeno nell'immediato e con sufficiente probabilità, la CPU troverà in essa anche i dati necessari in seguito, senza dover attendere troppo.Naturalmente prima o poi capiterà che il dato o il codice operativo (dopo un salto o una chiamata di procedura) richiesti non siano nella cache: in questo caso la CPU sarà comunque costretta ad accedere normalmente alla lenta Ram di sistema posta sul bus.Una delle ragioni della diversa velocità dei 2 tipi di memoria è di tipo tecnologico:

la cache memory è fatta con circuiti elementari a transistor bipolari ed è nota come SRAM (RAM Statica); per questo è molto veloce (meno di 2ns, più di 500MHz) ma relativamente piccola (il valore tipico è di 256kBytes÷512kBytes, fino ad un massimo di 2MBytes) e più costosa.

la memoria centrale di sistema è la Ram per antonomasia, molto semplice dal punto di vista costruttivo; è nota come DRAM (RAM Dinamica) e, di solito, presente in grande quantità (32MBytes, 64MBytes, 128MBytes e via raddoppiando..) e soggetta alla velocità del bus (alcuni esempi: 15ns/66MHz, 10ns/100MHz, 7.5ns/133MHz, 3.75ns/233MHz).Fin dalle prime architetture è stata prevista la presenza di cache tra CPU e memoria, direttamente sulla scheda madre e, data la grande efficienza di questo meccanismo, ben presto si è pensato di introdurre parte di essa addirittura dentro il processore; per velocizzare lo scambio di dati tra memoria e processore sono oggi disponibili:

la cache di 1° livello, non grandissima (da 8kBytes fino a 64kBytes) ma funzionante con la stessa velocità (clock) del processore che la ospita.

la cache di 2° livello, posta la cache di 1° livello (dentro la CPU) e la relativamente lenta RAM esterna; la sua dimensione tipica è di 256kBytes e, sebbene all'inizio come detto fosse allocata sulla scheda madre, nei moderni processori è loro parte integrante (come la cache di 1° livello); in questo caso la sua velocità pari a quella del processore (clock) e, comunque, sarà inferiore a quella del bus, a seconda del tipo di architettura.

La presenza della Cache Memory rende molto più rapida l'esecuzione dei programmi, dato che la CPU trova con buona probabilità i bytes che gli servono direttamente dentro se stessa (Cache di 1° livello) e nelle sue immediate vicinanze (Cache di 2° livello), senza essere costretta a perdere tempo per indirizzare ed aspettare risposta dalla lenta Ram convenzionale esterna.

Vale la pena ricordare che l'aumento della cache produce aumento di prestazioni, anche se non direttamente proporzionale e comunque subordinato al caso (per altro piuttosto probabile) di contenere dentro di sè i dati necessari alla CPU.Poiché i suoi costi sono intrinsecamente elevati, la tendenza dei produttori è quella, piuttosto, di rendere le frequenze del bus (e delle memorie DRAM convenzionali) sempre più simili a quella di clock.

All'accensione...

Il microprocessore governa con autorità e precisione tutto quello che gli è sottoposto; ma riflette sempre e comunque il nostro pensiero (con buona pace per il vecchio HAL...).La prima cosa che fa è ...cercare qualcosa da fare; il processore non è nulla se non ha un programma da eseguire.La sua bocca è il bus dati, la sua parola sono i numeri binari che vi sono coinvolti; attraverso il bus dati passa di tutto...e con frequenza allucinante: miliardi di informazioni al secondo, dati o ordini da eseguire.Dunque il microprocessore aspetta comunque nostri ordini e li esegue con assoluta fiducia: se i nostri ordini sono errati produrrà risultati incoerenti e potrebbe anche farci pagare la nostra leggerezza...Naturalmente gli ordini devono essere espressi nella lingua del processore e fatti trovare in un punto ad esso accessibile; per cui saranno dei bytes (numeri binari) e dovranno essere predisposti in memoria!Questo meccanismo va affrontato con alcune premesse:

in primo luogo il processore viene attivato con l'accensione del computer nel momento dell'accensione tutto è ancora precario e inospitale: il sistema operativo non è ancora

disponibile, sullo schermo appare qualche fugace frase bianca in campo nero e, dopo qualche secondo di ...sferragliamenti di vario tipo, appare la confortante immagine di sfondo, con tutte le sue ridenti iconcine.

se all'accensione non c'è sistema operativo che fa il processore? E perchè, nonostante tutto, il processore lo trova e lo attiva?

All'accensione la memoria è vuota... (sembra non ci sia nulla da fare...). Ma non tutta!La maggior parte di noi ritiene (a ragione) che la memoria sia quella che ci viene dichiarata all'atto dell'acquisto del computer (la famosa PC100, o PC133, o DDR, per rimanere nell'ambito del gergo corrente); in sostanza, la RAM!

17

Page 18: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

Questa memoria, se disalimentata, perde il suo contenuto, senza rimedio, e quindi ogni volta che il computer viene acceso non può contenere nulla; dunque la CPU, almeno all'inizio, non può contare sul contenuto di questa memoria.

Ma il processore DEVE eseguire qualcosa, all'accensione.Per sopperire a questa lacuna i suoi progettisti hanno pensato ad un machiavellico trucco: il processore è forzato a leggere una piccolissima memoria indelebile, sempre presente insieme ad esso sulla scheda madre; si tratta della famigerata BIOS, una memoria a sola lettura (ROM) che, nel gergo, ha assunto il nome del programma che contiene (appunto il Basic Input Output System).La (o il...) BIOS contiene tutte le procedure necessarie per predisporre al meglio il computer e per garantirgli autonomia operativa; tra queste la procedura di bootstrap, esattamente la prima cosa che qualunque processore si trova ad eseguire!

Il processore, non appena viene attivato dall'accensione del computer, esegue un programma (cioè una sequenza di bytes operativi) detto di bootstrap, che oltre ad eseguire un primo controllo di efficienza, ha il compito di cercare il sistema operativo (per esempio Windows) sulla memoria di massa (HD) e di trasferirlo nella memoria centrale (RAM). 

Per inciso il termine boot-strap (mediato da vetuste applicazioni elettroniche) letteralmente starebbe per "tirarsi su per le stringhe delle scarpe",  magicamente "alzarsi da terra" tirando verso l'alto le stringhe delle proprie scarpe.Si tratta di un'altro esempio della creatività espressiva anglosassone; il computer "si tira su" (parte, comincia a fare) passando dalla condizione di morte apparente a quella di prorompente vitalità (per intercessione del processore e del suo primo cibo, il BIOS).Quando il Sistema Operativo è stato trasferito in RAM il processore smette di eseguire il programma (di bootstrap) in BIOS e viene obbligato a saltarci dentro, trovandosi ora ad eseguire un altro programma (appunto il SisOp) in RAM, in attesa dei nostri comandi!

I Registri – PremesseLa struttura interna di un processore è relativamente complessa ma la logica che lo governa rende facile la comprensione delle sue parti; nelle pagine successive analizzeremo in dettaglio lo schema funzionale (architettura) del glorioso 8086, nostro punto di riferimento per la futura fase della programmazione in Assembly.Possiamo anticipare che ogni processore è costituito essenzialmente da 2 parti, rispettivamente specializzate nella gestione dei dati  (interfaccia con i bus) e nella loro elaborazione (unità di esecuzione); in entrambe entrano pesantemente in gioco i suoi Registri interni, una struttura tra le più importanti e tipiche di una CPU.Per questa ragione è conveniente descriverli  e conoscerli dettagliatamente, al fine di rendere più agevoli le analisi proposte nelle pagine future.Un microprocessore è chiamato ad elaborare informazioni assunte dall'esterno e, per poterlo fare ha bisogno di un suo taccuino d'appunti personale: chiunque di noi memorizza sulla carta gli operandi di una addizione e poi diligentemente ne somma le cifre in colonna, fino a ricostruire il risultato, su una riga sottostante...Il processore (... fatto a immagine e somiglianza del suo creatore) non è da meno: ha bisogno di memorizzare temporaneamente gli operandi dentro di se, in attesa che qualcuno li prenda in considerazione e ricostruisca il risultato dell'operazione richiesta.Le locazioni di memoria personali del processore hanno il nome di Registri.

I Registri sono locazioni di memoria ultraveloci (hanno la velocità del clock) in stretto contatto con tutte le altre parti della CPU a cui appartengono, con le quali interagiscono al fine di elaborare i dati pervenuti o organizzare il loro smistamento.

Dunque i registri sono una risorsa di enorme valore, anche come semplice deposito dati: il programmatore assembly (... cioè noi) può disporre di punti di memorizzazione direttamente sul posto della loro elaborazione, in alternativa a quelli classici disponibili in RAM; è chiaro che il dato di un registro è disponibile subito, mentre quello della RAM deve essere da essa prelevato e portato dentro, con notevole differenza sui tempi d'esecuzione.Purtroppo il loro numero è piuttosto piccolo (non ce n'è mai abbastanza, .. vecchio piagnisteo dei programmatori...) ma con una saggia amministrazione ed un corretto utilizzo la programmazione non può che trarne grande vantaggio.Il controllo dei registri si esercita attraverso le istruzioni , per esempio quelle di scambio (come  MOV AL,AH ) o quelle aritmetiche (come  ADD AX,BX ) o quelle logiche (come  XOR DI,SI ); la conoscenza del set delle istruzioni aiuta ad usare bene i singoli registri, al fine di accoppiarli ai compiti per i quali sono meglio predisposti.

18

Page 19: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

I Registri sono, di norma, specializzati, cioè sono in grado di compiere al meglio certe operazioni anziché altre; usare un registro diverso da quello specializzato non vanifica l'operazione (istruzione) desiderata ma la rende meno efficiente e più costosa, nel senso che il programma finale avrà tempi d'esecuzione più elevati ed occuperà più spazio in memoria).

Il numero e la dimensione dei registri si sono evoluti con la storia dei processori, come la disponibilità di nuove istruzioni; di norma la dimensione di un registro è quella del bus interno della CPU alla quale appartengono. In contrapposizione con i registri a 16 bit del patriarca 8086 (che cominceremo a conoscere tra poco...) vanno tenuti nel dovuto conto quelli a 32 bit delle ultime generazioni. In ogni caso i vecchi registri a 16 bit sono ancora perfettamente riconosciuti e ampiamente utilizzati nella programmazione; nelle nuove architetture sono da ritenersi un sottoinsieme dei nuovi (più esattamente la loro parte bassa).Per questa ragione lo studio e l'utilizzo dei registri a 16 bit rimane del tutto legittimo e didatticamente valido: spetterà al lettore sperimentare le nuove istruzioni a 32 bit (certamente più potenti e, forse, un po' più impegnative) al termine degli esperimenti condotti e suggeriti da questo Tutorial.Nelle pagine successive spingeremo a fondo la conoscenza dei 14 gloriosi registri a 16 bit dell'8086.

I Registri di uso Generale

Siamo pronti: questa è la prima vera interfaccia con la programmazione Assembly.Descrivere i Registri di una CPU e discuterne le istruzioni è un tutt'uno: i primi sono spesso gli operandi delle seconde... e le seconde tendono a specializzare l'uso dei primi.Come d'accordo per pura opportunità e per precisa scelta didattica (probabilmente discutibile, ma adottata da tutti i docenti, almeno all'inizio) prenderemo in considerazione i 14 registri a 16 bit dell'8086; il passaggio allo studio e all'uso di quelli a 32 bit sarà comunque indolore e immediato.

I primi sottoposti a esame sono i 4 registri di uso generale (General Purpose Registers); il loro nome è AX, BX, CX e DX ed hanno tutti la caratteristica di poter essere utilizzati così come sono definiti (cioè a 16 bit) o in 2 metà a 8 bit.Naturalmente il loro impiego nell'una o nell'altra dimensione dipende dal contesto, cioè dall'istruzione che li coinvolge; nel secondo caso i nomi dei registri a 8 bit conservano l'iniziale di quello che li contiene, seguita dalla lettera L o H, rispettivamente per la parte bassa (Low) e alta (High) del registro a 16 bit da cui hanno origine.Sebbene la cosa sia, al lato pratico, del tutto irrilevante la loro lettera iniziale può essere interpretata come iniziale del compito che al registro riesce meglio, cioè:

AX, Accumulatore: si tratta del registro più coinvolto dal set delle istruzioni e nessuno come AX è altrettanto efficiente; il suo nome è storicamente associato all'immagine di colui che prende su di se (accumula) il maggior carico di lavoro; in concreto è coinvolto per default in alcune importanti istruzioni:

aritmetiche: come  MUL ,  IMUL,  DIV,  IDIV, nelle quali rappresenta in ingresso il moltiplicando e il dividendo e in uscita il risultato

di spostamento dati dalla e verso la memoria, come  LODSB  (equivalente a  MOV AL,DS:[SI] ) e

 STOSB  (equivalente a  MOV ES:[DI],AL) di uso particolare (come  IN AL,DX  o  OUT DX,AL , nelle quali costituisce rispettivamente il

registro destinazione e sorgente dei dati da scambiare con dispositivi di Input/Output).

19

Page 20: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

Le sue metà a 8 bit sono AL e AH; le variazioni di ciascuna di esse influenzano ovviamente il contenuto di AX.

BX, Base: il suo nome deriva dal fatto che, unico tra i 4 registri di uso generale, può essere usato istituzionalmente come puntatore; le istruzioni che utilizzano questa tecnica sono, per esempio:

quelle di puntamento diretto, come  MOV AL,DS:[BX] . quelle di puntamento appunto con registro base, come  MOV AL,DS:[SI+BX+00] , di solito con

l'aiuto di un registro indice e di uno spiazzamento. Le sue metà a 8 bit sono BL e BH; le variazioni di ciascuna di esse influenzano ovviamente il

contenuto di BX. CX, Contatore: il suo nome deriva dal fatto che numerose istruzioni lo utilizzano per default come

contatore di eventi; tra esse: tutte quelle che consentono il prefisso  REP , il compito del quale è proprio di ripetere l'istruzione

fino a quando in registro CX, decrementato ad ogni giro, raggiunge il valore zero. l'istruzione  LOOP , e le sue simili, nelle quali fa da contatore dei cicli eseguiti: il ciclo viene

ripetuto fino a quando CX, decrementato ad ogni giro, raggiunge il valore zero. Le sue metà a 8 bit sono CL e CH; le variazioni di ciascuna di esse influenzano ovviamente il

contenuto di CX. DX, Data: il suo nome vuole rimarcare la generica disponibilità ad essere usato per memorizzare dati; in

realtà anche per questo registro esistono istruzioni che gli riservano un uso di default; tra esse: alcune aritmetiche, come  MUL ,  IMUL,  DIV,  IDIV, nelle quali, quando l'operando è una word,

rappresenta la parte alta del risultato. nelle istruzioni di Input/OutpuT, come  IN AL, DX  o  OUT DX,AL , nelle quali rappresenta

l'indirizzo del dispositivo periferico. Le sue metà a 8 bit sono DL e DH; le variazioni di ciascuna di esse influenzano ovviamente il

contenuto di DX.E' bene sottolineare che i 4 registri di uso generale, AX, BX, CX e DX, possono tranquillamente essere usati nel modo più diverso e libero; tuttavia se si desidera ottimizzare il proprio codice è saggio tener conto delle indicazioni suggerite, riservando a ciascuno di essi il compito che meglio lo realizza.Solo per completezza, a partire dal 80386 sono disponibili registri a 32 bit; i 4 registri di uso generale sono detti EAX, EBX, ECX e EDX, e quelli descritti in questa pagina sono ancora riconosciuti come loro parte bassa.

I Registri di Segmento - Indirizzi Logici e Indirizzi Fisici

Il processore 8086 prevede 4 registri di segmento (Segment Registers); il loro nome è CS, DS, ES e SS, tutti a 16 bit, indivisibili.Il concetto di segmento è presente in moltissime pagine di questo sito per cui un link univoco all'argomento sembra impossibile; è più semplice ribadire che si tratta di un'area di memoria di 65536 (64k) locazioni consecutive, utilizzata dal sistema per allocare i programmi, in attesa di ceder loro il controllo.A questo proposito è utile leggere l'argomento Come viene trattato il file EXE dal Loader del DOS del Capitolo 2, che sottolinea come una importante caratteristica dei files EXE consiste nel poter disporre di una quantità di memoria grande fino a 4 segmenti, di solito, associati al codice (e puntati con CS), allo stack (SS), ai dati (DS) e ad altri dati extra (ES).Risulta comunque chiaro che i registri di segmento servono per individuare le rispettive aree da 64k, nelle quali si svolgono attività vitali per la vita dei programmi in esecuzioneUn altro concetto chiave legato a questi registri è quello di indirizzo logico e indirizzo fisico. Il problema è sorto fin dall'inizio: i progettisti dell'8086 si sono trovati a gestire un bus d'indirizzi di 20 linee con registri a 16 bit; in pratica era evidente la necessità di porre un indirizzo valido sul rispettivo bus ma non era possibile farlo perchè gli strumenti a disposizione (registri) erano troppo piccoli.Da questa esigenza è nata la tecnica della segmentazione della memoria, un abile sotterfugio per poter puntare ogni indirizzo con 2 registri a 16 bit:

il primo (detto appunto registro di segmento) individua un'area di 64kBytes consecutivi, dentro lo spazio indirizzabile del processore, ed è uno di quelli descritti un questa pagina.

il secondo (detto registro di offset) è in grado di scorrere ciascuna delle 65536 locazioni contenute nel segmento, in virtù dei diversi possibili valori che può assumere (essendo a 16 bit, 216=65536=64k), ed è uno di quelli descritti della pagina seguente (per poter continuare la descrizione ne prenderemo in prestito uno, il registro puntatore d'istruzione IP).

20

Page 21: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

Dunque con un indirizzo logico, cioè con una coppia di registri di tipo Segment:Offset, per esempio CS:IP (notare la forma con cui si esprime l' indirizzo logico) è possibile ottenere un indirizzo fisico; basta imparare il meccanismo che la CPU usa, internamente, per ricostruirlo.

L'indirizzo fisico (cioè il numero binario a 20 bit che sarà posto sul bus address) si ottiene sommando il valore di un registro di segmento moltiplicato per 16 con il valore di un registro di offset; la coppia di registri a 16 bit coinvolta nell'operazione può essere messa in evidenza nella forma Segment:Offset, cioè nella forma tipica di un indirizzo logico.

Da notare che, per rendere leggibili gli indirizzi (sia fisici che logici), è prassi comune accorpare i bit a 4 a 4, sostituendo ogni quaterna con un simbolo del sistema di numerazione esadecimale:

tali simboli sono sedici (appunto exadeci..): i numeri da 0 a 9 e le lettere da A a F ciascuno di essi è dunque codificato da 4 bit (cioè è codificato dall'unità di misura logica detta nibble = 4

bit) così per esempio 00010010010001000000 (numero assurdamente illeggibile, espresso in binario)

diventa 12440, espresso in esadecimale per distinguere con certezza il tipo di codifica utilizzato per esprimere l'informazione si aggiunge una H

(per Hexad...), cosicché 00010010010001000000 (binario) = 12440H (in esadecimale)Lo schema seguente mostra questa tecnica: si osserva che moltiplicare per 16 significa aggiungere a destra del valore esadecimale del registro di segmento 4 bit di valore nullo (un nibble uguale a 0):

   Indirizzo fisico (20 bit) = Registro di Segmentox16+Registro di Offset   

  Se CS=1234H e IP=0100H dall'indirizzo logico CS:IP si ricava l'indirizzo fisico:

        CS*16 +  1234H*10H +  12340H +       IP =      0100H =   0100H =

   ----------------------------------  indirizzo fisico >>>   12440H

Va sottolineato che, per ogni indirizzo fisico, i valori dei 2 registri Segment:Offset che concorrono a definire l'indirizzo logico possono assumere numerosissime combinazioni (in pratica ben 65536..); lo schema seguente mostra altre 5 possibilità:

 10000H +  2440H =--------- 12440H

 11110H +  1330H =--------- 12440H

 12000H +  0440H =--------- 12440H

 11FF0H +  0450H =--------- 12440H

 12440H +  0000H =--------- 12440H

La scelta dei valori da associare ai 2 registri è dunque del tutto irrilevante; personalmente preferisco quella proposta per ultima, nell'esempio precedente, che lascia nel registro di offset un numero 0000H e in quello di segment la parte rimanente: è la proposta più vicina alla logica della memoria segmentata, nella quale l'offset punta l'inizio (0000H) del segmento a sua volta puntato dal segment (1244H).Per facilitare l'esercizio mentale legato a questa conversione è disponibile l'eseguibile Calcola.COM, che puoi scaricare o eseguire cliccando qui .Dei registri di offset parleremo nella pagina successiva; in questa riassumiamo i compiti dei 4 registri di segmento; di solito è il Loader (caricatore dei programmi in memoria) del Sistema Operativo che si occupa di caricare in questi registri i valori corretti per l'esecuzione del programma stesso:

CS, Code Segment: punta l'area di 64k destinata a contenere i bytes del codice eseguibile, la traduzione in linguaggio macchina delle nostre istruzioni; in ogni momento (insieme a IP, come vedremo) punta il codice operativo dell'istruzione che sta per essere eseguita. Non esistono istruzioni per cambiarne direttamente il valore, sebbene la cosa sia possibile, in modo indiretto, correttamente con  JMP ,  CALL o  RET  e impropriamente (e a rischio) con la coppia  PUSH rS / POP CS . Se si desidera avere una copia del valore di CS, per esempio in AX, possiamo usare senza danno la sequenza di istruzioni  PUSH CS / POP AX .

SS, Stack Segment: punta l'area di 64k destinata a contenere i bytes destinati allo stack, l'area nella quale il processore annota gli indirizzi a cui tornare in caso di esecuzione di  CALL o  INT ; in ogni momento (insieme a SP, come vedremo) punta la prima locazione disponibile ad essere utilizzata. Modificare il valore di questo registro è assurdo e sconveniente: il risultato è il probabile crash del programma in esecuzione (se non del computer stesso).

DS, Data Segment: punta l'area di 64k destinata a contenere i dati del programma in esecuzione e può

21

Page 22: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

essere modificato senza rischio dal programmatore, per esempio con la sequenza di istruzioni  MOV AX,nnnnH / MOV DS,AX  o con la coppia  PUSH AX / POP DS ; numerose istruzioni danno per scontato che questo sia il registro di segmento delle locazioni sorgente ( MOVS ,  LODS ) dei dati da esse trattati.

ES, Extra Segment: punta l'area di 64k destinata a contenere i dati del programma in esecuzione (oltre a quelli puntati da DS) e può essere modificato senza rischio dal programmatore, per esempio con la sequenza di istruzioni  MOV AX,nnnnH / MOV ES,AX  o con la coppia  PUSH AX / POP ES . Di solito è utilizzato per puntare particolari zone di memoria: la sovrapposizione di un segmento ad una determinata area ne facilita la gestione (si pensi per esempio alla RamVideo); numerose istruzioni danno per scontato che questo sia il registro di segmento delle locazioni destinazione  ( MOVS ,  STOS ) dei dati da esse trattati. Con l'avvento dei processori a 32 bit (cioè con bus dati interno, e quindi registri, a 32 bit), a partire dal 80386, i sistemi hanno cominciato a gestire la memoria con altre tecniche e il problema della segmentazione ha perso importanza; i registri di segmento sono utilizzati in 2 diverse modalità, dette real mode e protected mode.Il primo dei 2 modi (real mode, che si rifà alla descrizione appena conclusa) è comunque garantito, per assicurare portabilità verso il basso, e sarà da noi ampiamente utilizzato con soddisfazione, specialmente per puntare le locazioni del primo mega di memoria, straordinariamente ricco di informazioni e zone utili.Solo per completezza,  a partire dal 80386 sono disponibili altri 2 registri di segmento, GS e FS, comunque a 16 bit.

I Registri Puntatore e i Registri Indice

Il processore 8086 prevede 5 registri ufficialmente adatti a costituire la parte offset di un indirizzo logico; di solito sono distinti in registri puntatore (IP, SP e BP) e registri indice (DI e SI), tutti a 16 bit, indivisibili.Il concetto di offset è stato descritto nella pagina precedente: in sostanza, traducendo dall'inglese, significa spiazzamento, spostamento (distanza) da un punto iniziale, e rende bene l'idea del puntatore interno, in grado da individuare senza dubbi una qualunque delle possibili 65536 locazioni di un segmento.La definizione dei registri di offset non può essere disgiunta dall'accoppiamento con un registro di segmento, sebbene nessuno ci vieti di usare ciascuno di questi registri come semplice deposito dati a 16 bit.Come in occasione della definizione degli altri registri è comunque utile ricordare che esiste un modo proprio di utilizzarli, cioè con gli accoppiamenti suggeriti dal set delle istruzioni; con questo concetto ben presente vediamoli dunque uno per uno.Il registro puntatore IP (Instruction Pointer) fa coppia esclusiva con CS, e viceversa; una coppia assolutamente ...fedele.Il puntatore logico CS:IP è assolutamente indispensabile per la vita di ogni programma in esecuzione, essendo lo strumento (Program Counter) con il quale il processore punta il (primo) codice operativo dell'istruzione che sta per essere da lui eseguita.Si tratta dunque di un registro completamente gestito dal processore stesso, nel senso che non esiste istruzione che possa modificarne direttamente il valore; in condizioni normali viene aggiornato direttamente dalle logiche interne del processore durante l'esecuzione dell'istruzione da esso puntata: il numero dei suoi bytes viene semplicemente aggiunto al valore iniziale, cosicchè IP, al termine dell'esecuzione, si ritrova correttamente a puntare l'istruzione successiva.In modo indiretto (ma sempre per intervento del processore) il suo valore può essere cambiato anche radicalmente dall'esecuzione delle istruzioni JMP ,  CALL o  RET ; in nessun caso è conveniente manipolare in modo diverso il contenuto di questo registro.Il registro puntatore SP (Stack Pointer) fa coppia esclusiva con SS (sebbene, all'occorrenza, SS se la possa vedere anche con BP, che vedremo tra poco...).Il puntatore logico SS:SP è lo strumento con il quale il processore gestisce lo Stack, l'area di memoria nella quale annota gli indirizzi a cui tornare in caso di esecuzione di  CALL o  INT ; in ogni momento punta la prima locazione disponibile ad essere utilizzata.Anche questo registro è assolutamente indispensabile per la vita di ogni programma in esecuzione, e la sua modifica, pur possibile in modo anche esplicito, può rivelarsi sconveniente, se condotta con leggerezza e scarsa consapevolezza: i rischi di crash del programma in esecuzione (se non del computer stesso) sono molto elevati.Il registro è comunque gestito automaticamente dal processore in occasione dell'esecuzione di istruzioni che coinvolgono lo stack , come le coppie  CALL/ RET, INT/ IRET o  PUSH/ POP; in occasione di queste operazioni il valore del registro SP viene decrementato/incrementato di 2 bytes alla volta.Il registro puntatore BP (Base Pointer) fa coppia con SS ma non in assoluto.

22

Page 23: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

Il puntatore logico SS:BP è talvolta usato dal programmatore per puntare alcuni valori presenti nello stack: si tratta della tecnica di passaggio dei parametri tramite stack, molto frequente nei linguaggi di programmazione ad alto livello.E' facile capire che, intervenendo in un'area di memoria di solito riservata al processore, ogni operazione deve essere condotta con estrema attenzione, lasciando inalterato lo stato dei dati gestiti dal processore e soprattutto il puntatore ufficiale allo Stack, appunto SS:SP.Per questa ragione, sebbene tollerata, l'uso improprio dello Stack deve essere gestito con un secondo puntatore, SS:BP.Come ogni altro registro a 16 bit può, comunque, essere usato senza rischio anche in coppia con DS o ES, per puntare locazioni di memoria contenenti normali dati.I registri indice SI (Source Index) e DI (Destination Index) sono normali registri a 16 bit, sebbene il loro nome tradisca le funzioni alla quale il set delle istruzioni li destina.Le coppie di puntatori logici previste da numerose istruzioni del set sono DS:SI e ES:DI, rispettivamente utilizzate per puntare le aree di memoria da cui prendere (locazioni sorgente, come in MOVS ,  LODS ) e in cui mettere (locazioni destinazione, come in  MOVS ,  STOS ) i dati.Di solito queste potenti istruzioni provvedono anche a incrementare o decrementare il valore corrente di questi registri: poiché si tratta di operazioni piuttosto raffinate e impegnative si consiglia di consultarle direttamente nelle pagine ad esse dedicate.Per terminare ricordiamo che, comunque, è ammesso anche qualunque altro accoppiamento, che risulterà certamente meno efficace di quelli consigliati; entrambi i registri di segmento, DS e ES, possono essere usati in coppia con i registri di offset DI e SI, ma anche con BP e BX (quest'ultimo elevato al rango di puntatore).Solo per completezza,  a partire dal 80386 sono disponibili registri a 32 bit; i registri puntatori sono detti ESI, EDI, EBP, ESP e EIP, e quelli descritti in questa pagina sono ancora riconosciuti come loro parte bassa.In aggiunta citiamo alcuni tra i nuovi registri, introdotti nel tempo:

i 3 Control Register 80386:CR0, CR2, CR3. il Control Register Pentium:CR4. i 6 Debug Register 80386:DR0, DR1, DR2, DR3, DR6, DR7. i 5 Test Register 80486:TR3, TR4, TR5, TR6, TR7. i Model Specific Register Pentium: MSR. i Memory Type & Range Register PentiumPro: MTRR.

I  Registri delle Flag

La rassegna dei registri del processore 8086 termina con il registro dei flag (o, come piace a me, delle flag, pensando ad esse per quello che sono, delle bandiere); a qualcuno di noi verrà in mente qualche polveroso film di guerra, di quelli di propaganda, in bianco e nero..., con l'omino che, in mezzo alla pista d'atterraggio di una porta-aerei, si sbraccia con in mano 2 bandierine colorate per aiutare il pilota a non ...sfasciarsi sulla tolda...Ecco ... queste sono le (Maritime Signal) Flags da cui quei 4 mattacchioni di tecnici Intel hanno tratto l'idea e il nome: flag = segnalazione!Si tratta di uno strano registro a 16 bit, dall'impiego completamente diverso da tutti gli altri.Il suo contenuto non è da utilizzare nella consueta forma di word, ma in funzione del valore dei singoli bit in esso contenuti; dei 16 disponibili solo 9 sono significativi, mentre i rimanenti 7 sono inutilizzati. Di questi:

6 sono flag di stato, di solito influenzate dal risultato delle istruzioni aritmetico logiche. 3 sono flag di controllo, di solito controllabili da programma con opportune istruzioni dedicate.

Il compito di questo registro è straordinariamente importante: al lato pratico, il suo contenuto consente al processore di prendere decisioni!

Come abbiamo sottolineato in occasione della descrizione delle istruzioni di salto condizionato la CPU di solito decide saltando da una parte piuttosto che da un'altra.Il valore binario di una singola flag è dunque sufficiente per obbligare il processore ad eseguire un codice invece di un altro; ne consegue che non esistono (e sarebbero poco intelligenti) istruzioni che modifichino in blocco questo registro, sebbene sia possibile scriverlo (?!) o leggerlo da o in un altro registro a 16 bit con il solito trucco (per esempio: con  PUSHF/ POP AX  avremo in AX la copia esatta di tutti e 16 i bit).In ogni caso è possibile salvarne il valore nello stack (con  PUSHF ) o recuperarlo dallo stack (con  POPF ).In dettaglio ecco l'aspetto di questo registro; ciascuna delle flag in esso contenuta è da ritenersi settata se si trova al valore 1, e resettata se a 0:

15           

8 7           

0

23

Page 24: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

0 0 0 0 OF DF IF TF SF ZF 0 AF 0 PF 1 CF

Analizziamo lo scopo delle 6 flag di stato:

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).

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).

OF

(Overflow Flag, flag di Overflow): viene forzata a 1 se 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).

Parimenti vediamo lo scopo delle 3 flag di controllo:

TF

(Trap Flag, flag di Cattura): molto utile perchè, se  forzata a 1 (di solito con  INT 03H ) blocca nel punto predeterminato l'esecuzione di un programma in ambiente Debug; si presta dunque alla grande per l'esecuzione passo-passo (single-step) dei programmi.

IF

(Interrupt Flag, flag d'Interruzione Mascherabile): se forzata a 0 consente di disabilitare (mascherare) la possibile interruzione da parte di uno dei dispositivi abilitati a ciò; può essere controllata da software con  STI (che la forza a 1) o  CLI (che la forza a 0).

DF

(Direction Flag, flag di Direzione): indispensabile nella gestione delle stringhe ( MOVS , STOS o LODS ) per stabilire se i registri indice coinvolti (DI o SI) devono essere incrementati (DF=0) o decrementati (DF=1); può essere controllata da software con STD (che la forza a 1) o  CLD (che la forza a 0).

Solo per completezza, a partire dal 80286 sono disponibili 2 nuove flag e a partire dal 80386 altre 3; in questo ultimo caso anche questo registro (come gli altri) è a 32 bit, EFLAG, aumentando di conseguenza anche il possibile numero di flag:

31           

24 23           

1615

           8 7

          

0

0 0 0 0 0 0 0 0 0 0 0 0 0 0 VM RF 0 NT IOPL IOPL OF DF IF TF SF ZF 0 AF 0 PF 1 CF

Le nuove sono:

IOPL (I/O Privilege Level, livello di privilegio I/O), disponibile già con 80286, specifica (con i suoi 2 bit) uno dei 4 diversi livelli di privilegio richiesti nelle operazioni di input/output

NT (Nested Task Flag, flag di task annidato), disponibile già con 80286, controlla il funzionamento di una istruzione IRET ed è normalmente uguale a 0 in modo reale.

RF (Resume Flag, flag di ripresa) VM (Virtual Mode Flag, flag del modo virtuale)

24

Page 25: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

Architettura interna

Prima di tirare le somme vediamo lo schema funzionale dell'8086: la sua architettura è più che sufficiente per dare l'idea di cosa succede dentro una CPU, senza rischiare di perder d'occhio il nostro obiettivo con l'analisi di architetture più complesse.

Prima di proseguire cerca di non banalizzare questa figura; osservala con pazienza e cerca di memorizzare i suoi blocchi funzionali.L'analisi della figura mostra le 2 parti principali di una CPU:

alla prima (unità di interfaccia con i bus, Bus Interface Unit, BIU) è affidato il compito di acquisire e cedere i bytes da e verso l'esterno.

la seconda (unità di esecuzione, Execution Unit, EU) ha il compito di elaborarli e (se operativi) di eseguirli, e non ha alcun rapporto con l'esterno.Sulla base della figura precedente cerchiamo di capire come il nostro processore riesca ad assumere ed eseguire i bytes del programma che è chiamato ad interpretare.Vale la pena di ricordare che i programmi che un processore può eseguire non sono altro che una sequenza di bytes, freddi numeri binari da noi espressi (per nostra comodità) in esadecimale.

25

Page 26: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

Questi bytes sono di solito raccolti uno dopo l'altro nella memoria, puntigliosamente definita di programma (per distinguerla da quella usata, nell'ambito dell'esecuzione, per altri scopi, come lo stack o le tabelle di dati o variabili di vario tipo); la memoria di programma può essere la classica RAM ma anche la memoria a sola lettura (ROM) della scheda madre (BIOS) o della scheda video o di qualche altro dispositivo.Di sicuro c'è il fatto che il primo byte sarà sempre un codice operativo, cioè un byte che rappresenta un'istruzione da eseguire; ad esso potrà seguire un altro OpCode, ma anche uno o più bytes di dato, come succede per molte tra le possibili istruzioni che il processore è in grado di eseguire.Poiché un byte (8 bit) può assumere 256 (28) diversi valori può sembrare che un processore sia in grado di eseguire solo 256 diverse operazioni... troppo poche per le ambizioni di un buon processore; è questa la ragione per la quale le varie istruzioni sono spesso definite da più di un codice operativo.Già con 2 OpCode si possono potenzialmente codificare 65536 (216) diverse istruzioni, ora decisamente troppe; la verità sta nel mezzo: non tutte le combinazioni possibili dei bit dei codici operativi multipli corrispondono ad altrettante istruzioni!In pratica il rapporto tra CPU e istruzione da eseguire è piuttosto articolato:

l'istruzione non è dentro il processore (.. non ancora..): è conservata in memoria, sotto forma di uno o più bytes consecutivi.

il processore deve recuperare ciascun byte dalla memoria, ricostruendo l'indirizzo della locazione corrispondente, con l'aiuto del contenuto dei registri CS e IP.

solo quando l'informazione è dentro di lui può procedere all'interpretazione del codice operativo e dei suoi eventuali operandi, cioè all'esecuzione dell'istruzione.

in ogni caso il processore per fare questo dovrà attivare tutte le sue risorse per tradurre in fatti gli ordini ricevuti.Per comprendere in che modo ciò sia possibile dobbiamo imparare a conoscerlo intimamente; dobbiamo ...aprire la scatola magica!Come detto tutto il processo comincia nell'unità di interfaccia con i bus, Bus Interface Unit, BIU:

il suo primo compito consiste nella ricostruzione (con l'aiuto del suo sommatore interno) dell'indirizzo fisico a partire da quello logico, suggerito dal contenuto dei 2 registri puntatori di codice, CS:IP, con il meccanismo descritto in precedenza

non appena l'indirizzo è pronto e disponibile sul bus address interno la logica di controllo dei bus lo trasferisce anche su quello esterno, attivando anche le linee di controllo necessarie alla lettura di memoria.

dopo i tempi tipici della Ram di sistema (qualche nanosecondo) la memoria mette sul bus dati il codice operativo contenuto nella locazione richiesta e il processore, messosi istantaneamente in attesa subito dopo aver attivato le linee di controllo, lo cattura e lo mette nei registri della coda delle istruzioni, a disposizione della EU.Questa sequenza (compito della BIU) è nota con il nome di pre-fetch (fase precedente al prelievo del codice operativo); la BIU continua (in modo autonomo e distinto dalla EU) ad eseguire il pre fetch, ripetendo velocemente tutto da capo subito dopo aver incrementato il registro PC, e continuando a stoccare i bytes letti dalla memoria, uno dopo l'altro, nella coda delle istruzioni.In questo modo EU (che analizziamo tra un attimo) trova sempre bytes pronti ad essere eseguiti.

L'idea geniale per ottimizzare i tempi è la coda delle istruzioni: mentre la BIU si occupa di inserirvi i bytes letti dalla memoria la EU li estrae e li consuma traducendo in fatti il comando binario ricevuto. Fin tanto che la coda è piena si tagliano così i tempi morti.

Il vantaggio è reale solo se i bytes (prelevati dalla memoria e presenti nella coda) sono relativi ad istruzioni consecutive; se la EU è costretta ad eseguire istruzioni di salto, la BIU svuota completamente la coda e la riempie da capo con i bytes della sequenza di istruzioni che comincia al nuovo indirizzo, il chè costringe la EU ad attendere un po'...E' facile capire che questo processo trae enorme vantaggio dalla presenza di una cache interna (in pratica una specie di coda a da 8kBytes fino a 64kBytes).Dunque, mentre la BIU prepara la materia prima (nella coda delle istruzioni) l'unità di esecuzione, Execution Unit, EU), si occupa di interpretare i bytes prelevati in sequenza dalla medesima coda, cioè di eseguire l'istruzione.La sua Unità di Controllo di Esecuzione provvede ad organizzare tutto il lavoro, che prevede 2 fasi distinte:

la fase di fetch, durante la quale il byte prelevato dalla coda viene trasferito nel suo instruction register (IR).

la fase di decode, durante la quale il byte è "fatto a pezzi", nel senso che ogni codice operativo è frazionato in gruppi di 2 3 bit, in grado di dare indicazioni utili per la sua successiva esecuzione, come registri coinvolti o operazioni logiche o aritmetiche necessarie; ogni gruppo di bit è confrontato con il contenuto di alcune tabelle interne, in grado di attivare i giusti segnali di controllo necessari a garantire

26

Page 27: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

l'effetto suggerito dall'istruzione corrispondente al codice operativo.Non appena l'unità di controllo ha capito, parte la fase di execute, una incombenza tipica dell'altra parte fondamentale (con i registri) della EU: l'Unità Aritmetico Logica (ALU); il nome di questa struttura sottolinea la assoluta semplicità dei compiti che un processore è in grado di eseguire.

Nonostante l'enfasi diffusa sulla potenza dei processori (per altro indiscutibile..) si sottolinea per l'ennesima volta che le sue capacità operative sono effettivamente elementari: somme, differenze, prodotti e divisioni, qualche funzione logica (and, or, xor), qualche manipolazione di numeri binari (rotazioni e scorrimenti di bytes); niente che ciascuno di noi non possa fare altrettanto bene senza particolare difficoltà....... Solo che il processore fa questo in meno di miliardesimo di secondo!

E adesso, cosa fare?

La conoscenza dei dettagli funzionali del tuo processore e del computer che lo ospita dovrebbe darti sicurezza; è importante soprattutto sapere in che modo le istruzioni che fornirai verranno interpretate ed eseguite.Naturalmente ciascuna istruzione ti offrirà la propria attitudine e la metterà a tua disposizione: per questo i prossimi paragrafi saranno ricchi di dettagli e metteranno a nudo i trucchi e le abilità di ciascuna di esse.Per ora non ti rimane che leggere con attenzione il prossimo paragrafo, dedicato al Debugger, lo strumento più semplice ed efficace per verificare praticamente quello che hai letto in queste pagine.

27

Page 28: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

  Il Processore e il Debugger ISTRUZIONI 80x86

Questo paragrafo è descrittivo: costituisce il punto di contatto tra le tue idee e il modo di realizzarle, cioè ti insegna come farti obbedire dal tuo processore.Naturalmente qualunque comunicazione si basa sulla conoscenza del linguaggio e, in questo paragrafo, ci occuperemo delle parole necessarie per instaurarlo.In realtà le istruzioni sono come le parole di una lingua: non a caso consentono di esprimere i concetti della programmazione e costituiscono il tramite (mnemonico) tra programmatore e Cpu.Come le parole, anche le istruzioni sono molte di più di quante siano effettivamente necessarie e realmente utilizzate in una conversazione: nella normale programmazione quelle utilizzate più frequentemente sono solo qualche decina...Le istruzioni dei processori della famiglia 80x86 sono poco meno di 230 e la loro conoscenza non è assolutamente necessaria, ma rende giustizia a questa importante categoria di processori.Per non appesantire il tutorial, la sintassi, il modo d'uso e i segreti di ciascuna istruzione sono raccolti una ricca scheda , un eccellente punto di riferimento per capire come ottenere il massimo dalla programmazione in assembly. Nell'ambito della scheda sarà possibile analizzare in sequenza ciascuna istruzione, una pagina dopo l'altra.

Formato delle Istruzioni - Tipi di Operandi

Quando si parla di istruzione di solito si fa riferimento ad una struttura articolata su 3 campi: il codice Mnemonico, il campo Destinazione e il campo Sorgente (questi ultimi separati da una virgola):

  Mnemonico     Destinazione     Sorgente   MOV AX, BX

La sintassi delle istruzioni del linguaggio assembly per 80x86 è sempre quella sopra indicata, ed è bene fissarla bene in mente; l'esempio proposto è quello classico, e si legge: metti (MOV) il contenuto del registro BX (sorgente) in AX (destinazione).Nella stesura dei programmi sorgente è buona norma educarsi a mantenere un certo ordine; sebbene al lato pratico questo fatto non dia valore aggiunto, se non estetico, conviene far uso del tasto tabulato, al fine di mettere eventuali etichette sulla prima colonna, tutti gli mnemonici sulla seconda, e gli eventuali operandi sulla terza; opzionalmente è possibile aggiungere un quarto tab per scrivere un commento, di regola preceduto da un ; (punto e virgola).L'esempio seguente cerca di far luce su questo suggerimento, comunque utilizzato dall'Autore in tutti gli esempi di questo sito:

Esempio     di    Codice    Assembly--------------------------------------------------

Etichetta Mnemon  Operandi     ;Commento                Depo01 Depo02

DB      55H          ;variabile a 8 bitDW      55AAH        ;variabile a 16 bit

---------- ----------------------------------------------Inizio: MOV     AX,ES        ;Preparo il puntatore

MOV     ES,BX        ;alla prima locazioneMOV     DI,0000H     ;della Ram del VideoMOV     AL,ES:[DI]   ;Estrazione carattere

Lo stralcio di codice proposto mette in evidenza che le parole in esso contenute possono essere scritte indifferentemente in Maiuscolo o in minuscolo; è una questione di gusto... , di leggibilità e di personalità: l'Autore preferisce (ma può essere paranoia...) dare dignità alle etichette e al commento, scrivendo entrambi i campi in minuscolo ma con iniziale maiuscola, mentre predilige lo stampatello maiuscolo per i campi mnemonico e operandi, al fine di evidenziare la parte principale del programma.

Il campo etichetta : è molto importante perchè consente di associare un nome di fantasia alla locazione corrispondente alla

variabile (DB, o DW, o altro) o all'istruzione desiderata. il nome dell'etichetta è usato come operando per consentire al processore di localizzare la variabile in

operazioni di scrittura e/o lettura, e l'istruzione per saltarci (con JMP) o per chiamarla (con CALL) al fine di eseguirla.

28

Page 29: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

può contenere tutte le lettere (a-z,A-Z), tutti i numeri (0-9) ma non come primo carattere, e i simboli "_" (underscore), "$" (dollaro) e "?" (punto di domanda).

non deve essere uguale alle parole riservate dell'ambiente di programmazione, come gli mnemonici delle istruzioni e delle PseudoOperazioni o il nome dei registri (sono corrette Inizio _prima ma non DX o ESC).Il campo mnemonico contiene parole da 2 a 7 lettere (di solito da 3...) che descrivono sinteticamente il tipo di operazione da eseguire sugli operandi, oppure l'eventuale PseudoOperazione, o direttiva, da passare all'assemblatore; si definiscono mnemoniche perchè sono studiate per dare subito l'idea del loro compito, come MOVe (Muovi, sposta) JuMP (salta) CALL (chiama) e così via.Il campo Operando è quello che assume le forme più svariate possibili:

può anche rimanere vuoto, se l'istruzione non prevede interlocutori espliciti (in questo caso gli operandi sono fissati automaticamente dalla sintassi).

quando sono presenti sono di solito uno o 2, e la loro tipologia è spesso del tipo: tra registro e registro, o tra registro e memoria, o tra memoria e registro. tra registro e costante, o tra memoria e costante. tra accumulatore e costante.

l'operando costante è detto anche immediato, non per dare l'immagine di una cosa istantanea, ma nel senso di non mediato, cioè in grado di esprimere se stesso senza bisogno di altri:

se si tratta di un numero decimale è sufficiente digitarlo normalmente (1200); tutti i numeri normali

si intendono decimali. se deve esprimere un numero esadecimale deve avere una "H" dietro (2AH) e, se comincia per

lettera deve avere anche uno "0" davanti (0B800H): se non si mettesse questo 0 l'assemblatore segnalerebbe errore, scambiando il numero per etichetta, ovviamente non definita.

se, infine, il numero è binario deve avere una "B" dietro (01001100B), per le ragioni esposte negli altri casi; la scrittura di un numero binario può sembrare strana, ma in certe occasioni può aiutare a capire meglio il contesto del programma, per esempio per evidenziare un sensore in una batteria di otto, o un certo bit di un registro...

attenti a non scrivere per errore la "O" (vocale maiuscola) al posto dello "0" (numero zero). l'operando registro e l'operando memoria sono da intendere come il valore contenuto in essi.

Il campo del commento è ininfluente dal punto di vista del prodotto dell'assemblatore, ma per questo non deve essere sottovalutato: un buon programmatore cerca sempre di annotare il suo pensiero presente per sé e per i posteri...

Modi di indirizzamento

Quando si scrive un'istruzione di solito gli operandi vengono coinvolti con un meccanismo mentale automatico, senza pensarci più di tanto; i formalisti più attenti amano però associare ogni nostra scelta d'istinto a definizioni spesso poco memorabili, solo per il gusto di inquadrare tutto in rigidi schemi.La premessa probabilmente sorprenderà i luminari ed è per questo che ho deciso, comunque, di cercare un certo formalismo per esprimere questi concetti.In altre parole il problema non consiste nello stabilire dove trovare il dato da coinvolgere nelle operazioni del processore (cosa sacrosanta e del tutto necessaria), ma come chiamare questa tecnica di ricerca, cioè stabilire qual è il Modo di Indirizzamento.Sebbene i processori moderni siano in grado di gestire in modo diretto grandi quantità di memoria (quelli a 32 bit possono utilizzare puntatori in grado di indirizzare 232=4294967296 locazioni, cioè 4 Gbytes) in quasi tutte le pagine di questo tutorial si darà ospitalità ai programmi che lavorano con i registri a 16 bit, per altro naturalmente validi per tutta la famiglia 80x86; per questo i puntatori di memoria saranno in grado di servire aree di 216=65536 locazioni (64 Kbytes), a noi ben note come Segmenti.Dunque in funzione della tecnica d'accesso ad un determinato dato; vediamo i possibili di modi di indirizzamento:

tra registri: il dato è contenuto in un registro e viene semplicemente travasato in un altro registro (es: MOV AX,BX); si tratta del metodo più veloce possibile dato che il processore trova già dentro se stesso le informazioni necessarie per eseguire l'istruzione; naturalmente non è possibile coinvolgere registri di dimensione diversa.

immediato: il dato è indicato direttamente dall'istruzione e viene inserito nel registro specificato (es: MOV AX,1234H); sebbene la presenza del numero nella sintassi dell'istruzione possa indurre un pensiero di immediatezza anche nell'esecuzione, dobbiamo pensare che il dato costante è, in realtà, scritto nella memoria di programma (cioè quella puntata da CS:IP) dopo il codice operativo: per questo il processore è

29

Page 30: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

costretto ad eseguire uno o più accessi in memoria (a seconda della dimensione del dato) per prelevarlo e porlo nella coda d'istruzione, prima di sistemarlo:

dentro se stesso, in un registro MOV AX,1234H). in memoria MOV [Depo02],1234H); in questo caso la costante assunta dalla memoria di programma

dovrà essere spostata nella memoria dati (cioè puntata per default da DS:Offset, ma anche in altro segmento, se si impone esplicitamente un override, MOV CS:[Depo02],1234H).

diretto: il dato è localizzato dall'etichetta specificata direttamente dall'istruzione, ed è coinvolto (in lettura o in scrittura) con un registro di dimensione uguale a quella dell'operando diretto stesso (es: MOV AX,Depo02); bisogna sottolineare che:

l'etichetta non rappresenta l'indirizzo del dato ma il dato stesso!, cioè il dato contenuto nella locazione puntata da quell'indirizzo; per questo, sebbene la sintassi proposta come esempio sia perfettamente legale, personalmente preferisco educarmi a scriverla così MOV AX,[Depo02]: poiché il  compilatore la riconosce allo stesso modo mi sembra una scelta più vicina alla realtà.

l'altro operando deve avere la stessa dimensione del dato associato all'etichetta (con DB o DW o DD, nella riga di programma che definisce la variabile); in caso contrario è necessario utilizzare l'operatore Byte o Word o Dword (per esempio per trasferire in AL solo la parte bassa della word memorizzata in Depo02 bisogna scrivere MOV AL,Byte Ptr [Depo02]) 

indiretto tramite registro: il dato è localizzato con l'aiuto di un registro di Offset, di solito SI o DI ma anche altri registri a 16 bit:

la sintassi di queste istruzioni (es: MOV AX,[SI]) è, in questo caso, meno ambigua, dando con le parentesi quadre, il senso di contenuto della locazione puntata da SI (o qualunque altro registro).

per altro, se l'operando sorgente è una costante, è assolutamente necessario specificare anche la

dimensione del dato, con l'operatore Byte o Word o Dword Ptr , per evitare segnalazioni d'errore da parte dell'assemblatore,  per esempio: MOV Byte Ptr [Si],100)

indiretto tramite registro e spiazzamento: il dato è localizzato sommando il contenuto di un registro indice, SI o DI, o base, BX o BP, con il numero esadecimale con segno a 8 o a 16 bit, specificato nell'istruzione, detto displacement (spiazzamento) (es: MOV AX,[SI+10]):

la somma del contenuto dei registri con il numero fornito punta una locazione nel segmento DS se

i registri coinvolti sono SI, DI o BX, e nel segmento SS se il registro è BP. l'utilità di questo metodo è evidente quando è necessario scorrere una tabella in modo dinamico,

a partire da un certo punto; per esempio con la MOV AX,[Depo02+SI] basta cambiare il valore corrente di SI per assumere, una dopo l'altra, le word contenute nella tabella Depo02

indiretto tramite registro indice e base e spiazzamento: il dato è localizzato sommando il contenuto di un registro indice, SI o DI, con uno base, BX o BP, e con il numero esadecimale con segno a 8 o a 16 bit, specificato nell'istruzione, detto displacement (spiazzamento) (es: MOV AX,[SI+BX+10]):

la somma del contenuto dei registri con il numero fornito punta una locazione nel segmento DS se

il registro base coinvolto è BX, e nel segmento SS se invece è BP. questa ulteriore opzione rende ancora più versatile la gestione dinamica delle tabelle.

30

Page 31: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

  Il Processore e il Debugger DEBUG

In questo paragrafo facciamo conoscenza del Debugger, l'ambiente ideale per ispezionare e collaudare un programma, creato da noi o scelto tra l'infinita quantità di eseguibili (COM o EXE) presenti nelle nostre cartelle.Leggi con attenzione le descrizioni e contemporaneamente tieni aperta una finestra DOS con debug in funzione: potrai così verificare sulla tua pelle le importanti nozioni che ti darò.

Questo strumento (Debug.exe, da sempre fornito con il sistema operativo DOS, almeno fino a quando aveva la sua dignità e costituiva il vero punto di riferimento...) è molto spartano, quasi "repellente" per la sua estrema semplicità; ma questa sua semplicità è proprio la sua forza.

Naturalmente ci sono strumenti di progetto ben più potenti ma Debug aiuta ad entrare dentro il processore in modo essenziale e semplice, una condizione indispensabile sia per il neofita che per il grande esperto, quando è chiamato a risolvere da sé gli errori di compilazione...Dedica con passione qualche ora a questo potente strumento di lavoro: non snobbarlo e non supporre che dedicargli attenzione sia inutile perdita di tempo.Tratta fin d'ora il Debug come un tuo amico! ... quando "sarai grande" questo umile lavoro ti tornerà molto utile... 

Le tecniche sostenute in questo capitolo possono sembrare inadeguate al rango di programmatore al quale ambite, o troppo laboriose, o poco gratificanti...  Forse tutte queste obiezioni sono vere, ma sono convinto della loro reale utilità; tuttavia chi ritenesse superfluo perder tempo a usare Debug, può saltare questo paragrafo!

Che cos'è un Debugger?

Nel linguaggio comune un bug è una cosa fastidiosa, un pidocchio, una cimice, una calamità...Gli anglosassoni sono molto immediati nel definire i concetti e, spesso, associano ad eventi tecnici un'immagine forte e molto colorata; così un errore di programmazione diventa un bug........ e lo strumento che consente di localizzare ed eliminare i bug è diventato Debugger, lo "spulciatore"...La realtà è, a mio avviso, molto più nobile: il Debugger è molto di più, è un amico inseparabile, in grado quasi sempre di aiutarti a risolvere i problemi e a trovare gli errori più subdoli; la sua forza consiste nella capacità di simulare l'esecuzione di qualunque programma eseguibile (sia di tipo COM che di tipo EXE).Se l'assemblatore ha ritenuto corretta la sintassi del sorgente e il linker ha generato senza errore l'eseguibile non è detto che il nostro programma "giri" come ci aspettiamo; al contrario sono spesso in agguato gli errori di concetto che si manifestano di solito con devastante arroganza, bloccando tutto il computer e costringendoci a resettarlo (premere il pulsante di reset o chiudere l'applicazione con Ctrl-Alt-Canc). Sono i cosiddetti errori in run-time.In questi casi il modo migliore per capire dove abbiamo sbagliato è ricompilare il sorgente con dei break-point, cioè dei punti in cui il programma è costretto a fermarsi.

I break-point di solito si fissano inserendo nel punto desiderato l'istruzione INT 03H (Ricorda bene questo concetto!!); la loro presenza è del tutto irrilevante nell'esecuzione normale di un programma, ma se l'eseguibile è fatto girare sotto DEBUG esso si fermerà proprio nel punto previsto, consentendo l'esecuzione passo-passo delle successive istruzioni, fino a localizzare quella che ha creato l'errore run-time.

Dunque nella fase di collaudo e messa a punto di un programma il Debugger è uno strumento di lavoro particolarmente utile; da questo punto di vista si occupa del caricamento in memoria dell'eseguibile, in modo paragonabile a quello del loader del sistema operativo e, dopo aver preparato i puntatori alla prima istruzione (CS:IP) e alla prima locazione dello stack (SS:SP) cede il controllo a noi, manifestando la sua disponibilità con un trattino posto sulla riga successiva all'intestazione:

Microsoft (R) Symbolic Debug Utility Version 4.00Copyright (C) Microsoft Corp 1984, 1985. All rights reserved.Processor is [80286]-L'immagine proposta mostra l'intestazione del Symbolic Debug della Microsoft, SymDeb.exe, una versione più dotata di quella di solito disponibile, tipica del sistema operativo e fornita con esso, Debug.exe; le differenze tra le 2 versioni sono funzionali, ma sostanzialmente assicurano lo stesso servizio.

31

Page 32: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

Non bisogna ignorare, in questa fase di presentazione, l'altra grande valenza del Debugger: forse è esagerato chiamarlo programma per voyeur, ma certamente grande è l'emozione nel cercare di capire la logica che ha spinto un programmatore a sviluppare la propria creatura: il Debugger è in grado di dare questa emozione!

Con il Debugger è possibile aprire ed eseguire qualunque programma eseguibile: poiché è in grado di mostrarne il codice dissassemblato (molto vicino a quello sorgente originale) è facile scorrerne il contenuto, per cercare di capire o scoprire i trucchi del suo autore. (come pensi che facciano i "crackatori" di professione?).

Detto questo non rimane che cominciare l'avventura...

Cosa offre un Debugger? 

L'ambiente Debug è senz'altro spartano, essenziale: i detrattori fanno di questa caratteristica il suo limite ma, preferendogli sofisticati ambienti di debugging, come il TurboDebug della Borland o il CodeView della Microsoft.Personalmente ritengo che la sua semplicità sia la sua forza;....io lo amo alla follia...La verità è che chi lo conosce non può non usarlo; il debugger non è solo il punto d'inizio, un modo per entrare nell'ambiente; ... qualche volta è l'ultima spiaggia...Dopo essere entrati in Debug il comando ? mostra la forza di questo ambiente (tutti i comandi si danno digitandone la lettera o la stringa dopo il prompt del debug, cioè dopo il trattino).Molti di questi comandi sono di uso piuttosto raro e non strettamente necessario.Alcuni comandi del symbolic debugger non sono previsti dal debugger del Dos: tra questi alcuni servono specificatamente in presenza del pacchetto originale, che prevede la possibilità di coinvolgere addirittura i simboli definiti nel programma sorgente...Nelle pagine seguenti ci occuperemo di quelli indispensabili per il collaudo degli eseguibili, tralasciando di entrare nel merito dei comandi troppo particolari.

Come si usa Debug?

Per entrare in ambiente Debug è sufficiente digitare il suo nome al prompt del Dos; da questo momento non faremo alcuna distinzione tra le 2 versioni descritte nella pagina precedente, e prenderemo in considerazione i comandi in qualche modo in comune ad entrambe.Abbiamo già sottolineato che il programma Debug è particolarmente utile quando apre e gestisce un determinato file, non necessariamente eseguibile; in questo caso dopo il nome Debug deve essere digitato anche quello del file da aprire, anche con l'eventuale percorso:

C:\Arch-Lab\Lavoro>DEBUG prova.comC:\Arch-Lab\Lavoro>DEBUG a:prova.comC:\Arch-Lab\Lavoro>DEBUG macro.mac

Qualunque tipo di file può essere aperto in questo modo, essendo chiaro che, ovviamente, solo gli EXE o i COM potranno essere collaudati.Altri files, come quelli di testo, con estensione TXT, o di altro tipo (MAC, LIB, PAS, OBJ, eccetera) saranno comunque caricati in memoria.Che ragione c'è di caricare in memoria un file non eseguibile? Quando avrai completato la lettura di tutto il paragrafo questo concetto ti sarà chiaro: posso anticiparti che qualunque sia la natura del file gestito, Debug è in grado di modificarne il contenuto anche pesantemente...Dunque, se dopo la parola Debug, viene specificato il nome di un file esistente esso viene caricato in memoria a partire dalla locazione 0100H; nelle precedenti 256 locazioni, a partire da 0000H, viene creato un Prefisso di Segmento di Programma (PSP),  esattamente come fa il loader del Dos: in nessun caso bisogna manomettere il loro contenuto, almeno delle prime 92 (cioè fino all'indirizzo 005CH); se si modificano questi bytes il debug viene terminato o, peggio, si provoca il blocco del computer.Naturalmente è possibile fruire della grande capacità di ispettore di Debug anche senza il vincolo di un programma da gestire (cioè senza digitare alcun nome di file); in questo caso avremo la possibilità di intervenire direttamente sul contenuto sia della memoria Ram che dei singoli settori della memoria di massa:

nel primo caso, se sappiamo dove cercare, si aprono tutti i cassetti segreti del computer, magna cum libido...

nel secondo caso rischiamo moltissimo!!!, specialmente se mettiamo le mani sull'Hard Disk..; lo strumento di lavoro è molto potente ma va usato con assoluta conoscenza dei fatti! Nelle pagine

32

Page 33: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

seguenti, per etica professionale, riprenderò il discorso ma non dimenticare che meno tocchi i settori di un disco meglio è!

Comando N -  Specifica il Nome di un file

Va sottolineato che è possibile caricare un file anche senza specificarne il nome dopo la parola Debug; lo si può fare con 2 comandi consecutivi, dal suo interno:

-n prova.xxx-l

con N nomefile.ext: dopo aver confermato con Invio non sembra succedere niente; in realtà il gestore viene avvisato che dovrà cercare un programma con nome (NAME) nomefile ed estensione ext.

con L, LOAD, confermato da Invio, il debug è costretto a cercare il file e a caricarlo in memoria; solo se non lo trova segnalerà errore (File not found o Impossibile trovare il file).Da notare che il comando N deve essere fornito anche quando desideriamo fare l'operazione opposta: talvolta può essere necessario salvare un nostro lavoro originale, appena creato in memoria, o salvare con altro nome un file caricato in precedenza. Anche questa operazione si può fare con 2 comandi consecutivi:

-n prova.xxx-w

Il comando W, WRITE, è complementare al precedente e permette di scrivere una quantità di bytes sul disco (fisso o floppy).Entrambi i comandi digitati insieme a N hanno la loro dignità e saranno trattati più avanti, in modo autonomo e completo; in particolare il secondo (W) non avrà l'effetto desiderato se non sarà specificato il numero di bytes da salvare...

Comando Q -  termina la sessione di lavoro 

Prima di spingere a fondo la conoscenza di Debug espletiamo la formalità di descrivere il comando per uscire: premendo Q ,QUIT, ogni operazione svolta fino a quel momento viene persa irrimediabilmente (dopotutto siamo in ram) e il controllo viene ceduto di nuovo al sistema operativo.Non dimentichiamo dunque di salvare l'eventuale file ospitato, magari con altro nome, per fissare sulla memoria di massa i cambiamenti effettuati.

Comando D -  Analizza il contenuto della memoria 

Il nostro Debug è una vera bomba... Evitiamo, per ora, di assumere files da controllare: già così, da solo, questa utility mostra la sua assoluta versatilità. 

Se vuoi trarre il massimo profitto dalle pagine di questo paragrafo ti conviene aprire una shell Dos (cliccando sulla corrispondente icona del menu d'Avvio) e provare in diretta le cose che descriveremo: digita subito DEBUG e, quando appare il trattino, a sinistra, digita i comandi che ti suggerirò, di volta in volta.Diventerai ben presto autonomo e sicuro e ti verrà voglia di provare da solo... 

Cominciamo con il comando D, DUMP; già il nome merita una pausa di riflessione: il sostantivo dump significa letteralmente bidone della spazzatura, posto sudicio, o più elegantemente

cestino dei rifiuti; il verbo dump significa invece rovesciare

La brillante verve anglosassone ha colpito ancora... quando si richiede un dump qualcuno ci rovescia il cestino dei rifiuti sulla scrivania...; proprio quello che facciamo noi quando, disperati, ci accorgiamo di avere cestinato, per errore, un documento a cui tenevamo. Il comando D vuota sul video una bella fetta di memoria, mostrandone tutti i dettagli possibili.

Aldilà della metafora questo comando è veramente potente, sebbene lo si possa apprezzare solo quando si ha effettivamente qualcosa da cercare; premendo la lettera D, senza nessuna altra specifica, appare a video questa schermata:

33

Page 34: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

-d0DE0:0100 9D BE A4 9C 8B 3E E6 9D-B9 08 00 AC 3C 3F 75 02 .....>......<?u.0DE0:0110 8A 07 3C 20 74 01 AA 43-E2 F1 B1 03 34 00 CF 0D ..< t..C....4...0DE0:0120 74 12 B0 2E AA AC 3C 3F-75 02 8A 07 3C 20 74 01 t.....<?u...< t.0DE0:0130 AA 43 E2 F1 32 C0 AA C3-F6 46 04 02 75 43 8B D5 .C..2....F..uC..0DE0:0140 83 C2 05 57 B8 00 6C BB-40 00 33 C9 8B F2 BA 01 [email protected]:0150 01 CD 21 5F 73 15 E8 C4-DB 3D 02 00 74 23 3D 03 ..!_s....=..t#=.0DE0:0160 00 74 1E 3D 05 00 74 19-E9 E3 dotto 8B dotto B8 00 44 .t.=..t........D0DE0:0170 CD 21 B4 3E CD 21 F6 C2-80 75 53 F6 46 04 04 74 .!.>.!...uS.F..t

NB: la prima cosa che salta agli occhi è la naturalezza con cui DEBUG tratta le informazioni: poiché è uno strumento dedicato all'analisi del processore (i suoi registri) e della memoria ogni numero da esso presentato sul monitor va inteso espresso nella lingua del processore cioè esadecimale.Si tratta di uno strumento dedicato per cui, in questo ambiente, la presenza della 'H' che ci siamo educati a mettere dopo ciascun numero esadecimale è data per scontata.Naturalmente la regola vale anche quando saremo chiamati a dare informazioni a DEBUG, per fissare un indirizzo o per predisporre il valore di un registro o di una locazione di memoria... I numeri (esadecimali) digitati dovranno essere forniti senza la 'H' finale!

E' importante ricordare fin d'ora che i numeri esadecimali si possono trattare senza la "H" posteriore solo quando abbiamo a che fare con DEBUG; se è vero che esso non capirebbe (segnalando errore...) comandi del tipo D  0100H  è altrettanto vero che l'assemblatore farebbe altrettanto se invece dimenticassimo di metterla . Questo concetto è ripreso e spiegato in questa pagina.

Detto questo, analizziamo la videata ottenuta; sono 8 righe così strutturate: il campo di sinistra (in verde) mostra l'indirizzo segmentato della prima locazione di memoria che

andremo ad ispezionare: il puntatore è inteso espresso in esadecimale. il campo centrale (in celeste) elenca il contenuto delle 16 locazioni consecutive, a partire da quella

indirizzata dal primo campo, espresso in esadecimale. il campo di sinistra (in giallo) cerca di tradurre in forma Ascii il contenuto delle medesime locazioni.

Le 7 righe successive hanno la medesima struttura e descrivono altre 16 locazioni ciascuna, per un totale di 128 (un ottavo di kBytes).Valutiamo in modo critico le informazioni di questa immagine:

l'indirizzo di segmento è, per tutti i puntatori, sempre lo stesso (nell'esempio 0DE0): il suo valore dipende esclusivamente da quello della prima zona di ram libera al momento del caricamento del debugger in memoria; questo ultimo riserva ai nostri esperimenti un intero segmento che comincia proprio da 0DE0:0000.

l'indirizzo di offset iniziale è 0100: il suo valore risente del fatto che Debug ha riservato per se stesso le prime 256 locazioni, per ospitare, nella logica dei programmi gestiti dal Dos, il proprio PSP).

la sequenza dei numeri seguenti è esattamente la traduzione esadecimale di quello che debug ha effettivamente trovato: il loro valore è assolutamente imprevedibile e può essere cambiato in ogni momento, senza provocare alcun danno, come vedremo nelle prossime pagine.

la zona gialla dei caratteri Ascii è illeggibile, tanto più quanto maggiore è la casualità dell'area di memoria analizzata; tutti i bytes che corrispondono a caratteri Ascii stampabili sono mostrati per quello che sono, mentre tutti gli altri (da 00H a 1FH, caratteri di controllo, e da 80H a FFH, caratteri ascii estesi) sono visualizzati con un punto.Per motivi di chiarezza la sequenza dei 16 bytes di ciascuna riga è divisa in 2 da un trattino.Se il comando D viene dato di nuovo, viene rovesciata a video la successiva "cestinata" di 128 bytes, e così ad oltranza.Se si desidera tornare all'inizio o se si vuole analizzare un'altra parte della memoria basta specificare l'indirizzo subito dopo la lettera D, ma di questo parleremo nella prossima pagina.La potenza di DUMP sta nella sua capacità di ficcare il naso nella memoria..., in tutta la memoria!Specificando l'indirizzo desiderato ci viene offerta la possibilità di verificare concetti e idee maturate in altri ambiti di studio; per esempio possiamo vedere se la Ram del Video è effettivamente costituita da bytes alternati di carattere (ascii) e di colore (attributo); basta specificare, dopo il comando D, l'indirizzo di quell'area, B800:0000:

-d b800:0000B800:0000 20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07 . . . . . . . .B800:0010 20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07 . . . . . . . .

34

Page 35: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

B800:0020 20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07 . . . . . . . .B800:0030 20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07 . . . . . . . .B800:0040 20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07 . . . . . . . .B800:0050 20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07 . . . . . . . .B800:0060 20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07 . . . . . . . .B800:0070 20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07 . . . . . . . .

Straordinario: l'indagine ci dice che le prime 128 locazioni contengono 64 coppie consecutive di bytes 20H/07H.. Ma che significa?Intanto ciascuna coppia è una banale sequenza di bytes, ma il loro significato, nell'ambito nel quale sono stati trovati, non è banale! Nella Ram Video il primo è il carattere effettivamente presente sul monitor (e, poichè ha valore 20H si tratta di uno spazio, come risulta dalla caratteri Ascii standard), mentre il secondo è il codice associato al suo colore (poichè è 07H si tratta di bianco su nero, come risulta dal byte d'attributo di colore presentato in questa pagina).Dunque quella strana sequenza di bytes, mostrata con fredda determinazione dal debugger, rappresenta i primi 64 caratteri posti sul monitor, a cominciare dal primo, nell'angolo in alto a sinistra.. praticamente 64 spazi invisibili (perchè anche se colorati di bianco su nero sempre spazi sono...)In effetti, se tenti di verificare direttamente questo evento è difficile che la schermata sia uguale a quella che ti ho proposto qui sopra.. Il debug è un fedele servitore e codifica quello che trova sul monitor in quel momento.. la codifica proposta nello schema precedente è relativa ad uno schermo completamente vuoto...Ma se, con lo schermo vuoto, al prompt del Dos si digita il comando Debug confermato con invio... sul video apparirà:

C:\ARCH-LAB\SITO>debugMicrosoft (R) Symbolic Debug Utility Version 4.00Copyright (C) Microsoft Corp 1984, 1985. All rights reserved.

Processor is [80286]-

quello che vedremo dopo aver dato il comando -d b800:0000 sarà:

-d b800:0000B800:0000 20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07 . . . . . . . .B800:0010 20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07 . . . . . . . .B800:0020 20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07 . . . . . . . .B800:0030 20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07 . . . . . . . .B800:0040 20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07 . . . . . . . .B800:0050 20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07 . . . . . . . .B800:0060 20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07 . . . . . . . .B800:0070 20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07 . . . . . . . .-dB800:0080 20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07 . . . . . . . .B800:0090 20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07 . . . . . . . .B800:00A0 43 07 3A 07 5C 07 41 07-52 07 43 07 48 07 2D 07 C.:.\.A.R.C.H.-.B800:00B0 4C 07 41 07 42 07 5C 07-53 07 49 07 54 07 4F 07 L.A.B.\.S.I.T.O.B800:00C0 3E 07 64 07 65 07 62 07-75 07 67 07 20 07 20 07 >.d.e.b.u.g. . .B800:00D0 20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07 . . . . . . . .B800:00E0 20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07 . . . . . . . .B800:00F0 20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07 . . . . . . . .-Che è successo? Debug ha codificato quello che ha trovato: ogni carattere presente sul monitor, a gruppi di 64 alla volta; poichè la prima riga del monitor è vuota (cioè i primi 80 caratteri sono tutti spazi) per cominciare a notare qualcosa bisogna dare un altro comando -d... Solo nel secondo elenco si comincia a capire il meccanismo.Le prime coppie diverse da 20H/07H sono proprio visibili a partire dal 161° bytes (quello all'indirizzo B800:00A0): infatti:

i primi 160 bytes sono 80 bytes 20H e 80 bytes 07H; e rappresentano gli 80 spazi della prima riga vuota del monitor.

i successivi bytes sono per metà al valore 07H perché il colore della frase presente sul monitor è, appunto, bianco su nero (=07H)...

... mentre l'altra metà sono i bytes 43H, 3AH, 5CH, 41H, 52H, 43H, 48H, 2DH, ..., appunto la traduzione

35

Page 36: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

esadecimale dei caratteri che compongono le frasi a video, C:\ARCH-Del resto il buon Debug cerca di aiutarci a capire inserendo a destra la traduzione Ascii dei bytes trovati, indicando tra un carattere e l'altro un puntino, non riuscendo ad associare al colore 07H altro simbolo; cosicché la frase trovata e ricostruita è proprio quella attualmente a video:

C:\ARCH-LAB\SITO>debug

Un'altra prova simpatica consiste nella ricerca dei messaggi del dos: quando il sistema operativo viene caricato viene allocato nel primo segmento di memoria ram (cioè certamente dentro i primi 64kBytes, nell'area fino a 0000:FFFFH).Dunque, con un po' di pazienza cominciando con il comando D 0:0 e continuando, successivamente, con il comando D (senza altre specifiche) prima o poi i messaggi vengono trovati; nella figura mostriamo l'area in cui, finalmente, sono stati trovati, sul mio computer:

-d 0:00000:0000 68 10 A7 00 8B 01 70 00-16 00 B4 03 8B 01 70 00 h.....p.......p.      ..................  omissis ...................

0000:4940 46 32 00 00 00 54 52 49-4C 53 4E 07 54 65 72 6D F2...TRILSN.Term0000:4950 69 6E 61 09 2C 20 52 69-70 72 6F 76 61 08 2C 20 ina., Riprova.,0000:4960 49 67 6E 6F 72 61 0B 2C-20 54 72 61 6C 61 73 63 Ignora., Tralasc0000:4970 69 61 01 3F 0B 6C 65 74-74 75 72 61 20 64 69 00 ia.?.lettura di.-d0000:4980 0D 73 63 72 69 74 74 75-72 61 20 64 69 00 0E 20 .scrittura di..0000:4990 25 31 20 75 6E 69 74 85-20 25 32 0D 0A 0E 20 25 %1 unit. %2... %0000:49A0 31 20 75 6E 69 74 85 20-25 32 0D 0A 2D 49 6E 73 1 unit. %2..-Ins0000:49B0 65 72 69 72 65 20 69 6C-20 76 6F 6C 75 6D 65 20 erire il volume0000:49C0 25 31 20 6E 75 6D 65 72-6F 20 64 69 20 73 65 72 %1 numero di ser0000:49D0 69 65 20 25 32 2D 25 33-0D 0A 31 54 61 62 65 6C ie %2-%3..1Tabel0000:49E0 6C 61 20 64 69 20 61 6C-6C 6F 63 61 7A 69 6F 6E la di allocazion0000:49F0 65 20 66 69 6C 65 20 64-69 66 65 74 74 6F 73 61 e file difettosa-d0000:4A00 2C 20 75 6E 69 74 85 20-25 31 0D 0A 18 43 4F 4D , unit. %1...COM0000:4A10 4D 41 4E 44 2E 43 4F 4D-20 6E 6F 6E 20 76 61 6C MAND.COM non val0000:4A20 69 64 6F 0D 0A 28 49 6E-73 65 72 69 72 65 20 69 ido..(Inserire i0000:4A30 6C 20 64 69 73 63 6F 20-63 6F 6E 20 25 31 20 6E l disco con %1 n0000:4A40 65 6C 6C 27 75 6E 69 74-85 20 25 32 0D 0A 27 50 ell'unit. %2..'P0000:4A50 72 65 6D 65 72 65 20 75-6E 20 74 61 73 74 6F 20 remere un tasto0000:4A60 70 65 72 20 63 6F 6E 74-69 6E 75 61 72 65 20 2E per continuare .0000:4A70 20 2E 20 2E 0D 0A 24 0D-0A 54 65 72 6D 69 6E 61 . ...$..Termina

Naturalmente la tecnica della ricerca dei testi è straordinariamente utile anche nella pratica quotidiana; se Debug sta analizzando un file eseguibile da studiare e capire, con pazienza e in tempi relativamente veloci se ci sono i testi saltano fuori! Desidero sottolineare anche un altro aspetto; abituiamoci ad andare aldilà delle apparenza (cioè a vedere tra le righe...): 

con la vista allenata i caratteri Ascii dei testi sono riconoscibilissimi: sono tutti numeri compresi tra 20 (lo spazio) e 7F (il simbolo di copyright) e sono sempre in gruppo, tra loro.

spesso in queste sequenze di codici (tra 20 e 7F) sono chiaramente visibili le coppie 0D, 0A. (in giallo, nella figura). Sono i codici ascii dell' Invio : in quel punto il testo viene mandato a capo!

Comando F -  Riempie la memoria [azzeramento delle locazioni]

Questo comando è piuttosto comodo in particolari situazioni; l'uso del comando D (Dump) ci ha insegnato che l'analisi del contenuto della Ram di sistema è molto spesso casuale.

Tieni ben presente che il contenuto esadecimale delle locazioni di memoria è del tutto imprevedibile nel momento in cui Debug ne prende possesso: è possibile che i valori letti siano tutti a 00, ma non è da escludere qualunque altro valore (memoria "sporca") lasciato in Ram dall'uso da parte di precedenti applicativi.

36

Page 37: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

Questa osservazione vale, ovviamente, anche nel segmento a disposizione del debugger; qualunque cosa venga inserita risulta poco probabile distinguerne la fine.Per questo l'Autore consiglia di "pulire" il segmento prima di caricare il file da analizzare, evitando di entrare in Debug nel modo, per altro sacrosanto, suggerito in precedenza. Per studiare il file xxx.com (è solo un esempio!), dopo essere entrati in debug la sequenza possibile è mostrata in figura:

-f 100 e000 00-n xxx.com-l

Il comando F (FILL, riempi) si aspetta l'intervallo di indirizzi (offset) iniziale e finale (nel nostro esempio 0100H e E000H); bisogna stare attenti a non esagerare: se si cancellano locazioni sotto l'indirizzo 005CH o sopra E000H (valore indicativo) il debug potrebbe "piantarsi". Le aree esterne a questo intervallo sono infatti vitali per il suo funzionamento: nelle prime 92 locazioni sono presenti dati insostituibili del Prefisso di Segmento di Programma (PSP), mentre le ultime sono destinate allo stack; l'utilizzo del Symbolic Debug rende quest'ultima zona certamente sovradimensionata rispetto a quella di norma prevista (di solito è sufficiente riservare qualche decina di bytes in fondo al segmento, per esempio a partire da FF00H).Se l'indirizzo specificato è solo quello di offset i dati visualizzati si ritengono appartenenti al segmento puntato da DS; in condizioni di default (come quelle in cui operiamo ora) il problema non si pone (tutti e 4 i registri di segmento hanno lo stesso valore).Il terzo parametro del comando F può essere di diverso tipo: l'esempio suggerito utilizza un byte esadecimale di valore 00H. Dopo la conferma con Invio sembra non sia successo nulla; in realtà la memoria è stata riempita, in tempo reale, di 00H, come dimostra la seguente analisi con il comando D:

-f 100 e000 00-d 1001192:0100 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................1192:0110 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................1192:0120 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................1192:0130 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................1192:0140 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................1192:0150 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................1192:0160 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................1192:0170 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................-d1192:0180 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................      ..................  omissis ...................

-d dfa01192:DFA0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................1192:DFB0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................1192:DFC0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................1192:DFD0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................1192:DFE0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................1192:DFF0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................1192:E000 00 C2 05 57 B8 00 6C BB-40 00 33 C9 8B F2 BA 01 [email protected]:E010 01 CD 21 5F 73 15 E8 C4-DB 3D 02 00 74 23 3D 03 ..!_s....=..t#=.

Per evitare un crampo alla mano... dopo aver verificato l'azzeramento delle prime pagine abbiamo dato il comando D DFF0, puntando un indirizzo leggermente inferiore a quello finale passato al comando F: il risultato dell'indagine sottolinea che, effettivamente, dopo di esso nessun'altra locazione risulta azzerata.Se immaginiamo di caricare qualunque cosa in questo segmento di memoria è facile rilevare il suo ultimo byte, con grande probabilità quello dopo il quale comincia la lunga teoria degli zero...

Comando F -  Riempie la memoria [utilizzo di altri caratteri]

Il comando F è particolarmente versatile; come anticipato il suo terzo parametro può essere di diverso tipo; la memoria può essere riempita con singoli bytes (per esempio 00H, come nell'esempio precedente, ma anche con qualunque altro valore), con sequenze di bytes, con caratteri Ascii, con stringhe Ascii di qualunque lunghezza. Le immagini mostrano il comando corretto F, nei vari casi, e, con l'aiuto di D, l'effetto

37

Page 38: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

prodotto. Osserviamo che, qualunque sia la sequenza passata come terzo parametro, essa viene ripetuta più volte, fino a saturare tutte le locazioni previste.

-f 100 15f 01,02,03,04-d 1001192:0100 01 02 03 04 01 02 03 04-01 02 03 04 01 02 03 04 ................1192:0110 01 02 03 04 01 02 03 04-01 02 03 04 01 02 03 04 ................1192:0120 01 02 03 04 01 02 03 04-01 02 03 04 01 02 03 04 ................1192:0130 01 02 03 04 01 02 03 04-01 02 03 04 01 02 03 04 ................1192:0140 01 02 03 04 01 02 03 04-01 02 03 04 01 02 03 04 ................1192:0150 01 02 03 04 01 02 03 04-01 02 03 04 01 02 03 04 ................1192:0160 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................1192:0170 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................

La sequenza di bytes può essere anche più lunga.Per localizzare facilmente la fine del codice di un programma può essere utile riempire la memoria di asterischi (carattere ascii '*') invece che di zero:

-f 200 24f '*'-d 2001192:0200 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 2A 2A 2A ****************1192:0210 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 2A 2A 2A ****************1192:0220 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 2A 2A 2A ****************1192:0230 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 2A 2A 2A ****************1192:0240 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 2A 2A 2A ****************1192:0250 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................1192:0260 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................1192:0270 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................

Sebbene la cosa sia al limite della paranoia... la memoria si può riempire anche con piccole (o grandi) frasi:

-f 300 360 '[Giobe] '-d 3001192:0300 5B 47 69 6F 62 65 5D 20-5B 47 69 6F 62 65 5D 20 [Giobe] [Giobe]1192:0310 5B 47 69 6F 62 65 5D 20-5B 47 69 6F 62 65 5D 20 [Giobe] [Giobe]1192:0320 5B 47 69 6F 62 65 5D 20-5B 47 69 6F 62 65 5D 20 [Giobe] [Giobe]1192:0330 5B 47 69 6F 62 65 5D 20-5B 47 69 6F 62 65 5D 20 [Giobe] [Giobe]1192:0340 5B 47 69 6F 62 65 5D 20-5B 47 69 6F 62 65 5D 20 [Giobe] [Giobe]1192:0350 5B 47 69 6F 62 65 5D 20-5B 47 69 6F 62 65 5D 20 [Giobe] [Giobe]1192:0360 5B 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 [...............1192:0370 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................

Come altri comandi del debug, il range degli indirizzi da coinvolgere può essere passato sotto forma di indirizzo iniziale, lunghezza (espressa con una L seguita dal numero esadecimale delle locazioni da riempire), per esempio così:

-f 400 L50 'abcde'-d 4001192:0400 61 62 63 64 65 61 62 63-64 65 61 62 63 64 65 61 abcdeabcdeabcdea1192:0410 62 63 64 65 61 62 63 64-65 61 62 63 64 65 61 62 bcdeabcdeabcdeab1192:0420 63 64 65 61 62 63 64 65-61 62 63 64 65 61 62 63 cdeabcdeabcdeabc1192:0430 64 65 61 62 63 64 65 61-62 63 64 65 61 62 63 64 deabcdeabcdeabcd1192:0440 65 61 62 63 64 65 61 62-63 64 65 61 62 63 64 65 eabcdeabcdeabcde1192:0450 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................1192:0460 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................1192:0470 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................

Comando C -  Confronta 2 aree di memoria

Mai dire mai! Se i valori presenti in memoria sono particolarmente significativi può essere necessario confrontarli tra loro, sebbene questo evento sia poco probabile; in ogni caso la sintassi prevede al solito 2 modi, sostanzialmente uguali. 

38

Page 39: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

Il comando C (COMPARE, confronta) si aspetta 3 indirizzi (offset): quello iniziale e finale della prima area e quello iniziale della seconda area.Naturalmente è possibile passare anche indirizzi completi (cioè anche con il valore del segment); se l'indirizzo specificato è solo quello di offset i dati visualizzati si ritengono appartenenti al segmento puntato da DS; in condizioni di default (come quelle in cui operiamo ora) il problema non si pone (tutti e 4 i registri di segmento hanno lo stesso valore). Il comando C risponde mostrando (purtroppo velocemente...) l'indirizzo completo e il contenuto di entrambe le aree, nella sequenza:

segment1:offset1     contenuto1     contenuto2     segment2:offset2Nell'esempio seguente sono confrontate le 2 aree DS:0100H e DS:0200H; poichè il loro contenuto è noto (per effetto degli esercizi fatti nella pagina precedente) il risultato del confronto è piuttosto gratificante:

-c 100 10a 2001192:0100 01 2A 1192:02001192:0101 02 2A 1192:02011192:0102 03 2A 1192:02021192:0103 04 2A 1192:02031192:0104 01 2A 1192:02041192:0105 02 2A 1192:02051192:0106 03 2A 1192:02061192:0107 04 2A 1192:02071192:0108 01 2A 1192:02081192:0109 02 2A 1192:02091192:010A 03 2A 1192:020A---------------------------1192:0100 01 02 03 04 01 02 03 04-01 02 03 04 01 02 03 04 ................---------------------------1192:0200 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 2A 2A 2A *************

Se le 2 aree di memoria contengono gli stessi bytes non viene mostrato alcun valore; è il caso del seguente esempio nel quale entrambi gli indirizzi iniziali di ciascuna area sono volutamente uguali a DS:0100H:

-c 100 10a 100-

Anche in questo caso il comando può essere dato passando l'indirizzo iniziale della prima area e la lunghezza (espressa con una L seguita dal numero esadecimale delle locazioni da confrontare) seguito dall'indirizzo iniziale della seconda area:

-c 200 La 3001192:0200 2A 5B 1192:03001192:0201 2A 47 1192:03011192:0202 2A 69 1192:03021192:0203 2A 6F 1192:03031192:0204 2A 62 1192:03041192:0205 2A 65 1192:03051192:0206 2A 5D 1192:03061192:0207 2A 20 1192:03071192:0208 2A 5B 1192:03081192:0209 2A 47 1192:0309-

Comando M -  Copia il contenuto della memoria

Sebbene sia ormai chiaro che l'ambiente debug non sia particolarmente adatto al progetto (ma indispensabile nel collaudo...) nelle rare occasioni in cui viene deputato a tale compito può essere necessario spostare una certa quantità di bytes per poterne intromettere altri.In realtà più che di uno spostamento si tratta di una copia, dato che i bytes coinvolti saranno ancora presenti nelle locazioni sorgente.Il comando M (MOVE, muovi) si aspetta 3 indirizzi (offset): quello iniziale e finale dell'area in cui sono contenuti i bytes da copiare e quello iniziale dell'area in cui si desidera copiarli.

39

Page 40: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

Se l'indirizzo specificato è solo quello di offset i dati visualizzati si ritengono appartenenti al segmento puntato da DS; in condizioni di default tutti e 4 i registri di segmento hanno lo stesso valore, per cui il problema non si pone; naturalmente è possibile passare anche indirizzi completi (cioè anche con il valore del segment).Nell'esempio seguente i primi 32 bytes a partire dall'indirizzo DS:0100H sono copiati nelle locazioni a partire da DS:0500H; la conferma del comando con Invio sembra non produrre alcun effetto, ma la successiva conferma con il comando D mostra l'avvenuto servizio:

-m 100 120 500-d 1001192:0100 01 02 03 04 01 02 03 04-01 02 03 04 01 02 03 04 ................1192:0110 01 02 03 04 01 02 03 04-01 02 03 04 01 02 03 04 ................1192:0120 01 02 03 04 01 02 03 04-01 02 03 04 01 02 03 04 ................1192:0130 01 02 03 04 01 02 03 04-01 02 03 04 01 02 03 04 ................1192:0140 01 02 03 04 01 02 03 04-01 02 03 04 01 02 03 04 ................1192:0150 01 02 03 04 01 02 03 04-01 02 03 04 01 02 03 04 ................1192:0160 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................1192:0170 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................-d 5001192:0500 01 02 03 04 01 02 03 04-01 02 03 04 01 02 03 04 ................1192:0510 01 02 03 04 01 02 03 04-01 02 03 04 01 02 03 04 ................1192:0520 01 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................1192:0530 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................1192:0540 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................1192:0550 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................1192:0560 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................1192:0570 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................-

Il comando può essere dato passando l'indirizzo iniziale della prima area e la lunghezza (espressa con una L seguita dal numero esadecimale delle locazioni da copiare) seguito dall'indirizzo iniziale della seconda area:

-m 100 L20 600-d 6001192:0600 01 02 03 04 01 02 03 04-01 02 03 04 01 02 03 04 ................1192:0610 01 02 03 04 01 02 03 04-01 02 03 04 01 02 03 04 ................1192:0620 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................

Non possiamo passare oltre senza sottolineare la magia di questo comando: se l'area sorgente e quella di destinazione si sovrappongono la copia viene portata a termine senza perdita di informazione; naturalmente l'area sorgente non potrà rimanere inalterata se quella di destinazione la copre!

-d 2001192:0200 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 2A 2A 2A ****************1192:0210 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 2A 2A 2A ****************1192:0220 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 2A 2A 2A ****************1192:0230 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 2A 2A 2A ****************1192:0240 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 2A 2A 2A ****************1192:0250 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................1192:0260 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................1192:0270 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................-m 200 L50 230-d 2001192:0200 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 2A 2A 2A ****************1192:0210 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 2A 2A 2A ****************1192:0220 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 2A 2A 2A ****************1192:0230 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 2A 2A 2A ****************1192:0240 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 2A 2A 2A ****************1192:0250 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 2A 2A 2A ****************1192:0260 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 2A 2A 2A ****************1192:0270 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 2A 2A 2A ****************

40

Page 41: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

Comando S -  Cerca in memoria 

Il comando S (SEARCH, cerca) si dimostra spesso utile, non tanto per cercare stringhe, per le quali è perfettamente abilitato, ma soprattutto per cercare determinate sequenze di bytes; l'esperienza dimostra che con esso è possibile trovare tutti i punti di un programma in cui viene, per esempio, chiamata una certa procedura di sistema.Come è noto ogni istruzione è codificata con uno o più bytes, di solito un codice operativo e un operando; a forza di ficcare il naso nei programmi eseguibili con il buon vecchio debug non ci vuole molto tempo per imparare i principali accoppiamenti tra istruzioni e relativi bytes.Così, per esempio, può essere utile sapere in quali punti un dato programma cita l'istruzione INT 10H, codici CD 10; niente di più facile: basta coinvolgere questo comando specificando l'indirizzo (offset) iniziale e finale e la sequenza di bytes da cercare.L'immagine seguente mostra il risultato della ricerca in una zona di memoria in cui è stato caricato un programma che usava questa istruzione 4 volte:

-s 100 500 cd,1011A0:012011A0:01A011A0:024011A0:0300

Se la coppia di bytes non viene trovata il comando non produce (ovviamente) effetto: nel nostro caso, invece viene elencata la sequenza degli indirizzi in cui la coppia viene trovata. Non serve sottolineare che, in realtà, l'indagine da per certo il rilevamento della coppia di bytes richiesta, CD 10, in 4 punti (indirizzi) della memoria sottoposta a test; questo non significa che, in quei punti, sia presente l'istruzione INT 10H, ma la cosa è altamente probabile! Può succedere infatti che la sequenza dei 2 bytes sia quella di un operando o di qualche dato casualmente coincidente; per avere certezza del risultato è necessario analizzare anche i bytes nell'intorno dell'indirizzo scoperto dal comando S, sebbene, come detto, raramente si abbiano brutte sorprese!Il comando S è particolarmente versatile; come anticipato il suo terzo parametro può essere di diverso tipo; oltre alle sequenze di bytes possono essere cercate anche stringhe Ascii di qualunque lunghezza; la cosa è particolarmente utile per trovare, per esempio, la zona dei messaggi di un dato programma. L'esempio che segue riprende l'analisi della pagina dedicata al comando D , in cui si suggeriva la ricerca dei messaggi del dos: l'osservazione della figura mostra la presenza della parola "Inserire" in più posizioni ; vediamo come se la sbriga il comando S:

-s 0:0 L5000 'Inserire'0000:49AD0000:4A26

-d 0:49ad0000:49A0                                        49 6E 73 Ins0000:49B0 65 72 69 72 65 20 69 6C-20 76 6F 6C 75 6D 65 20 erire il volume0000:49C0 25 31 20 6E 75 6D 65 72-6F 20 64 69 20 73 65 72 %1 numero di ser

Favoloso: 2 parole presenti, 2 parole trovate! Il comando D conferma il rilevamento agli indirizzi trovati dal comando S. Come si può notare il comando è stato passato sotto forma di indirizzo iniziale, lunghezza. Per finire possiamo ricordare che, sebbene sia particolarmente ridicolo, l'indagine può essere condotta anche per la ricerca di un singolo carattere o di un singolo byte; per esempio avendo riempito di asterischi l'area

-s 200 205 '*'11A0:020011A0:020111A0:020211A0:020311A0:020411A0:0205

41

Page 42: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

Comando E -  Inserisce  valori in memoria 

Il comando E (ENTER, inserisci) consente di modificare il contenuto di una o più locazioni di memoria a partire dall'indirizzo (offset) passato come primo parametro; dopo di esso possono essere scritti uno o più valori esadecimali, separati da spazi o da virgole. Non appena il comando così strutturato viene confermato con Invio il primo valore va a sostituire quello della locazione indicata nel comando, il secondo sostituisce il contenuto della locazione successiva, e così via. L'esempio mostra l'effetto del comando su una zona di memoria preventivamente riempita di asterischi:

-d 100   prima del comando "e"1192:0100 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 2A 2A 2A ****************-e 100 10 20 30 40-d 100   dopo il comando "e"1192:0100 10 20 30 40 2A 2A 2A 2A-2A 2A 2A 2A 2A 2A 2A 2A . 0@************

Se l'indirizzo specificato è solo quello di offset i dati visualizzati si ritengono appartenenti al segmento di default, DS. Il comando E può essere dato senza la sequenza di bytes: questo metodo consente di modificare il contenuto della ram in modo più sicuro del precedente:

digitando E e confermando con Invio viene infatti mostrato l'indirizzo specificato seguito dal suo contento e da un punto: -e 100 1192:0100 10.

a questo punto, se si digita un valore esadecimale esso andrà a sostituire quello visualizzato a sinistra, ma solo quando l'operazione verrà confermata; le possibilità sono 2:

se, dopo aver digitato il nuovo numero (2a, nell'esempio che segue) si preme, per la conferma, il tasto Invio il processo di modifica ha termine e riappare il prompt del Debug (il trattino): -e 100 1192:0100 10.2a -

se, invece, per la conferma si preme lo spazio appare il contenuto della locazione successiva seguito ancora da un punto, e il processo può continuare con le stesse modalità; i nuovi valori digitati (nell'esempio: 2a 2b 2c 13 a2 11 35 5f) andranno a sostituire i vecchi (nell'esempio 10 20 30 40 2A 2A 2A 2A), non appena si deciderà di dare la conferma finale (sempre con la pressione del tasto Invio): -e 100 1192:0100 10.2a 20.2b 30.2c 40.13 2A.a2 2A.11 2A.35 2A.5f

da notare che, se si conferma il byte mostrato con spazio senza aver digitato alcun numero sostitutivo, il byte originale non subisce variazioni: , ma è ancora possibile intervenire sui valori successivi (sempre in attesa di confermare le eventuali modifiche con la pressione finale del tasto Invio): -e 100 1192:0100 10.2a 20.   30.   40.   2A.a2 2A.11 2A.35 2A.5f

Comando R -  Mostra il valore corrente dei Registri CPU

Il comando R (REGISTER, registri) senza parametri mostra il contenuto dei registri del processore; naturalmente si tratta di una simulazione o meglio del valore che avrebbero i registri CPU mentre si attende di cominciare l'esecuzione di un programma.

******** analisi con Symbolic Debug ***************************-rAX=0000 BX=0000 CX=0000 DX=0000 SP=ED5D BP=0000 SI=0000 DI=0000DS=1192 ES=1192 SS=1192 CS=1192 IP=0100 NV UP EI PL NZ NA PO NC

1192:0100 B83412 MOV AX,1234

******** analisi con Debug standard ***************************-rAX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000DS=0DE0 ES=0DE0 SS=0DE0 CS=0DE0 IP=0100 NV UP EI PL NZ NA PO NC0DE0:0100 B83412 MOV AX,1234

42

Page 43: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

L'immagine precedente si presta alle seguenti considerazioni: Tutti i registri"comuni" (quelli utente AX, BX, CX e DX, e quelli indice DI e SI, con BP) hanno valore

iniziale 0000H. La cosa è ragionevole: debug simula le condizioni ottimali; sebbene non sia indispensabile è bene pensare di iniziare l'esecuzione di un programma con i registri "puliti"

tutti i registri di segmento (CS, DS, SS e ES) hanno lo stesso valore; esso non è prevedibile e dipende esclusivamente dall'indirizzo della prima locazione libera in memoria nel momento in cui debug è stato allocato dal loader del dos. 

L'immagine mostra 2 valori nettamente diversi anche se cambia il debugger: con SymbDeb il valore è 1192H mentre con il Debug standard del Dos leggiamo 0DE0H ; questo sta chiaramente ad indicare che nel primo caso l'allocazione del Symbolic Debug ha consumato molta più memoria di quanta ne abbia richiesta il secondo. 

E' molto probabile che il valore che tu stai leggendo nella shell dos in cui provi i comandi che ti descrivo, sia a sua volta diverso da quelli mostrati in figura! ma la cosa non è per nulla importante: basta prendere atto che debug riserverà al programma che stiamo per collaudare un intero segmento, a partire dall'indirizzo logico CS:0000 (nel nostro esempio 1192:0000 o 0DE0:0000, pari all'indirizzo fisico 11920 o 0DE00).

Il puntatore di istruzione (IP) sarà lasciato sempre a 0100H, così come sarebbe in realtà se il programma sotto test fosse allocato in memoria senza la tutela del debugger. Abbiamo più volte sottolineato che il loader del Dos vuole per sè le prime 256 locazioni, per il Prefisso di Segmento di Programma (PSP).

Il puntatore di Stack (SP) ha sempre un valore piuttosto elevato, decisamente grande con SymbDeb, ED5DH, e più verosimile con il debug standard, FFEEH; se il programma da sottoporre a test non fosse ospitato il valore corretto sarebbe FFFEH, solo 2 locazioni sopra la fine del segmento. 

Il fatto che i valori imposti dai debugger siano maggiori fa pensare che essi stessi utilizzino una parte dello stack per motivi personali...Una trattazione a parte merita la visualizzazione dell'ultimo registro, quello dei flag (o delle flag, come piace a me, pensando ad esse per quelle che sono, delle bandiere, femminile!); esso è visualizzato in forma interpretata (zona gialla della figura precedente), cioè al posto dei bit significativi viene mostrata la sigla della flag corrispondente, in accordo con la tabella:

FLAG  SET    RESETOverflow Overflow OV si NV noDirection Direzione DN decremento UP incrementoInterrupt Interruzione EI abilitato DI disabilitato

Sign Segno NG negativo PL positivoZero Zero ZR si NZ no

Auxiliary Carry Riporto ausiliario AC si NA noParity Parità PE pari PO dispariCarry Riporto CY si NC no

Il comando RF mostra lo stato corrente delle otto flag documentate: se si vuole è possibile modificare una o più di esse, semplicemente specificando la sigla del nuovo stato, anche in ordine casuale:

-rfNV UP EI PL NZ NA PO NC - ov up di pl-rfOV UP DI PL NZ NA PO NC -zr-rfOV UP DI PL ZR NA PO NC –

Di solito il comando R  è utile per modificare il valore di un registro; per questo è necessario far seguire al comando la sigla del registro desiderato. Non appena si conferma con Invio viene proposto il vecchio attuale e, sulla linea successiva, appare il segno dei 2 punti, dopo il quale è possibile digitare il nuovo valore, da confermare ancora con Invio:

-r axAX 0000:1234-rAX=1234 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000

43

Page 44: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

Da notare che, con SymbDeb il nuovo valore si può dare direttamente dopo il nome del registro, mentre il debug standard segnala errore:******** con Symbolic Debug **************

Il comando R è molto utile e importante: ogni volta che si desidera ricominciare l'analisi e il collaudo di un programma è necessario obbligare il processore a puntare la prima istruzione: non è dunque possibile fare a meno del comando R IP seguito dal valore 0100 !

Prima di chiudere mettiamo in evidenza la buona disponibilità di questo comando: dopo aver mostrato il valore corrente di tutti i registri esso aggiunge (bontà sua...) anche l'indirizzo, i bytes e la stringa mnemonica dell'istruzione corrente (in celeste, nella prima figura della pagina) cioè dell'istruzione che sta per essere eseguita (puntata ovviamente da CS:IP).

Comando L -  Carica  il codice di un file eseguibile

Il comando L (LOAD, carica) carica in memoria un file di qualunque tipo; di solito viene dato senza parametri, dopo aver specificato il nome (e l'eventuale percorso) con il comando N, già discusso in precedenza; il file viene assunto in memoria rigorosamente a partire dall'indirizzo CS:0100H.

-n esegui.com-l

Il file caricato in memoria può essere di qualunque tipo (di testo TXT, di dati DAT, eseguibile COM o EXE) sebbene la potenza di debug sia meglio evidenziata nella gestione dei files di codice, come gli ultimi 2.Se, dopo il comando L, è specificato un indirizzo (offset) esso rappresenta la locazione a partire dalla quale viene caricato il file; naturalmente questo ha senso solo se il file è di tipo COM; un file EXE viene infatti sempre e comunque rilocato all'indirizzo specificato nel suo header!Se l'indirizzo specificato è solo quello di offset i dati visualizzati si ritengono appartenenti al segmento CSNon dimenticare che, dopo la copia del file è disponibile un numero a 32 bit che esprime la quantità di bytes caricati in memoria, lasciato nella coppia di registri BX,CX, rispettivamente parte alte e parte bassa.

Comando L -  Carica  i bytes di uno o più settori di un disco

Il comando L (LOAD, carica) è spesso utile anche per caricare in memoria uno o più settori di una memoria di massa (hard disk o floppy disk).In questo caso è conveniente specificare l'indirizzo (offset) in cui travasare i bytes richiesti, dopo il comando L e prima dei 3 parametri necessari per individuare i settori desiderati:

il primo è un numero che indica il disco da cui prendere i dati: 0 per il drive A, 1 per il drive B, 2 per il drive C, e cosi via...

il secondo è il numero (logico) del primo settore da caricare dal disco appena indicato; vale la pena soffermarci un po' su questo numero, sebbene sia argomento tipico dei dischi:

si tratta di un numero progressivo che parte da 0 e raggiunge il valore dato dal prodotto (N°Settori/Traccia)(N°Tracce)(N°Lati).

La numerazione di settori logici proseguirà in sequenza sulla medesima traccia (Cylinder) del lato (Head) corrente e proseguirà (in verticale) sulla stessa traccia del lato successivo fino all'esaurimento di tutte le facce disponibili; per riprendere, lato dopo lato, sulla traccia (cilindro) successiva, verso l'interno del disco. 

Questo modo logico di trovare i settori di un disco è tipico del DOS ed è diverso da quello assoluto/fisico usato dal BIOS e costituito dalla terna di numeri detta sinteticamente CHS (Cylinder, Head, Sector).

Così, per esempio, il primo settore fisico, il boot record, identificato dal numero 0,0,1, corrisponde al settore logico 0.

La tecnica BIOS (Settore fisico, basso livello) è senz'altro più utile di quella Dos (Settore Logico, alto livello); il passaggio dalla prima alla seconda è facilitato dalla seguente Formula:

N° settore logico = (N°Settore fisico - 1) + [N°Lato*(N°Settori/Traccia)]+[Traccia*(N°Settori/Traccia)*(N°Lati)]

La poco chiara numerazione logica dei Settori da parte del DOS è, per altro, estremamente efficace perchè consente al Sistema Operativo di accedere a qualunque disco, indipendentemente dalle sue caratteristiche hardware.

44

Page 45: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

il terzo e il numero di settori da caricare;  non è possibile leggere più di 80 settori, pari a 40k di memoria.

La possibilità di copiare interi settori di un disco è senza dubbio una situazione di straordinaria potenza. Sebbene non comporti grandi rischi conviene agire con discrezione, sicurezza e competenza: ti consiglio di fare le prove con un dischetto floppy e di toccare l'HD solo quando 6 ben certo di quello che fai.

Per restare in tema la seguente stringa carica il boot record di un floppy disk a partire dall'indirizzo (offset) 1000H, nell'unico segmento a disposizione di Debug; tutti i registri di segmento (CS, DS, ES, SS) sono infatti predisposti con lo stesso valore.La stringa si legge: carica (L), a partire dall'indirizzo 1000, dal disco 0 (driver A) il settore n°0 (il primo) nella quantità 1 (un solo settore, cioè 512 bytes):-l 1000 0 0 1 ; comando per leggere il Boot Record

Analogamente per analizzare le 2 copie della FAT (File Allocation Table) di un floppy disk da 1,44M, possiamo dare il comando seguente, che le copia a partire dall'indirizzo (offset) 1000H. Notoriamente ciascuna FAT occupa, in questo caso, 9 settori, subito dopo quello del boot record, analizzato in precedenza; perciò il comando sarà (per la prima copia di FAT): carica (L), a partire dall'indirizzo 1000, dal disco 0 (driver A), i settori a partire dal n°1 (il primo) nella quantità 9:-l 1000 0 1 9  ; comando per la   prima copia della FAT

oppure (per la seconda copia di FAT): carica (L), a partire dall'indirizzo 1000, dal disco 0 (driver A), i settori a partire dal n°10 (in exa 0AH) nella quantità 9: -l 1000 0 A 9  ; comando per la seconda copia della FAT

Se  vuoi continuare con questo gioco ricorda che, in un floppy disk da 1,44M, la directory occupa i 14 settori successivi alle 2 copie della FAT; è facile concludere che il comando da date sarà: carica dal disco 0 (driver A) i settori a partire dal n°19 (cioè 1+9+9=19, in esadecimale 13H) nella quantità 14 (in esadecimale 0EH):-l 1000 0 13 E  ; comando per leggere la Directory

Comando W -  Scrivi su disco il codice di un file eseguibile 

Il comando W (WRITE, scrivi) permette di creare un file (o sovrascriverlo, se già esiste) nella cartella corrente del disco; di solito viene dato dopo aver specificato il nome (e l'eventuale percorso) del file con il comando N, già discusso in precedenza; Se il comando è dato senza parametriSe l'indirizzo specificato è solo quello di offset i dati da scrivere si ritengono appartenenti al segmento CS.

Quando si usa il comando W per salvare il nostro lavoro in un file sul disco non bisogna dimenticare di caricare nei registri BX e CX la parte alta e bassa del numero a 32 bytes che indica la quantità di bytes da salvare!!

Il modo più semplice per calcolare il numero da mettere in BX,CX consiste nel prendere l'indirizzo di offset della locazione successiva all'ultima e sottrarre da esso il numero 0100H.

Se, dopo una sessione di lavoro abbiamo prodotto una codice eseguibile (o una tabella) di 200 bytes, al momento del salvataggio su disco dobbiamo eseguire, in sequenza, tutte queste operazioni:

dare un nome al file da creare (o sovrascrivere) scrivere in BX il valore 0000H e i CX il valore 00C8H (esadecimale di 200) finalmente scrivere e confermare il comando W:

-n miofile.com-r bxBX 0000:0000-r cxCX 0000:00c8-wScrittura di 000C8 byte in corso-

-n miofile.com-r bx 0000-r cx 00c8-wWriting 00C8 bytes-

45

Page 46: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

Se tutto va bene debug mostra il messaggio mostrato in figura (a sinistra con Debug standard e a destra con SymbDeb), e rimane in attesa di ulteriori comandi.

Comando W -  Scrivi i bytes di uno o più settori di un disco

Il comando W (WRITE, scrivi) è complementare al comando L , usato per caricare in memoria uno o più settori di una memoria di massa (hard disk o floppy disk); naturalmente serve per fare l'operazione opposta.La specifica dell'indirizzo (offset) da cui prelevare i bytes da salvare su disco, è dunque indispensabile: essa deve essere eseguita dopo il comando W e prima dei 3 parametri necessari per individuare i settori del disco da sovrascrivere:

il primo è un numero che indica il disco su cui scrivere i dati: 0 per il drive A, 1 per il drive B, 2 per il drive C, e cosi via...

il secondo è il numero (logico) del primo settore da sovrascrivere nel disco appena indicato; la descrizione di questo numero è già stata ampiamente discussa nella pagina precedente; non ci sembra il caso di ripeterla.

il terzo e il numero di settori da scrivere;  non è possibile leggere più di 80 settori, pari a 40k di memoria.

Ti prego di fare molta attenzione: la pratica del comando W è ad altissimo rischio!! Se usata con discrezione, sicurezza e competenza può rivelarsi uno strumento potente, ma non dimenticare che quando la usi ti comporti come un virus: cancelli e sostituisci parti del tuo disco!!Ti consiglio di fare le prove con un dischetto floppy e di non toccare l'HD, se non sei ben certo di quello che fai.

L'esempio mostra come scrivere su un floppy disk i 2kbytes (4 settori) attualmente presenti all'indirizzo CS:1000H; si legge: preleva a partire dalla locazione 1000, i bytes da scrivere sul disco 0 (driver A); il primo settore da sostituire è il 64 (valore esadecimale pari a 100) nella quantità 4 (4 settori, cioè 512*4 bytes = 2048 bytes = 2k):-w 1000 0 64 4 ; comando per scrivere 4 settori sul disco

Comando U -  Disassembla il codice di un file eseguibile 

Ecco la vera bomba! ... il comando U (UNASSEMBLE, disassembla): di solito ha senso solo dopo aver specificato il nome (con il comando N ) e caricato in memoria  (con il comando L ) un file eseguibile,  magari dopo aver pulito la memoria chiamata ad ospitarlo (con il comando F ); se viene dato senza parametri inizia a tradurre il bytes presenti in memoria a partire dall'indirizzo CS:0100H; il segmento di default è ovviamente quello di codice, CS.E' facile capire la potenza di questo comando: con esso si possono analizzare le istruzioni di qualunque file eseguibile, in primis quelli da noi prodotti, in fase di messa a punto o di ricerca delle rogne...Ma soprattutto (?!) quelli prodotti da altri (per esempio il tuo ben amato Autore...); l'ipocrisia è la peggiore delle essenze umane; i sepolcri imbiancati sono lo sfoggio della peggiore architettura...Naturalmente la "traduzione" in chiaro di un sorgente non è priva di intoppi e malizie: è il prezzo che bisogna pagare all'esperienza e al colpo d'occhio.

Il comando U prova comunque a tradurre in assembly i bytes che trova; se per qualche ragione il programma contiene tabelle o dati o messaggi (cosa estremamente probabile..) il risultato sarà del tutto illogico, cioè verranno mostrate sequenze di istruzioni assurde e scorrelate. Bisogna quindi saper localizzare le aree dati di un programma, escludendole dall'indagine con U a beneficio di quella con il comando D .

L'esempio mostra la sequenza di comandi adatti all'analisi del programma prova.com, usato nel capitolo 2 per esercitarci nella sua creazione; nella parte destra è riproposto il codice sorgente (prova.asm) mentre a sinistra si può osservare come viene interpretato dal comando U:-f 100 1000 00-n prova.com-l-u11A0:0100 B400 MOV AH,0011A0:0102 B003 MOV AL,0311A0:0104 CD10 INT 1011A0:0106 B400 MOV AH,00

_prog   SEGMENT BYTE PUBLIC 'CODE'        ASSUME CS:_prog,DS:_prog        ORG    0100HINIZIO: MOV    AH,00H   ;Pulisci lo schermo        MOV    AL,03H   ;(ClearScreen)        INT    10H      ;        MOV    AH,00H   ;Aspetta la pressione

46

Page 47: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

11A0:0108 CD16 INT 1611A0:010A B44C MOV AH,4C11A0:010C CD21 INT 2111A0:010E 0000 ADD [BX+SI],AL

        INT    16H      ;di un tasto        MOV    AH,4CH   ;Torna al dos        INT    21H      ;_prog   ENDS        END INIZIO

Osserviamo con calma il frutto di Unassemble: la pressione di U (ed ogni altra successiva) ha coinvolto almeno 16 bytes di memoria. l'indirizzo della locazione di partenza è CS:0100 (perchè è la prima volta) ma in generale è sempre dato

dal valore corrente di CS:IP. i bytes di ciascuna riga visualizzata appartengono ad una ben precisa istruzione, ad insindacabile

giudizio del debugger.

per ogni riga mostrata sono resi disponibili: l'indirizzo logico (CS:IP corrente) del primo dei bytes coinvolti. la sequenza dei bytes associati all'istruzione riconosciuta; di essi il primo è certamente un codice

operativo. dopo i bytes che codificano l'istruzione viene mostrata la loro interpretazione

mnemonica:

Non dimenticare: in ambiente Debug i numeri mostrati sono sempre esadecimali anche se non sono dotati della H finale!

in ogni caso il processo continua per tutti i bytes coinvolti, anche per quelli che non appartengono più al programma caricato in memoria; ne da dimostrazione l'ultima riga di disassemblato, nella quale i 2 bytes a 00H sono comunque ritenuti istruzione dal comando U (un'istruzione del tutto improbabile e illogica, almeno nel contesto precedente, ADD [BX+SI],AL).Ogni volta che si preme U il video si riempie con le istruzioni corrispondenti ai successivi 16 bytes.Se desideri rivedere la traduzione di bytes passati in precedenza è necessario usare il comando U con la specifica dell'indirizzo (offset) desiderato, per esempio U 100, per tornare a rivedere tutto! In certi casi (in particolare se si riesce a ridirigere la videata verso un file....) è conveniente passare 2 parametri, l'indirizzo iniziale e il numero (espresso con una L seguita dal numero esadecimale) delle istruzioni da dissassemblare; per esempio, conoscendo la lunghezza del programma è possibile evitare così la visualizzazione dell'istruzione fasulla:

-u 100 L711A0:0100 B400 MOV AH,0011A0:0102 B003 MOV AL,0311A0:0104 CD10 INT 1011A0:0106 B400 MOV AH,0011A0:0108 CD16 INT 1611A0:010A B44C MOV AH,4C11A0:010C CD21 INT 21

Naturalmente se si punta l'indirizzo  di un bytes operando (cosa probabile, quando si effettua un'analisi al buio...) il risultati sono imprevedibili, ma prima o poi il vero programma viene agganciato; l'esperienza aiuta a trovare il vero indirizzo iniziale; vediamo il significato di questa osservazione con l'analisi del programma precedente, puntato male:

-u 10111A0:0101 00B003CD ADD [BX+SI+CD03],DH11A0:0105 10B400CD ADC [SI+CD00],DH11A0:0109 16       PUSH SS11A0:010A B44C     MOV AH,4C11A0:010C CD21     INT 2111A0:010E 0000     ADD [BX+SI],AL11A0:0110 0000     ADD [BX+SI],AL11A0:0112 0000     ADD [BX+SI],AL

Ci vuole un bel po' per individuare le istruzioni vere (quelle a 010A e 010C) ma l'assurdità delle prime 3 istruzioni ci ha chiaramente messo sull'avviso che qualcosa è andato storto! Il buon comando U ci ha comunque provato.

47

Page 48: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

Comando A -  Crea un programma eseguibile 

Il comando A (ASSEMBLY, assembla) permette la creazione di programmi eseguibili anche in ambiente debug; si tratta di un esercizio senza futuro, al limite della paranoia, poco pratico e piuttosto complesso; la logica dei debugger (per esempio quella di richiedere numeri esadecimali senza la H finale) rende questo esercizio addirittura controproducente.La precedente ...esplosione di ottimismo per sottolineare di evitare l'uso proprio di questo comando.Anche l'uso per effettuare piccole correzioni locali è assurdo: si fa prima a tornare in editor , correggere, ricompilare e rientrare in debug con la nuova versione dell'eseguibile.Volendo trovare per forza una occasione utile possiamo pensare all'uso in una esercitazione sulla scrittura di istruzioni: poiché l'assemblatore del debug (cioè il comando A) è in grado di riconoscere gli errori, se la stringa digitata non è corretta viene segnalato errore.Vediamo dunque come si usa Assembly: non appena si conferma con Invio la lettera A, sulla riga successiva appare l'indirizzo puntato da CS:IP. La dove sta lampeggiando il cursore dovremo scrivere il codice mnemonico di una istruzione, confermando ogni volta con Invio.Solo quando riteniamo di aver finito bisogna premere Invio 2 volte di fila: si torna così al prompt del debug (il segno meno, a sinistra).Vediamo l'effetto di questo esercizio; sulla sinistra abbiamo scritto alcune istruzioni, decisamente a caso. Il debug, senza mostrarlo esplicitamente le ha compilate: l'unico segno del fatto sta nell'indirizzo successivo, effettivamente incrementato del numero presumibile di bytes associati a ciascuna istruzione.La verifica con il comando U (a destra) dimostra che in memoria sono stati effettivamente allocati i bytes corrispondenti alle istruzioni che abbiamo digitato:-a11A0:0100 mov ax,123411A0:0103 mov dx,567811A0:0106 add ax,dx11A0:0108 call 543211A0:010B jmp abcd11A0:010E-

-u 10011A0:0100 B83412 MOV AX,123411A0:0103 BA7856 MOV DX,567811A0:0106 01D0   ADD AX,DX11A0:0108 E82753 CALL 543211A0:010B E9BFAA JMP ABCD11A0:010E 0000   ADD [BX+SI],AL

Ecco la cosa utile: abbiamo imparato che il codice operativo di call 5432 è E8, quello di jmp abcd è E9; e così via.Come detto tutti i valori numerici devono essere intesi esadecimali (cioè non è necessario aggiungere la H finale, anzi è un errore!); in linea di massima tutte le istruzioni sono sostanzialmente identiche, con qualche distinguo. Per esempio:

debug riconosce DW e DB come fossero appartenenti al set dell'80x86 (in realtà sono macroistruzioni) riconosce i salti in modo automatico, in funzione della distanza del punto d'arrivo, e li codifica di

conseguenza corti (short, con 2 bytes) o vicini (near, con 3 bytes); da notare che, comunque, l'operando è un numero positivo relativo (al punto d'arrivo) e non assoluto

-a 1001192:0100 jmp 1101192:0102 jmp 10021192:0105 jmp 100

-u 1001192:0100 EB0E   JMP 01101192:0102 E9FD0E JMP 10021192:0105 EBF9   JMP 0100

in particolare il numero relativo codificato a fianco del codice operativo (EB o E9) è da ritenersi numero con segno:

positivo, se il salto si riferisce a locazioni successive a quella in cui viene richiesto (cioè in avanti); in questo caso si calcola escludendo i bytes delle istruzioni di partenza (certamente JMP ..) e di arrivo, cioè contando solo i bytes che vengono saltati; per esempio, se all'indirizzo 0100 troviamo l'istruzione JMP 0110 (codificata: EB0E) salta i bytes da 0102 a 010F compresi, cioè 14, appunto 0EH.

Addr Sequenza Bytes Istruzione

0100010201050108010B010E0110

EB 0EB8 22 11BB 44 33B9 66 55BA 88 7701 D801 D1 LabelNear:

JMP  SHORT LabelNearMOV AX,1122MOV BX,3344MOV CX,5566MOV DX,7788ADD AX,BXADD CX,DX

48

Page 49: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

negativo, se il salto si riferisce a locazioni prededenti a quella in cui viene richiesto (cioè indietro); in questo caso si calcola contando anche i bytes dell'istruzione di salto (2 o 3) e quelli dell'istruzione presente all'indirizzo in cui si salta; per esempio, se all'indirizzo 0105 troviamo l'istruzione JMP 0100 (codificata: EBF9) salta i bytes da 0106 a 0100 compresi, cioè 7 che, essendo negativo si esprime con il complemento a 2, per cui 00000111binario diventa 11111001, appunto F9H (in dettaglio: da 00000111binario  >> 11111000complemento a 1 >> 11111001complemento a 2 = F9H)

Addr Sequenza Bytes Istruzione

0100010101030105

90B0 55B4 AAEB F9

LabelNear; NOPMOV  AL,55HMOV  AH,0AAHJMP  SHORT LabelNear

da notare che, se il numero relativo è a 2 bytes, viene scritto in memoria con la solita tecnica Lo-Hi (prima la sua parte bassa e poi la parte alta); per esempio il salto in avanti JMP 1002, proposto nel riquadro iniziale all'indirizzo 0102, salta i bytes da 0105 a 1001 compresi, cioè una quantità espressa dal numero decimale positivo 3837, appunto 0EFDH, codificata quindi da E9FD0E.

I comandi più importanti del debugger sono certamente quelli descritti in questa pagina e nella successiva: la loro azione è rivolta decisamente al collaudo di un programma, cioè alla sua esecuzione controllata.

Benedetto sia Debug e il suo inventore!Se il tuo programma fa i capricci e il tuo umore assomiglia ad una notte senza luna, basta forzare l'esecuzione fino ad un certo punto sicuro (comando G ) e poi procedere a piccoli passi (comando T) evitando di eseguire (comando P ) le procedure personali (riconoscibili dallo mnemonico CALL) o di sistema (attivate dall'istruzione INT).L'errore salta fuori da solo, di solito con un ghigno di superiorità, per farti capire quanto sei frescone... Non dimenticare: 

il computer ha sempre ragione....per il semplice fatto che tu lo hai istruito

Comando T -  Traccia di un programma eseguibile 

Il comando T (TRACE, traccia) esegue una o più istruzioni; di solito viene usato senza parametri, al fine di eseguire l'istruzione corrente (cioè quella puntata da CS:IP); subito dopo visualizza automaticamente la nuova situazione dei registri e le informazioni relative all'istruzione cha sta per essere eseguita (indirizzo logico, codici associati e stringa mnemonica).La tecnica garantita da questo comando è nota come esecuzione passo-passo.Questo comando consente l'uso di 2 parametri, entrambi poco pratici (almeno dal mio punto di vista):

il primo consente di specificare l'indirizzo della prima istruzione da eseguire (P.es: T = 0112, notare il segno "uguale", mai usato finora...); anche volendo far partire l'esecuzione da un certo punto intermedio del programma l'effetto non è quello ottenibile nell'esecuzione passo-passo dall'inizio: verrebbe a mancare infatti l'influenza sui registri di tutte le precedenti istruzioni.

il secondo parametro è rischioso, se usato con sufficienza o scarsa attenzione; consente di eseguire di seguito più istruzioni, semplicemente indicandone il numero subito dopo  (P.es: T 12). Il rischio è di entrare dentro le procedure e perdere il filo del programma, specialmente se si entra in una INT di sistema.Dopo aver caricato il programma prova.com, usato nel capitolo 2 per esercitarci nella sua creazione, e dopo averlo visualizzato con il comando U (parte alta dell'immagine), possiamo vedete l'effetto dell'esecuzione passo-passo delle prime 3 istruzioni (parte bassa):-f 100 1000 00-n prova.com-l-u11A0:0100 B400 MOV AH,0011A0:0102 B003 MOV AL,0311A0:0104 CD10 INT 1011A0:0106 B400 MOV AH,0011A0:0108 CD16 INT 16

49

Page 50: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

11A0:010A B44C MOV AH,4C11A0:010C CD21 INT 2111A0:010E 0000 ADD [BX+SI],AL-tAX=0000 BX=0000 CX=000E DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000DS=11A0 ES=11A0 SS=11A0 CS=11A0 IP=0102 NV UP EI PL NZ NA PO NC11A0:0102 B003          MOV AL,03-tAX=0003 BX=0000 CX=000E DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000DS=11A0 ES=11A0 SS=11A0 CS=11A0 IP=0104 NV UP EI PL NZ NA PO NC11A0:0104 CD10          INT 10-tAX=0003 BX=0000 CX=000E DX=0000 SP=FFF8 BP=0000 SI=0000 DI=0000DS=11A0 ES=11A0 SS=11A0 CS=0212 IP=08A9 NV UP DI PL NZ NA PO NC0212:08A9 2E803EA70802  CMP Byte Ptr CS:[08A7],02          CS:08A7=00Osserviamo con calma cosa ci fornisce Trace:

la pagina si riempie di campi simili: in particolare possiamo seguire i cambiamenti dei registri dopo l'azione dell'istruzione appena eseguita; per esempio l'azione della prima T (esegue MOV AH,00) non cambia il registro AH (che è già a 00H) ma la seconda T (esegue MOV AL,03) produce il cambiamento di AL; si vede chiaramente che AX=0003H)

l'azione della terza T è una cosa inutile e sbagliata perchè ci obbliga a seguire il codice di una procedura di sistema (INT 10) di cui diamo per scontata l'esattezza; in questi casi bisogna stare attenti e dare, in vece, il comando P . 

Le istruzioni INT xx non vanno tracciate con il comando T, ma eseguite in blocco con il comando P; la loro traccia può essere interessante solo a fini didattici o di auto-istruzione, per vedere come sono fatte...

notare come l'azione della terza T abbia cambiato il registro IP in modo diverso e drastico rispetto ai prevedibili cambiamenti imposti dalle prime 2 tracce; anche il valore del registro di segmento ha assunto un valore diverso rimarcando il fatto che non siamo più dentro il nostro programma (o meglio nel segmento ad esso riservato dal debugger) ma Dio sa dove!...; l'indirizzo fisico è 029C9H, inferiore a quello 11B04H da cui siamo partiti e, dovendo essere una procedura video (di solito caratterizzata da indirizzi del tipo CxxxxH), qualcuno la ha rimappata nella parte iniziale della Ram.

Se per errore entriamo all'interno del codice di una INT è poi laborioso ritornare nel nostro programma: bisogna riportare sia CS che IP ai valori originali, sperando di non essere andati troppo avanti, cioè di non averli persi di vista irrimediabilmente...

Comando P -  Esegue le procedure di un programma eseguibile 

Il comando P (PROCEED, procedi) esegue un'intera procedura, di solito rappresentata dall'istruzione CALL xxxx o INT xyH:

nel primo caso si tratta di un sottoprogramma proprietario del codice eseguibile sotto test, normalmente allocato nel medesimo segmento di codice dell'istruzione.

INT rappresenta invece sempre una procedura di sistema, sempre esterna al segmento del nostro codice:

se è una funzione BIOS trova posto nella parte più alta del primo mega di memoria, nell'area fisica

che va dall'indirizzo F000H, a meno che non sia stata "rilocata" da programmi di gestione, come drivers o applicativi residenti in memoria. Capita spesso che la scheda video si appropri del vettore INT 10H, mappandone i servizi dentro la sua rom, dall'indirizzo C0000H

se è una funzione DOS è collocata nella parte bassa della memoria: un indirizzo verosimile è per esempio 0E000H

se è una funzione speciale (per esempio quelle del mouse, attivate con INT 33H) è allocata in posizioni non molto distanti da quelle del DOS, per esempio a 11000H

Dunque, quando il debug ci presenta una di queste istruzioni: è assolutamente necessario dare il comando P se non desideriamo esplicitamente entrare nella

procedura chiamata da CALL(per verificarne passo-passo il funzionamento). ci conviene dare il comando P per evitare di entrare nella procedura di sistema chiamata da INT

(verificarne passo-passo il funzionamento è inutile e controproducente).

50

Page 51: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

Questo comando consente anche di eseguire in blocco le istruzioni ripetute (quelle con prefisso REP) e le istruzioni gestite da LOOP: in questo caso può essere conveniente alternare questa possibilità a quella offerta dal comando T , più adatto per cercare e trovare imperfezioni durante l'esecuzione di queste procedure iterative.

51

Page 52: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

Comando G -  Esegue un programma

Il comando G (GO, vai!) esegue tutto il programma; se viene dato senza parametri inizia l'esecuzione del programma presente in memoria a partire dall'indirizzo CS:0100H; il segmento di default è ovviamente quello di codice, CS.Naturalmente l'esecuzione "diretta" (senza parametri) del programma non ha senso: per fare questo basta lanciare l'eseguibile dal prompt del Dos, senza scomodare il debugger.Lo scopo di G è quello di eseguire in blocco un certo numero di istruzioni, per poi proseguire passo-passo con il comando T o con il comando P; per fare questo è sufficiente aggiungere un indirizzo dopo la G, confermando con Invio; il programma sarà eseguito fino al punto indicato.La sequenza di azioni consigliata per la ricerca di malfunzionamenti è frutto dell'esperienza; personalmente seguo questo metodo:

mi procuro la stampa (su carta) delle istruzioni da esaminare, magari in forma LST (cioè complete di indirizzi offset e bytes associati alle istruzioni)

apro debug dal DOS e mi preparo l'ambiente migliore (pulizia con il comando F , caricamento del file con i comandi N e L , in sequenza)

scorro con il comando U , dato più volte, il codice disassemblato per verificare che quanto vedo coincide con il listato (cosa ovvia, se non ho commesso errori, quindi non del tutto scontata...)

dopo aver annotato l'indirizzo dell'istruzione successiva a quella fino alla quale voglio eseguire il programma (per esempio 010AH, nell'immagine della figura seguente) do il comando G 010A e confermo con Invio.

-f 100 6000 00-n prova.com-l-u1311:0100 B400   MOV AH,001311:0102 B003   MOV AL,031311:0104 CD10   INT 101311:0106 B400   MOV AH,001311:0108 CD16   INT 161311:010A B44C   MOV AH,4C1311:010C CD21   INT 211311:010E 0000   ADD [BX+SI],AL-g 10aAX=1C0D BX=0000 CX=000E DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000DS=1311 ES=1311 SS=1311 CS=1311 IP=010A NV UP EI PL NZ NA PO NC1311:010A B44C   MOV AH,4C  -

Da questo momento si prosegue con il comando comando T , osservando con estrema attenzione i nuovi valori dei registri (soprattutto quello delle flag).

Ti posso consigliare un altro modo molto gratificante di eseguire questo collaudo: torna momentaneamente in ambiente windows (con il tasto WINDOWS, o semplicemente con Alt-Invio): la pagina DOS in cui lavora debug con il programma eseguibile, Prova.COM, viene così costretta in una finestra, nel desktop.  apri un'altra finestra DOS (icona MsDOS o su quella Assembly, se disponi del mio ambiente...) e affiancala alla precedente. apri nella seconda finestra Qedit con il programma sorgente, Prova.ASM. esegui le procedure indicate sopra nella prima finestra e tieni d'occhio il codice sorgente corrispondente nella seconda!!!

52

Page 53: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

Quando utilizzi il comando G fai molta attenzione a specificare un indirizzo corretto, altrimenti rischi di mandare in crash il computer!!

Rimangono 3 comandi di usa marginale, che illustriamo per completezza.

Comando H -  Calcola la somma e la differenza dei valori specificati 

Il comando H (HEX, esadecimale) calcola e visualizza la somma e la differenza di 2 numeri esadecimali forniti dopo il comando; entrambi non possono essere più grandi di 4 cifre (e vanno specificati ovviamente senza la H finale).Vediamo alcuni esempi:-h 100 2000300 FF00

-h 23a 100033A 013A

-h 9876 1234AAAA 8642

-h ffff ffffFFFE 0000

Comando I -  Input da una porta 

Il comando I (INPUT, ingresso) esegue la lettura della porta specificata dal parametro e mostra, sulla riga successiva, il valore esadecimale letto.Vediamo un esempio (lettura del Registro di stato della porta parallela , 0379H):

-i 3790F-

Comando O -  Output da una porta

Il comando O (OUTPUT, uscita) spedisce un byte alla porta specificata dal primo parametro; il byte da trasmettere è passato come secondo parametro.Vediamo un esempio (scrittura del Registro di uscita della porta parallela , 0378H):

-o 378 ff-

E adesso, cosa fare?Se sei sopravvissuto alle pagine precedenti di questo paragrafo sai tutto del programma debug; in effetti esso merita di essere usato, come risulta dalle frequenti dichiarazioni d'amore sparse qua e là dal vostro vetusto Maestro...Importante è sapere dove e quando usarlo: debug non è un ambiente per tutte le stagioni.La sua ragione di vita è la verifica di programmi eseguibili, anche non nostri: l'esecuzione passo-passo di un programma può svelare segreti inarrivabili, tecniche di programmazione brillanti, idee originali, e perchè no?, chiavi d'accesso o procedure di protezione.

53

Page 54: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

La possibilità di indagare sull'insieme di bytes di un programma o di un file di altro tipo, permette di localizzare con facilità le zone di testo, modificandole a piacere per riadattarle alle nostre esigenze.

Se la lettura delle ultime 2 righe ti ha prodotto un certo formicolio, ricorda: Non fare agli altri quello che non vorresti fosse fatto a te!Il buon programmatore in Assembly (con buona pace per i detrattori ben pensanti) è consapevole della potenza che ha e che gestisce e si comporta con buona etica, da vero professionista.

Rinuncia fin d'ora al pensiero di usarlo per creare programmi: comincia subito a frequentare l'Ambiente Assembler descritto nel paragrafo 7 del Capitolo 2 ; debug verrà comodo nel momento in cui non saprai spiegarti dello strano difetto che fa il tuo programma... Con questo l'argomento è chiuso... Non ci resta che provare a programmare, con tanta fiducia nei nostri mezzi.

54

Page 55: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

  Il Processore e il Debugger LA GRANDE LIBRERIA

L'ultima parte del Capitolo 1 apre orizzonti impensabili, scopre le gemme più preziose del tuo computer.Impareremo a trovare e utilizzare tutte le risorse software nascoste negli angoli più intimi della memoria in dotazione.Alla fine potremo accedere a piacere a ciascuno dei libri della grande libreria e, dopo averne letto i preziosi capitoli, avremo il dominio assoluto!La metafora del libro, inteso come raccolta di procedure di sistema, ci accompagnerà per tutto il paragrafo: sorseggiane con calma il contenuto...Ne vale la pena!

La Grande Libreria

Adesso conosciamo con sufficiente sicurezza il motore della nostra automobile; mentre osserviamo l’immagine sul monitor del nostro computer esso sta già rombando a tutta potenza...La vita del microprocessore è un programma da eseguire, una sequenza logica di codici operativi; abbiamo già visto che le possibilità funzionali della CPU non sono particolarmente straordinarie: può fare alcune operazioni aritmetiche, poche funzioni logiche, determinate manipolazioni di numeri binari.Ma può eseguire tutto questo in un tempo impensabilmente piccolo rispetto alla nostra umana comprensione e questo fatto è sufficiente per mandare sonde spaziali ai confini dell’universo.I matematici sanno bene che il valore di una qualunque funzione può essere ottenuto con una somma di addendi particolari (sviluppo in serie), garantendo un risultato tanto più preciso quanto maggiore è il numero di elementi della somma stessa; è dunque solo questione di tempo e in questo il processore va a nozze!Tutti noi possediamo una calcolatrice e abbiamo notato che esegue talune operazioni in un lampo mentre per altre, più complesse, sembra che ci pensi...; la nostra utile amica non è altro che un piccolo computer “dedicato”, cioè specializzato nel calcolo di funzioni aritmetiche o matematiche.

La morale di questa storia porta a concludere che il microprocessore, pur alimentandosi di cose semplici, in virtù della sua velocità può colpire bersagli molto al di là della nostra immaginazione; serve solo qualcuno in grado di organizzare le sequenze di istruzioni in modo ottimale; serve la creatività della mente umana, senza la quale anche il tanto decantato processore rimane un semplice biscottino di sabbia compressa munito di zampe metalliche, sperduto aracnoide tra aracnoidi...

Quando diamo alimentazione il processore si risveglia e cerca di localizzare tra le risorse disponibili un programma da eseguire: con i suoi registri puntatori di programma (CS:IP) si accinge a puntare una locazione di memoria in cui deve assolutamente essere presente una speciale sequenza di istruzioni che provveda a caricare il più scontato tra i programmi ma al tempo stesso il più vitale e indispensabile: il Sistema Operativo.Questa fase, detta boot-strap, è piuttosto articolata e i dettagli attraverso i quali si sviluppa sono già stati ampiamente sottolineati in altra parte di questo Capitolo; sta di fatto che, dopo un breve frenetico susseguirsi di rumori e di messaggi, sul monitor appare la rassicurante immagine del nostro sfondo preferito: la macchina è pronta per partire; aspetta solo i nostri comandi.Qualche tempo fa, il monitor si stabilizzava su un'immagine in bianco-nero e l’unico segno di vita era un piccolo trattino, lampeggiante nelle vicinanze di una scritta (C:\>_), posta in basso a sinistra: il Prompt del DOS; ora della vecchia pagina nera è rimasto solo un polveroso ricordo..Il lettore curioso comincerà a farsi domande... Perchè la pressione di un tasto produce (spesso) la visualizzazione del carattere che appare su di esso? Perchè il movimento del mouse si tira dietro la piccola freccia? Perchè il click di un suo tasto può produrre l'emissione di un suono?Ma anche il perchè di operazioni più complesse come la ricerca, l’apertura e la chiusura di un file, la gestione dei dischi, la trasmissione dei dati verso una porta di sistema, seriale o parallela, e così via.Per ognuna di queste domande esiste una risposta di sistema, cioè un sottoprogramma in grado di assicurare il servizio con poca fatica da parte del programmatore; basta solo sapere dove è collocato, come richiamarlo e come fornirgli le informazioni necessarie per avere la massima soddisfazione.Il compito di utilizzare con profitto queste procedure interne sarà l’argomento principale delle pagine di questo Tutorial; basta ancora un po’ di pazienza.Ora ci occuperemo di localizzarle con certezza; una cosa sembra certa: esse non possono essere che in memoria perché solo così il microprocessore è in grado di “leggerle” e di metterle in pratica, indirizzandole al solito con i 2 registri puntatori di programma CS:IP.

55

Page 56: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

La memoria nasconde una grande libreria con almeno 2 o 3 capaci ripiani, con decine e decine di libri, ordinati e in bella mostra e a completa disposizione del processore; ciascuno di essi porta, per titolo, un numero progressivo a partire da zero, che noi impareremo ad esprimere subito in esadecimale, da 00H (0) a FFH (255).

Dove sono i libri della Libreria

L’immagine dello scaffale con tanti libri (prezioso mobile di casa...) non è poi così distante dal vero; ciascuno dei libri in esso riposti contiene una raccolta monografica di procedure, cioè sottoprogrammi in linguaggio macchina dedicati ad un preciso argomento.Avremo il libro che parla del video, quello dedicato alla tastiera, quello che si occupa della gestione dei dischi, ... e tutti porteranno sulla costa in vista uno strano titolo: un numero binario a 8 bit, espresso in esadecimale.Per questo lo scaffale potrà contenere fino a 256 libri (28), ma in realtà ne troveremo solo un centinaio: molti tra i possibili libri non sono ancora stati scritti o sono stati tolti perchè superati dal tempo...Ma quelli che rimangono sono una vera manna per il programmatore dei processori 80x86 e dei computer che li ospitano: in essi possiamo trovare le procedure già belle e pronte, curate in ogni minimo dettaglio per garantire il miglior utilizzo dell'oggetto al quale sono riferite.Il primo problema è dove trovare queste preziose risorse: all'inizio è impensabile che la memoria di sistema (la RAM) possa contenere qualcosa di utile, dato che essa è volatile, cioè perde i suoi dati ogni volta che il computer viene spento...D'altra parte sulla scheda madre è presente una memoria a sola lettura (ROM) contenente il Basic Input Output System, BIOS; poiché il contenuto di questa memoria è sempre disponibile (cioè non dipende dalla presenza o meno della tensione di alimentazione) è ragionevole pensare che il processore ne possa far uso in ogni momento e a sua (ehm, nostra...) completa discrezione.La memoria che ospita il BIOS (spesso impropriamente chiamata con lo stesso nome) è allocata nell'ultimo segmento (64k) del primo mega di memoria, cioè tra F0000H (=F000:0000) e FFFFFH (=F000:FFFF).

Dunque solo alcuni dei possibili 100 libri sono disponibili subito... Gli altri saranno aggiunti pochi istanti dopo, non appena il processore ha provveduto (su preciso insindacabile ordine) ad installare il Sistema Operativo e i suoi accessori (Drivers)

Di fatto il primo codice macchina che il processore si troverà ad eseguire, non appena comincia una nuova sessione di lavoro (appunto la procedura di boot-strap), sarà assunto dal BIOS, con il compito (tra l'altro...) di caricare in memoria il Sistema Operativo e di cedergli poi il comando.Ma questo programma non è il solo presente nel BIOS: in linea di massima per ogni oggetto importante collegato o collegabile con la scheda madre è garantita una procedura di servizio di default.

Il BIOS (raccolta di procedure di sistema) contiene il codice macchina necessario per far funzionare (quasi) tutto l'HardWare disponibile sulla (o visibile dalla) scheda madre, come timer di sistema, tastiera, interfaccia per il video, porta parallela e seriale, HD e FD, eccetera.

In linea di massima il computer potrebbe funzionare anche senza Sistema Operativo, con l'aiuto delle sole primitive del BIOS; naturalmente l'assenza si farebbe sentire. In particolare verrebbe a mancare completamente una delle sue funzioni principali: il File System, cioè la gestione dei files (creazione, apertura, scrittura, lettura, catalogazione in cartelle, gestione delle date di creazione o di aggiornamento, ...).E' quello che succede quando si utilizza il computer per il controllo di processi o di eventi, nel qual caso spesso ci troviamo di fronte al non facile compito di inventarci un nostro sistema operativo..Ma un computer senza SysOp (come Windows o DOS o Linux o altro) è una cosa rara per cui la sua presenza provvederà a completare l'allestimento e la dotazione della libreria: i libri aggiunti sono parte integrante del suo codice e saranno stabilmente disponibili nella memoria Ram, a disposizione sua e nostra, fino alla chiusura della giornata di lavoro...

Come trovare i libri della Libreria

Si pone ora il problema di poter accedere a ciascun libro; per ora è noto che ognuna delle possibili raccolte di procedure avrà un numero da 00H a FFH, nella logica binaria di un processore.I suoi astuti costruttori hanno pensato ad una apposita istruzione in grado di accedere a ciascuna di esse semplicemente passandole come operando il corrispondente numero.Questa istruzione è INT xyH, con xyH uguale ad uno qualunque dei possibili valori, tra 00H e FFH; si tratta di un'istruzione di chiamata di procedura, di norma costituita da 2 bytes (il codice operativo CDH e l'operando a 8 bit xyH).

56

Page 57: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

Il suo compito assomiglia a quello svolto dall'istruzione CALL address: la differenza sta nel fatto che questa è destinata a chiamare le nostre procedure (cioè quelle definite per nostro comodo nei nostri programmi sorgente) mentre INT xyH rende disponibili le procedure di sistema (cioè quelle predisposte dal costruttore nella BIOS o dal sistema operativo o dalle sue estensioni).Ma perchè, per puntare una procedura, INT usa un numero esadecimale a 8 bit invece di un indirizzo esplicito come invece fa CALL? Come è possibile? La risposta non è banale...Il processore deve poter ricostruire l'indirizzo dal numero e lo può fare solo con l'aiuto di una struttura appositamente inventata: la Tabella dei Vettori.Con riferimento al processore 8086 (o comunque al funzionamento in modo reale) si tratta di un'area posta esattamente all'inizio della memoria RAM convenzionale, cioè proprio nelle prime locazioni, da 00000H (=0000:0000) a 003FFH (=0000:03FF), destinata a raccogliere 256 puntatori  (detti anche Vettori), uno per ciascuna delle possibili raccolte di procedure (libri).Poiché ciascun puntatore è strutturato nella forma segment:offset (cioè coinvolge 4 bytes) l'area di memoria necessaria sarà di 1024 bytes (1k).

La Tabella dei Vettori ospita l'elenco degli entry-point (indirizzo logico, segment:offset) della locazione di memoria a partire dalla quale sarà disponibile il codice macchina di ciascuna delle possibili 256 procedure di sistema (i libri presenti nella grande libreria), catalogate progressivamente per titolo, da 00H a FFH.

Si tratta di una struttura dinamica, nel senso che qualunque software fatto girare successivamente (anche quelli prodotti da noi) può sostituire i vettori predisposti, purchè a ciascun nuovo puntatore sia associato anche un nuovo servizio alternativo funzionante!Il compito di trovare il vettore a partire dal numero n (binario a 8 bit) e di eseguire il codice puntato dal vettore spetta proprio alla potente istruzione INT xyH: in pratica:

moltiplica per 4 il numero n, localizzando la prima delle 4 locazioni della tabella nelle quali è ospitato l'indirizzo logico effettivo della procedura corrispondente.

estrae i 4 bytes, ordinati con la consueta logica Lo-Hi (cioè rispettivamente con il significato: Low OFFSET, High OFFSET , Low SEGMENT , High SEGMENT), e li copia nei 2 registri CS:IP.

in questo modo obbliga il processore ad eseguire la procedura di sistema desiderata.Naturalmente l'istruzione INT, detta Interrupt software, provvede anche ad altri compiti di contorno, descritti nella scheda ad essa dedicata, volutamente ignorati per non perdere d'occhio il nostro obiettivo.Per esempio se abbiamo bisogno delle procedure che controllano il video chiameremo INT 10H:

la CPU calcola il punto esatto della Tabella in cui è scritto il vettore corrispondente, moltiplicando per 4 il numero 10H, passato come operando (10H*4=00040H, 64 bytes sotto l'inizio)

quindi preleva dalle 4 locazioni consecutive (da 00040H a 00043H) i bytes in esse contenuti, e li trasferisce in CS:IP.

Se il vettore recuperato dalla tabella (e finito in CS:IP) fosse C31C:198A sarebbe stato rappresentato dalla sequenza dei seguenti bytes:

Vettore in Tabella byte0000:0040 8A0000:0041 190000:0042 1C0000:0043 C3

Che legame c'è tra la Tabella dei Vettori e le interruzioni?

Nella discussione del punto precedente è emersa la tecnica con cui il processore è in grado di svolgere un compito di sistema: quando, in un programma qualunque, è chiamato ad eseguire l'istruzione INT xyH è costretto ad interrompere il lavoro che stava facendo per occuparsi del servizio di sistema richiesto, per poi tornare alla fine a rioccuparsi del lavoro momentaneamente sospeso.Lo mnemonico INT è proprio l'abbreviazione della parola INTerrupt e sottolinea una delle tecniche più potenti ed efficaci in grado di obbligare il processore a fare cose diverse da quelle suggerite dal programma in esecuzione.

Di solito imporre un'interruzione significa intervenire a livello Hardware direttamente sul processore, al fine di obbligarlo a fare cose diverse (improrogabili o impellenti) rispetto a quelle del suo normale tran-tran; per questo sono previste delle apposite linee di controllo (dette linee di Richiesta d'Interruzione, IRQ, Interrupt ReQuest).

57

Page 58: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

In ogni istante della nostra esistenza siamo martellati da richieste d'interruzione, sebbene talvolta si possa far finta di non sentirle... Per questa ragione esistono interruzioni mascherabili e non mascherabili.Se, mentre Hercule Poirot sta inchiodando il colpevole (finalmente! dopo un'ora di attesa...), suona il telefono posso dire tra me e me: "adesso non ci sono... richiameranno tra un po'!": ho mascherato l'interruzione.Ma se nel medesimo momento mi scivola la tazzina di caffè bollente non c'è Agata che tenga.. salto su come una molla, nella speranza di minimizzare i danni: interruzione non mascherabile!La vita di un processore non è da meno; qualunque dispositivo esterno, come la tastiera o la porta seriale, può richiedere la sua attenzione (IRQ), pregandolo di sospendere l'attività corrente per assicurargli la dovuta procedura di servizio; lo farà ponendo un livello logico attivo su uno dei fili predisposti per questo, poco più di una decina.. La richiesta arriverà comunque ma la CPU potrà ignorarla se, da programma, abbiamo provveduto a mascherarla..: in sostanza per ogni possibile linea IRQ è disponibile un bit di stato che garantirà o meno il servizio richiesto in funzione del suo valore binario.Una sola di queste richieste sarà insindacabile: quella che coinvolge la linea NMI (Non-Maskable Interrupt); per essa non sono previsti bit di stato e il processore sarà costretto ad assecondarla!I dettagli sulle tecniche d'interruzione del processore sono argomento di un capitolo specifico del Tutorial e sono comunque spesso riprese nella parte del Sito dedicata ai dispositivi, come per la porta parallela o le stampantiIn questa sede è interessante sottolineare che, comunque, esiste un legame tra le linee IRQ di richiesta d'interruzione e l'istruzione INT xyH: di norma in risposta all'attivazione delle prime il processore mette in esecuzione automaticamente la seconda.In altri termini a ciascuna delle possibili richieste d'interruzione (IRQ o NMI) corrisponde una INT, o più precisamente una procedura predisposta dal sistema per il suo servizio; come vedremo più avanti, alcuni tra i possibili numeri esadecimali xyH da passare a INT serviranno proprio per puntare il programma che la Cpu sarà chiamata a svolgere in occasione di una richiesta d'interrupt.

Le potenti istruzioni INT xyH hanno questo nome proprio perchè sono in grado di produrre da software lo stesso effetto prodotto sul processore da hardware, con l'attivazione di una linea a ciò dedicata (come IRQ o NMI).

In altri termini le procedure forzate in risposta all'attivazione di IRQ o NMI possono essere messe in esecuzione anche senza l'effettivo intervento fisico sulla linea corrispondente e anche se il corrispondente bit di stato indicasse di mascherarla: basta l'esecuzione dell'istruzione INT relativa per simularne l'effetto da software.In linea generale, però, non è il caso di insinuare dubbi: la gran parte delle INT (Interrupt software) non ha alcun legame con le linee d'interruzione hardware: ciascuna di esse raccoglie comunque un insieme di funzioni generalmente orientate ad assicurare servizi legati al funzionamento o alla gestione del computer.

Perchè serve la Tabella dei Vettori?

Rimane da capire perchè i progettisti dell'80x86 hanno voluto ricorrere a questo complicato meccanismo, per poter rendere disponibili le risorse di sistema.La prima risposta è funzionale: al programmatore non serve ricordare l'improbabile, grosso (4 bytes...), numero esadecimale associato all'indirizzo logico della procedura di cui ha bisogno, e non gli importa neppure sapere in quale tipo di memoria (rom se legata al bios o ram se proveniente da SysOp o da drivers) sarà pescata..Per esempio se abbiamo bisogno delle procedure che controllano il video chiameremo INT 10H, e il servizio sarà garantito indipendentemente dal punto della memoria in cui il processore si troverà a lavorare; questo esempio è particolarmente significativo perchè sottolinea un'altra potente caratteristica della Tabella dei Vettori: la rilocabilità del servizio.In pratica la procedura di Boot è a conoscenza della zona BIOS in cui il servizio è garantito d'ufficio (è impensabile che il costruttore non abbia previsto gli strumenti necessari per scrivere messaggi a video..) e, non appena l'ha localizzata, ne trasferisce l'effettivo indirizzo in Tabella; ma quando il Sistema Operativo (che le subentra) si accorge della presenza di una moderna scheda video, sul bus AGP o PCI, provvederà ad installarne il driver in memoria e a metterlo in esecuzione.La presenza attiva del nuovo driver video renderà disponibile una propria procedura, ovviamente alternativa a quella di default e allocata in indirizzi propri della scheda video; per renderla disponibile a chiunque ne abbia bisogno, il driver stesso andrà a sostituire il vettore originale di default con quello nuovo di zecca, relativo alla memoria rom presente sulla scheda SVGA.

Dunque: l'uso di numeri a 8 bit (da 00H a FFH) virtualizza l'accesso alle possibili procedure di sistema (i libri della grande libreria), cioè ne consente l'uso anche senza la necessità di conoscerne l'effettivo indirizzo.

58

Page 59: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

Ma il vero problema è un altro!  Come è facile pensare, la quantità di codice macchina necessario per sviluppare un determinato servizio può subire, con il passare del tempo, una prevedibile dilatazione dovuta per esempio all’evoluzione tecnologica; si pensi emblematicamente alle modifiche subite dalla procedura che si occupa degli Hard Disk, chiamata molti anni fa a gestire memorie di massa da 20-40 MBytes e ora orientata al servizio di HD con capacità superiore ai 100 GBytes!!Dopo ogni modifica, se possiamo ritenere che il puntatore (Vettore) a questa procedura sia rimasto inalterato, dobbiamo renderci conto che l'aumento del suo numero di istruzioni ha spostato inevitabilmente verso il basso gli indirizzi iniziali di ciascun'altra procedura di servizio successiva.Tutti si incrementano di un numero pari a quello dei bytes aggiunti alla prima; tutti i Vettori di queste procedure dovranno essere cambiati!Poichè gli aggiornamenti del BIOS (ma anche quelli di un Sistema Operativo) sono imprevedibili e molto frequenti, l'indirizzo fisico (puntatore, Vettore) effettivo di ciascun libro può subire variazioni in ogni momento; per non parlare dei possibili diversi produttori di BIOS e di schede madri, ciascuno dei quali sarà chiamato a garantire il servizio a partire dagli oggetti da lui prodotti, inevitabilmente diversi da quelli della concorrenza...

L'accesso alle procedure di sistema (i libri della grande libreria), non può assolutamente essere eseguito saltando direttamente al rispettivo indirizzo: esso non è per nulla stabile nel tempo e la sua precarietà renderebbe inaccessibile la risorsa.

L'uso della Tabella dei Vettori risolve per sempre questo problema: la risorsa desiderata si ottiene (tramite INT xyH) specificandone il numero , assolutamente stabile e riconosciuto da tutto l'ambiente (produttori e programmatori).Sarà compito del produttore del BIOS (o del sistema operativo, o del driver) scrivere in tabella i giusti indirizzi delle procedure di sistema, probabilmente diversi da quelli della versione precedente, ma sicuramente associati agli stessi numeri esadecimali xyH.Per la descrizione dettagliata del contenuto e dei segreti della Tabella dei Vettori si rimanda all'apposita scheda; uno dei primi programmi che realizzeremo, non appena avremo sufficiente autonomia, sarà proprio Tabella.ASM, con il quale cercheremo di visualizzare il contenuto di questa preziosa area di memoria di sistema.Se lo desideri puoi comunque levarti fin d'ora questa curiosità scaricando qui http://www.giobe2000.it/../Tutorial/Exe/TABVETT.COM e provando la versione offerta dell'Autore.

Il Primo ripiano della Libreria

Il ripiano più basso della libreria contiene i libri destinati ad assicurare il facile utilizzo degli oggetti più vicini all’Hardware del computer.Per questa ragione sono per noi tra i più appetibili: costituiscono lo strato software più comodo per il controllo assoluto del nostro computer.Sotto di esso c'è solamente l'accesso diretto alle porte di input/output (o alla memoria) certamente più efficace ma anche un po' più complesso e, tra l'altro, ultimamente messo in discussione dai moderni sistemi operativi (vedi scheda dedicata alla porta parallela).Tra i libri più appetibili di questo ripiano troviamo quello che tratta la gestione del Video, caratterizzato dal numero 10H, della Tastiera (16H), della Stampante (17H), delle memorie di massa o Dischi (13H), delle porte Seriali (14H), dell’Orologio in tempo reale (1AH); con questo po' po' di menu non vediamo l'ora di cominciare... Ancora un po' di pazienza. E’ dunque possibile che il processore gestisca l’emissione di messaggi a video, o la lettura di dischi, o la richiesta di pressione di tasti, e così via, anche in assenza di un qualunque altro programma, come succede nei suoi primissimi secondi di vita.

La disponibilità dei libri di questo primo ripiano è di fondamentale utilità e costituisce l’interfaccia più comoda tra gli applicativi e l’Hardware, nel senso che, con la loro chiamata l’utente viene liberato dal gravoso compito di gestirli nel dettaglio.

Essa è sempre assicurata, anche in assenza del Sistema Operativo, proprio per il fatto che questo importante software, scritto in linguaggio macchina, è garantito dal costruttore della scheda madre con la presenza fisica della BIOS, termine gergale con cui si identifica la memoria a sola lettura (ROM) che contiene (tra l’altro) l’omonimo software, il Basic Input Output System, BIOS.Sebbene succeda spesso che il software (caricato durante e dopo la fase di boot-strap) sostituisca (rimappi) i vettori di questa categoria, puntando procedure di servizio alternative a quelle fornite d'ufficio nel BIOS, il processore chiamato ad eseguirle non se ne accorgerà nemmeno, per via della virtualizzazione assicurata dal loro numero, unico riferimento necessario a localizzarle.

59

Page 60: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

In buona sostanza basterebbero dunque solo questi libri per assicurare il completo controllo di un computer: si tratta dei primi 32 vettori, chiamati a puntare le procedure di servizio legate in parte al processore e in parte alle periferiche interne (sulla scheda madre), o collegate agli slot di espansione (ISA/EISA/PCI/AGP), o ai connettori di controllo (IDE/EIDE), o alle porte di comunicazione (seriale, parallela).Per completezza, ai 32 vettori storici (tra 00H e 1FH) possiamo metterne in conto anche qualche altro (per esempio quelli tra 70H e 77H), aggiunto in seguito per garantire i servizi resi necessari dalla naturale evoluzione del computer; vediamo di chiarire meglio le categorie dei servizi ottenibili passando ad INT xyH l'operando numerico corrispondente:

puntatori associati al servizio di interruzioni hardware interne, generate dal processore:Vettore in Tabella N° Vettore Funzione Assicurata

0000:0000 00H Errore di divisione per zero0000:0004 01H Single-Step, usato nel debugging0000:000C 03H Punto di Break (BreakPoint), usato nel debugging0000:0010 04H Errore di Overflow aritmetico0000:0018 06H Codice Operativo (OpCode) non valido / non definito0000:001C 07H Processore matematico non disponibile

puntatori associati al servizio di interruzioni hardware generate esternamente:

Vettore in Tabella N° Vettore Funzione Assicurata

0000:0008 02H NMI, Interruzione NON mascherabile0000:0020 08H IRQ0, Interruz. mascherabile dal Timer di Sistema0000:0024 09H IRQ1, Interruz. mascherabile dalla Tastiera0000:0028 0AH IRQ2, Interruz. mascherabile dal secondo gestore0000:002C 0BH IRQ3, Interruz. mascherabile dalla Seriale COM20000:0030 0CH IRQ4, Interruz. mascherabile dalla Seriale COM10000:0034 0DH IRQ5, Interruz. mascherabile dalla Stampante LPT20000:0038 0EH IRQ6, Interruz. mascherabile dal Floppy Disk0000:003C 0FH IRQ7, Interruz. mascherabile dalla Stampante LPT10000:01C0 70H IRQ8, Interruz. mascherabile Cmos0000:01C4 71H IRQ9, Interruz. IRQ2 Ridiretta0000:01C8 72H IRQ10, Interruz. mascherabile0000:01CC 73H IRQ11, Interruz. mascherabile0000:01D0 74H IRQ12, Interruz. mascherabile dal Mouse0000:01D4 75H IRQ13, Interruz. mascherabile dal Coprocessore0000:01D8 76H IRQ14, Interruz. mascherabile dal Disco Fisso0000:01DC 77H IRQ15, Interruz. mascherabile

puntatori associati al servizio di interruzioni software/hardware tipiche BIOS:

Vettore in Tabella N° Vettore Funzione Assicurata

0000:0014 05H HardCopy, servizio per il tasto Print Screen/Stampa0000:0040 10H Funzioni per la Gestione del Video 0000:0044 11H Determinazione della dotazione del computer 0000:0048 12H Determinazione della dimensione della Memoria 0000:004C 13H Funzioni per la Gestione dei Dischi 0000:0050 14H Funzioni per la Gestione delle Porte Seriali 0000:0054 15H Funzioni per la Gestione Estesa del Sistema 0000:0058 16H Funzioni per la Gestione della Tastiera 0000:005C 17H Funzioni per la Gestione della Stampante 0000:0060 18H Caricatore del Basic IBM residente (obsoleta)0000:0064 19H Esecuzione del Boot-strap da disco 0000:0068 1AH Funzioni per la Gestione dell'Orologio in Tempo Reale

0000:006C 1BH Procedura Utente per la Gestione della Tastiera (lanciata da INT 09H)

60

Page 61: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

0000:0070 1CHProcedura Utente per la Gestione del Timer di

Sistema (lanciata da INT 08H)

puntatori associati a Tabelle tipiche BIOS/ROM VIDEO:

Vettore in Tabella N° Vettore Funzione Assicurata

0000:0074 1DH Tabella di Inizializzazione dei Parametri Video0000:0078 1EH Tabella Base dei Parametri dei Dischetti0000:007C 1FH Tabella dei Caratteri Grafici Video (Set2)0000:0104 41H Prima Tabella Parametri Dischi Fissi0000:010C 43H Tabella dei Font Caratteri Grafici in Rom Video0000:0110 44H API rete o Tabella Font Caratteri Grafici0000:0118 46H Seconda Tabella Parametri Dischi Fissi

Il Secondo ripiano della Libreria

Il ripiano superiore della libreria contiene un'ulteriore serie di libri, tutti caratterizzati da un numero compreso tra 20H e 3FH; si tratta della raccolta dei servizi offerti dal Sistema Operativo Ms-DOS (Microsoft-Disk Operating System) e quindi la loro presenza è assicurata solo dopo che il computer ha ultimato con successo la fase di boot-strap.I titoli di tale ripiano trattano argomenti in grado di garantire l'intercessione e la corretta supervisione dell’Ms-DOS.Quando questo sistema operativo governava il mondo (con buona pace dei nobili Windows...) le funzioni DOS erano le uniche procedure di sistema in grado di affrontare e risolvere i problemi legati alla gestione software di un computer: con esse abbiamo imparato a gestire cartelle e files, passo indispensabile per organizzare ed elaborare i dati assunti con la gestione hardware assicurata dalle funzioni BIOS, descritte nella pagina precedente.Ms-DOS ha superato i vent'anni di vita, essendo stato rilasciato nel 1981: a differenza dei moderni sistemi operativi, che operano in ambiente grafico (cioè basato sul pixel) aveva (e mantiene, all'interno del programma shell di DOS) un'interfaccia di tipo testo (cioè basata sull'uso di caratteri), detta interfaccia a riga di comando per evidenziare la necessità di passargli il comando desiderato digitando da tastiera i caratteri corrispondenti (come DIR, CD, COPY, ...)Questo sistema operativo era costituito da 3 parti ben precise, 3 files necessari e sufficienti per garantire il funzionamento del computer che lo ospitava; ancora oggi questi 3 files sono i soli indispensabili in un dischetto Auto-boot, cioè in grado di far partire, se presente nel lettore A: prima dell'accensione, un computer in modalità DOS.Essi sono:

il file IO.SYS (noto anche come IBMIO.SYS nella versione fornita dall'IBM): era chiamato a fornire l'interfaccia tra il sistema vero e proprio (detto kernel e presente nel prossimo file) e le funzioni BIOS, notoriamente legate all'I/O; in altre parole ogni volta che il kernel aveva bisogno di servizi Bios li chiedeva ad IO.SYS che si occupava di farglieli avere; questa tecnica contribuiva a rendere la richiesta del sistema sempre meno vincolata all'hardware, sempre più virtualizzata.

il file MSDOS.SYS (noto anche come IBMDOS.SYS nella versione fornita dall'IBM): era il kernel, come detto, il sistema vero e proprio; il suo compito consisteva nell'assicurare il file system (cioè la gestione dei files su disco) e la gestione della memoria e dei processi; in pratica proprio la raccolta di procedure di sistema ospitate nel nostro secondo ipotetico ripiano di libreria, accessibili da programma con le istruzioni INT.

il file COMMAND.COM: era l'interprete dei comandi, la cosiddetta shell (=conchiglia); il suo compito consisteva nel controllare ogni comando che veniva digitato a destra del Prompt, la classica scritta C:\>_, da esso stesso prodotta; se i comandi digitati erano quelli previsti da una sua tabella interna provvedeva a metterli in esecuzione, interpretando eventuali altri comandi esterni come files, da caricare (suoi ospiti) nella zona di memoria RAM successiva a "se stesso" e da mettere in esecuzione (con l'aiuto della funzione exec), cedendo loro il controllo del processore.Oggi giorno tutto è più asettico ed oscuro... Le sanguigne funzioni DOS sono state sostituite da quelle della API ( Application Programming Interface) Windows, oggetti preconfezionati privi di stimoli, poco emozionanti, utilizzabili per creare un’applicazione certamente esteticamente più accattivante, ma poco gratificante dal punto di vista creativo..Ma per noi, inguaribili romantici (o passionali raziocinanti?) rimane il piacere della malta e del mattone... e finchè il grande Bill ci lascierà la monotòna, amata conchiglia, vi ci tufferemo senza freno, magna cum libido!

61

Page 62: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

In realtà i nostri programmi, creati con ampio riferimento a funzioni Bios e MsDOS, continueranno a funzionare egregiamente, ospitati da una shell messa a disposizione (bontà sua..) da Windows.

La shell di DOS è in pratica un programma che simula in tutto e per tutto il DOS originale, cercando di eseguire i compiti svolti, in quell'ambiente, dall'interprete dei comandi, cioè dalla terza delle sue 3 parti componenti, quella nota come Command.com.Vi si accede cliccando sull'icona "Ms-Dos" disponibile nel Menu d'Avvio: di solito dopo questa azione si apre una finestra dallo sfondo nero, in tutto e per tutto uguale all'interfaccia proposta dal DOS originale, espandibile a pieno schermo semplicemente premendo insieme Alt e Invio.

Fin tanto che la finestra non sarà chiusa (cliccando sulla X posta nel suo angolo in alto a destra oppure digitando il comando Exit, al prompt) tutto il lavoro sarà esattamente come quello svolto sotto la tutela del vecchio DOS, ospiti del suo interprete Command.com.

Vediamo di chiarire meglio le categorie dei servizi ottenibili passando ad INT xyH l'operando numerico compreso tra 20H e 3FH; è ormai appurato che si tratta di servizi DOS, cioè inevitabilmente caricati in memoria (dopo il boot-strap) con i 3 files IO.SYS, MSDOS.SYS e COMMAND.COM:

nel secondo ripiano della libreria appare subito evidente un libro nettamente più grande di qualunque altro: si tratta del numero 21H, il cuore di questo Sistema Operativo: con l’ingente quantità dei suoi “capitoli” (le funzioni DOS) descrive in ogni dettaglio la sua potenza, come la capacità di gestire i files su disco (File System), la possibilità di controllare l’uscita di dati verso il video (o, più genericamente, verso qualunque altra periferica come la stampante) e di riceverne dalla tastiera (o da altro oggetto in grado di garantire un ingresso dati come la porta seriale). Tra le funzioni DOS troveremo la risposta ad ogni possibile domanda riguardante l’organizzazione software del nostro computer.

Vettore in Tabella N° Vettore Funzione Assicurata

0000:0084 21H Funzioni generali del DOS (da Ms-DOS.SYS) 3 libri sono destinati a fornire l'indirizzo di importanti servizi di gestione interna:

Vettore in Tabella N° Vettore Funzione Assicurata

0000:0088 22H Procedura di Terminazione (da Command.COM)0000:008C 23H Gestione del Ctrl-Break (da Command.COM)0000:0090 24H Gestione degli Errori Critici (da Command.COM)

2 libri si occupano della scrittura e lettura assoluta dei dischi, operazione tanto potente quanto delicata:

Vettore in Tabella N° Vettore Funzione Assicurata

0000:0094 25H Lettura Assoluta dei Dischi (da Ms-DOS.SYS)0000:0098 26H Scrittura Assoluta dei Dischi (da Ms-DOS.SYS)

2 libri organizzano le procedure necessarie per farsi restituire il controllo da un programma eseguibile, quando ha finito il suo compito; il secondo Interrupt software è particolarmente importante, perchè consente di lasciare in memoria una parte del programma che sta per essere terminato:

Vettore in Tabella N° Vettore Funzione Assicurata

0000:0080 20H Terminatore di un programma (da Ms-DOS.SYS)

0000:009C 27H Termina il programma ma resta residente (Ms-DOS.SYS)

62

Page 63: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

Tutti gli altri sono sostanzialmente riservati al DOS per uso interno, sebbene nel tempo alcuni siano stati presi in prestito da altri per assicurare importanti servizi standard; di questi preferiamo parlare nella prossima pagina, dedicando loro un ripiano specifico:

Vettore in Tabella N° Vettore Funzione Assicurata

0000:00A0 28H riservato DOS - Stati d'attesa IDLE (Ms-DOS.SYS)0000:00A4 29H riservato DOS - (IO.SYS)0000:00A8 2AH riservato DOS - (Ms-DOS.SYS)0000:00AC 2BH riservato DOS - (Ms-DOS.SYS)0000:00B0 2CH riservato DOS - (Ms-DOS.SYS)0000:00B4 2DH riservato DOS - (Ms-DOS.SYS)0000:00B8 2EH riservato DOS - (Ms-DOS.SYS)0000:00BC 2FH riservato DOS - Vedi pagina seguente0000:00C0 30H riservato DOS - (Ms-DOS.SYS)0000:00C4 31H riservato DOS - (Ms-DOS.SYS)0000:00C8 32H riservato DOS - (Ms-DOS.SYS)0000:00CC 33H riservato DOS - Vedi pagina seguente0000:00D0 34H riservato DOS - (Ms-DOS.SYS)0000:00D4 35H riservato DOS - (Ms-DOS.SYS)0000:00D8 36H riservato DOS - (Ms-DOS.SYS)0000:00DC 37H riservato DOS - (Ms-DOS.SYS)0000:00E0 38H riservato DOS - (Ms-DOS.SYS)0000:00E4 39H riservato DOS - (Ms-DOS.SYS)0000:00E8 3AH riservato DOS - (Ms-DOS.SYS)0000:00EC 3BH riservato DOS - (Ms-DOS.SYS)0000:00F0 3CH riservato DOS - (Ms-DOS.SYS)0000:00F4 3DH riservato DOS - (Ms-DOS.SYS)0000:00F8 3EH riservato DOS - (Ms-DOS.SYS)0000:00FC 3FH riservato DOS - Gestore di Overlay (Ms-DOS.SYS)

Gli altri ripiani della Libreria

Possiamo chiudere l’immagine fantastica della libreria pensando che possa disporre di ulteriori ripiani; nella norma questo non è un dato certo ma molto probabile.Ci sono delle estensioni del Sistema Operativo, cioè degli oggetti che non sono stati previsti al suo interno ma di cui è consuetudine disporre: sono i cosiddetti Driver di Dispositivo.Ai tempi del DOS venivano collocati nella RAM subito dopo il Sistema stesso, con l’aiuto delle voci del file di configurazione CONFIG.SYS; la loro presenza in memoria era latente, silenziosa, ma pronta ad intervenire ogni qual volta gli applicativi ne facevano richiesta (naturalmente mediante una chiamata INT).Il meccanismo d'installazione di un driver (ancora oggi praticabile in ambiente DOS) consisteva nell'eseguire un programma COM contenente il codice macchina delle funzioni da rendere disponibili a tutti; il suo compito era quello di un razzo vettore chiamato a mettere in orbita un satellite: veniva fatto terminare senza fare altro se non collocare le funzioni in memoria Ram.Per questo questi preziosi eseguibili erano (e sono) noti con il nome di TSR (Terminate and Stay Resident, termina ma lascia una parte residente in Ram).In alternativa (ai tempi del DOS) era possibile ottenere lo stesso servizio costringendo il sistema ad eseguire files specifici, con estensione SYS, elencati nel file Config.sys, a sua volta processato in fase di boot-strap.Ora sono risorse condivise organizzate direttamente da Windows (o chi per lui..); ma quando siamo in una shell di DOS sono comunque visibili, ancora a nostra disposizione, con grande nostra soddisfazione, come vedremo...Il driver più noto è più ricercato dagli applicativi è certamente il Gestore del Mouse: ad esso è ormai universalmente riconosciuto il vettore (Interrupt Software) INT 33H, al quale corrisponde una succulenta raccolta di funzioni, ampiamente usata nella Sezione Pascal (si vedano i sorgenti delle Procedure e delle Funzioni dedicate alla Gestione del Mouse ):

Vettore in Tabella N° Vettore Funzione Assicurata

63

Page 64: Corso Assembler - risorsegratuite.org  · Web viewIl suo contenuto non è da utilizzare nella consueta forma di word, ... Gli anglosassoni sono molto immediati nel definire i concetti

0000:00CC 33H Gestore delle funzioni del MouseTra gli altri vettori (Interrupt Software) riconosciuti da tutti (produttori e utenti) meritano una citazione:

il gestore INT 15H della memoria estesa, la XMS, Extended Memory Specification, intesa in generale come quella eccedente il primo mega; la gestione della memoria è assolutamente diversa da quella assicurata dalla EMS (vedi sotto), ma lo scopo è il medesimo. Di solito il driver chiamato a questo compito era HIMEM.sys, lanciabile esclusivamente da Config.sys.

Vettore in Tabella N° Vettore Funzione Assicurata

0000:0054 15H Gestore della Memoria Estesa, XMS il gestore INT 67H della memoria espansa, la EMS, Expanded Memory Specification, nato per consentire

al povero 8086 di riconoscere una quantità di memoria superiore a quella da esso indirizzabile (solo un mega...): la tecnica era quella di far trasferire in posizione fissa standard (dentro il primo mega) più blocchi di memoria, uno alla volta, di solito allocati su apposito hardware aggiuntivo esterno. Con l'avvento dei processori in grado di indirizzare direttamente la memoria superiore al 1° mega (detta memoria estesa), il problema è diventato quello di simulare la memoria espansa in quella estesa; di solito il driver chiamato a questo compito era EMM386.exe (anch'esso lanciabile esclusivamente da Config.sys).

Vettore in Tabella N° Vettore Funzione Assicurata

0000:019C 67H Gestore della Memoria Espansa, LIM EMS 4.0 il gestore INT 2FH detto Multiplexer DOS, il cui compito è quello di offrire un entry-point a diversi

dispositivi TSR, di solito identificati passando un numero in AH, cercando di organizzarli al fine di minimizzare i possibili conflitti, tanto più numerosi quanto maggiore è la loro quantità. Non sempre i servizi assicurati da questa funzione sono attendibili e documentati; alcuni sono dedicati al DOS (per la gestione di comandi come Print, Assign, Append, Driver,Share, Graphics, Graftabl, Display, Mscdex, Ansi,..), ma anche per il driver della memoria estesa (Himem, Xma2Ems) o per quelli delle reti (Novell Netware IPX, Lan Receiver, ...).

Vettore in Tabella N° Vettore Funzione Assicurata

0000:00BC 2FH Multiplexer DOS

E adesso, cosa fare?

Dopo una decina di pagine sull'onda della metafora possiamo concludere che il nostro personal computer è effettivamente un oggetto pieno di risorse.Molte di queste risorse sono utilizzate in background... La gran parte dei suoi utenti non se ne rende nemmeno conto.. Non ha tempo di sapere perchè e come... basta che il servizio richiesto venga assicurato al meglio e nel più breve tempo possibile: (ahimè..) tutto e subito!La gran parte dei suoi utenti non si rende conto che il funzionamento del suo computer è assicurato e regolato dalla competente intercessione del Sistema Operativo; e magari si infastidisce quando, all'acquisto del suo nuovo fiammante giocattolo, si ritrova questa voce nella nota spese..Se mamma INTEL ha creato il processore, modellandolo nella creta, lo zio Bill gli ha soffiato sopra, dandogli la vita! (e tutto ciò con buona pace della concorrenza, in un senso e nell'altro..)

Il processore è il cervello del nostro computer; tutto il resto gli da vigore e forza potenziale... Ma l'anima gli viene dalle sue risorse software, il Bios e il Sistema Operativo.

Al termine di questo capitolo sappiamo con chi avremo a che fare (il processore e il suo mondo), ma abbiamo scoperto anche l'esistenza di decine e decine di programmi di gestione (funzioni Bios e Dos) già pronti e, soprattutto, dove sono e come poterli utilizzare (interruzioni Software, INT).Nel prossimo Capitolo 2 parleremo degli strumenti di lavoro, i programmi e i metodi per avvicinarci alla programmazione, per sfruttare al meglio le nostre giovani conoscenze...E poi, finalmente, prenderemo il volo!

64