5 Dec 2019 - 21:43--=[Computer]=----=[Computer]=----=[Musica]=----=[Musica]=----=[Geometra]=----=[Geometra]=----=[Download]=----=[Download]=----=[Link]=----=[Link]=----=[Articoli]=----=[Articoli]=--
Indice Computer Computer/ Software/ Organizzazione Software - 4/


Parte |1|2|3|4|


Descriviamo adesso alcuni semplici programmi, con lo scopo di illustrare l'utilizzo delle istruzioni del processore. Nei programmi non verrà considerato il problema dell'ingresso dei dati e dell'uscita dei risultati (di questo ne parleremo, se avrò il tempo di farlo, nei linguaggi di programmazione nella sezione assembly). Al momento supporremo quindi che i dati si trovino già in memoria (come del resto anche il programma), e che i risultati vengano lasciati in memoria. I contenuti delle locazioni, delle doppie locazioni o delle quadruple locazioni di memoria destinate a contenere i dati o risultati saranno indicati semplicemente con le parole BYTE, WORD e LONG, rispettivamente.
Nello scrivere programmi, è necessario conoscere la lunghezza delle varie istruzioni macchina. A questo scopo, supponiamo che le istruzioni del processore PS siano codificate come le istruzioni macchina dei processori presenti nel Personal Computer (a partire dal 386).


Conteggio del numero di bit a 1

Il programma che esamineremo conta quanti bit di valore 1 sono presenti in un certo numero (dato da elaborare). Si suppone che il dato (una parola) si trovi nella doppia locazione di indirizzo 00000100, e che il risultato (un byte) sia lasciato nella locazione di indirizzo 00000102. Il programma, che inizia dalla locazione di indirizzo 00000200, utilizza CL come contatore (CL è inizialmente azzerato) e copia il dato da elaborare nel registro AX. Viene poi eseguito un ciclo, nel quale viene inizialmente verificato che il contenuto di AX sia uguale a zero: in caso affermativo il programma termina memorizzando il contenuto di CL, altrimenti viene effettuata una traslazione a sinistra del contenuto di AX (con spostamento del bit più significativo nel flag CF). Viene quindi effettuato il test di CF e, se uguale a 1, viene incrementato il contenuto di CL. In ogni caso si torna all'inizio del ciclo.

Visualizza esempio pratico


Somma degli elementi di un vettore

Il seguente programma somma gli elementi di un vettore. Il numero di elementi (una parola) si trova nella doppia locazione di indirizzo 00000102, il vettore (i cui elementi sono lunghi ciascuno una parola) si trova a partire dalla doppia locazione di indirizzo 00000104, mentre il risultato (una parola) verrà posto nella doppia locazione di indirizzo 00000100. Si suppone che durante l'operazione di somma dei vari elementi non si generi mai un riporto (se gli elementi sono di tipo naturale) o un traboccamento (se se gli elementi sono di tipo intero).
Il programma inizia dall'indirizzo 00000200. Il registro AX, inizialmente azzerato, viene utilizzato come accumulatore per la somma dei vari elementi. Il registro CX viene utilizzato come contatore del numero di cicli: viene inizializzato con il numero di elementi del vettore, e decremento dopo ogni somma, fino a che il suo contenuto non diviene uguale a 0. Il registro EBX viene utilizzato come registro puntatore per riferire in sequenza tutti gli elementi del vettore: esso viene inizializzato con l'indirizzo del primo elemento del vettore, e a ogni ciclo viene incrementato di due (lunghezza in byte di un elemento) per puntare all'elemento successivo.

Visualizza esempio pratico


Somma di due vettori elemento per elemento

Il sefuente programma somma gli elementi di un vettore vett1 con i corrispondenti elementi di un altro vettore vett2, ponendo il risultato al posto di vett1. Il numero di elementi dei due vettori (un byte) è contenuto nella locazione di indirizzo 00000101, mentre i due vettori (aventi elementi del tipo intero lunghi una parola) sono memorizzati a partire dalle doppie locazioni di indirizzo 00000102 e 00000202, rispettivamente. Nel caso in cui la somma fra due componenti corrispondenti generi overflow, nella cella di indirizzo 00000100 viene posta la quantità FF (e il programma termina), altrimenti in questa cella rimane la quantità 00.
I due vettori vengono sommati eseguendo un ciclo controllato dal contenuto del registro CL. Il contenuto di tale registro, inizializzato con il numero di elementi dei vettori stessi, viene decrementato dopo la somma di sue elementi corrispondenti, e se rimane diverso da 0 il ciclo viene ripetuto. Gli elementi dei vettori vengono riferiti in sequenza, utilizzando l'indirizzamento a registro indice. Il registro che funge da registro indirce è EBX: esso è inizializzato a 0 e a ogni ciclo viene incrementato di due (lunghezza in byte di ogni elemento dei vettori). Le istruzioni (due) che riferiscono in sequenza gli elementi di vett1 hanno come spiazzamento l'indirizzo di partenza 00000102, mentre l'istruzione che riferisce in sequenza gli elementi di vett2 ha come spiazzamento 00000202.

Visualizza esempio pratico


Sottoprogrammi

Un sottoprogramma realizza un procedimento di calcolo che può essere utilizzato in punti diversi di una stesso programma principale, con dati di volta in volta differenti. L'esecuzione di un sottoprogramma si ottiene attraverso l'esecuzione di un'apposita istruzione chiamata (CALL), la quale provvede a salvare in pila il contenuto attuale del registro EIP prima di effettuare il salto al sottoprogramma stesso: poichè il registro EIP contiene ad ogni istante l'indirizzo dell'istruzione sequenzialmente successiva rispetto a quella in esecuzione, in pila verrà memorizzato l'indirizzo dell'istruzione che si trova dopo la CALL. Un sottoprogramma deve terminare con la particolare istruzione RET, la quale estrae la parola lunga dalla pila e la trasferisce nel registro EIP: se al momento dell'esecuzione dell'istruzione RET la pila si trova ancora nella stessa situazione in cui è statalasciata dall'istruzione CALL, avviene un ritorno al programma chiamante all'istruzionee successiva rispetto a quella chiamata.
I dati attuali su cui il sottoprogramma deve operare, come pure i risultati prodotti dal sottoprograma (argomenti o parametri) possono essere passati (trasmessi) o attraverso registri generali o tramite la pila: in entrambi i casi il programma chiamante, prima di effettuare l'istruzione CALL, deve provvedere a ricopiare i parametri stessi nei registri o nella pila e, dopo l'istruzione CALL (al termine del sottoprogramma), a prelevare dai registri o dalla pila i risultati prodotti dal sottoprogramma.
Un parametro può essere costituito, oltre che da un valore, da un indirizzo: in questo il sottoprogramma può prelevare direttamente un dato dalla locazione di memoria in cui si trova, o depositare un risultato nella locazione di memoria dovuta.
Illustriamo adesso due semplici sottoprogrammi, che utilizzano le tecniche di trasmissione dei parametri anzidette.


Somma degli elementi di un vettore: parametri nei registri

Il seguente programma è composto da un programma principale e da un sottopramma. Il sottopramma esegue la somma degli elementi di un vettore (ciascuno lungo una parola): il numero di elementi è contenuto nel registro CX, l'indirizzo del primo elemento è contenuto nel registro EBX e il risultato della somma viene lasciato nel registro AX. Il programma principale chiama due volte il sottoprogramma, per operare su due differenti vettori: prima di ogni chiamata esso provvede a passare i parametri al sottoprogramma, ossia ricopiare in CX il numero di elementi del vettore in EBX l'indirizzo del primo elemento; analgogamente , una volta terminano il sottoprogramma, esso provvede a trasferire a trasferire il risultato da AX in memoria.
Il primo vettore (vett1) è memorizzato a partire dalla doppia locazione di indirizzo 00000106, il numero di elementi si trova nella qudrupla locazione di indirizzo 00000102, e il risultato della somma verrà messo nella doppia locazione di indirizzo 0000100. Anagolamente, il secondo vettore (vett2) è memorizzato a partire dalla doppia locazione di indirizzo 00000206, il numero di elementi si trova nella quadrupla locazione di indirizzo 00000202, e il risultato della somma verrà messo nella doppia locazione di indirizzo 00000200. Il programma principale è composto da due sequenze di istruzioni simili (che iniziano rispettivamente dalle locazioni di indirizzo 00000300 e 00000340), ciascuna della quali esegue il passaggio di parametri, la chiamata del sottoprogramma e la memorizzazione del risultato. Il sottoprogramma, che inizia alla locazione di indirizzo 00000400, utilizza EBX come registro puntatore per riferire i vari elementi del vettore, ECX come registro contatore e AX come registro accumulatore.

Visualizza esempio pratico


Somma degli elementi di un vettore: partametri in pila

Questo programma è analogo al precedente. La differenza sta nel fatto che i parametri sono trasmessi dal programma principale al sottoprogramma utilizzando la pila, invece dei registri (vedi figura sotto). Tale tecnica, più generale della precedente, consente di passare un numero comunque alto di parametri (e di realizzare facilmente sottoprogrammi ricorsivi).

Pila

Prima di ogni chiamata, il programma principale mette nella pila (nell'ordine) il numero di elementi del vettore, l'indirizzo del primo elemento del vettore e l'indirizzo del risultato. Effettua quindi l'istruzione di chiamata, e, terminato il sottoprogramma, provvede a ripulire la pila, togliendo da essa i parametri (questo viene effettuato incrementando opportunatamente ESP).
Il sottoprogramma preleva i parametri dalla pila utilizzando l'indirizzamento modificato con registro base. Più precisamente, dopo aver salvato il contenuto EBX, il sottoprogramma ricopia in tale registro il valore attuale ESP. Rispetto a tale base, gli spiazzamenti che individuano i vari parametri sono quindi i seguenti (vedi figura): 08 per l'indirizzo del risultato, 0C per l'indirizzo del primo elemento del vettore e 10 per il numero di elementi del vettore. Il sottoprogramma provvede a salvare (e a ripristinare alla fine) anche gli altri registri che utilizza.

Visualizza esempio pratico


Modello di una semplice interfaccia

Un'interfaccia è un'unità che colloquia da un lato con il processore comportandosi come una piccola memoria, e dall'altro con un dispositivo esterno (trasduttore) secondo protocolli (in genere) standard.
Da un punto di vista funzionale, un'interfaccia semplificata appare come un'insieme di porte (dette anche registri) a 8 bit. Al momento ci riferiamo a una gestione a controllo di programma, e supponiamo che l'interfaccia stessa abbia tre soli registri interni, detti RBR, TBR e STR (vedi figura sotto).

Interfaccia

Il registro RBR (Receiver Buffer Register) serve per memorizzare un byte proveniente dal trasduttore esterno, che dovrà poi essere prelevato dal processore. Il registro TBR (Transmitter Buffer Register) serve per memorizzare un byte proveniente dal processore, che sarà poi spedito al dispositivo esterno. La funzione del registro STR (Status register) è quella di specificare se è o meno in corso un trasferimento dati tra interfaccia e dispositivo.
Le interfaccie vengono tipicamente posizionate nello spazio di I/O.
L'invio di informazioni (generalmente sequenze di byte) da un dispositivo esterno al calcolatore comporta quindi un trasferimento di byte dal dispositivo al registro RBR, e un trasferimento di byte dal registro RBR al processore. Similmente, l'invio di informazioni (generalmente sequenze di byte) da un calcolatore a un dispositivo esterno comporta un trasferimento di byte dal processore al registro TBR, e un trasferimento di byte dal registro TBR al dispositivo.
Il processore PS utilizza il registro AL pre scambiare byte con i registri di un'interfaccia semplificata: il trasferimento di un byte avviene mediante l'esecuzione di un'istruzione INB o di un'istruzione OUTB.
I trasferimenti di byte dal dispositivo al registro RBR e dal registro TBR al dispositivo avvengono invece via hardware, ad opera dell'interfaccia stessa. Più precisamente nel registro di stato STR sono presenti due flag, FI (bit n0) e FO (bit n1), che indicano quando il buffer di ingresso è pieno o il buffer di uscita è vuoto, rispettivamente: quando FI vale 1, un nuovo byte è stato trasferito dal dispositivo esterno all'interfaccia, ed è disponibile per il programmatore nel registro RBR, mentre quando FO vale 1, il byte precedentemente immesso dal programmatore nel registro TBR è stato trasferito dall'interfaccia al dispositivo esterno. Pertanto, solo quando il flag FI vale 1, il programmatore puù correttamente prelevare un nuovo byte dal registro RBR dell'interfaccia: quando tale prelievo avviene (tramite l'esecuzione dell'istruzione INB), l'interfaccia porta automaticamente a 0 il flag e inizia a trasferire un nuovo byte dal dispositivo. Similmente quando il flag FO vale 1, il programmatore può correttamente immettere un buovo byte nel registro TBR dell'interfaccia: quando tale immissione avviene (tramite l'esecuzione dell'istruzione OUTB), l'interfaccia pone automaticamente a 0 il flag e inizia a trasferire il byte al dispositivo. La gestione di un'operazione di ingresso o di uscita a controllo di programma comporta la verifica, per ogni byte da traferire, dello stato dei flag.
Un'interfaccia posizionata nello spazio di I/O viene ad avere specifici indirizzi per i suoi registri interni. Supponiamo che la notra interfaccia sia posizionata in modo che i tre registri abbiano i seguenti indirizzi:
Registro    Indirizzo

RBR         00F8
TBR         00F9
STR         00FA

Da quando detto risulta che un sottoprogramma di ingresso che porta nel registro AL del processore un nuovo byte, prelevandolo dal registro RBR dell'interfaccia, può essere strutturato nel modo illustrato di seguito.
Indirizzi          Contenuti             Commenti

00002000           INB   FA,AL           Copia in AL il contenuto di STR
00002004           ANDB  $0001,AL        Esamina il bit n0 di AL
00002008           JZ    EIP-0C          Salta se zero a 00002000
0000200C           INB   F8,AL           Preleva il dato da RBR
00002010           RET                   Ritorna al chiamante

Il sottoprogramma contiene un ciclo in cui viene esaminato il contenuto del registro di stato STR, il quale termina solo quando il flag FI vale 1: a questo punto viene prelevato il nuovo byte da RBR e viene copiato in AL.
In modo del tutto analogo, un sottoprogramma di uscita che porta nel registro TBR dell'interfaccia un byte, preventivamente posto nel registro AL (dal programma chiamante), può essere strutturato nel modo illustrato di seguito.
Indirizzi          Contenuti             Commenti

00002010           PUSHL   EAX           Salva contenuto di EAX in pila
00002012           INB     FA,AL         Copia in AL il contenuto di STR
00002016           ANDB    $0002,AL      Esamina il bit n1 di AL
0000201A           JZ      EIP-0C        Salta se zero a 00002002
0000201E           POPL    EAX           Ripristina il contenuto di EAX
00002020           OUTB    AL,F9         Immette il dato in TBR
00002024           RET                   Ritorna al chiamante
Anche in questo caso è previsto un ciclo in cui viene esaminato il flag FO, il quale termina quando tale flag vale 1: a questo punto viene copiato il contenuto di AL nel registro TBR.
Nella tecnica di ingresso/uscita dati cha abbiamo esaminato, nota come "Controllo di programma polling", cicli di test dei flag del registro di stato STR servono in ultima analisi a sincronizzare la velocità del processore con quella del dispositivo esterno, che in genere è molto più lento del processore stesso. Per evitare un tale spreco di tempo per il processore, sono state messe a punto altre tecniche più sofisticate di I/O dati, quali l'interruzione di programma e l'accesso diretto alla memoria (DMA: Direct Memory Access).

Vai Precedente
--=[Home page]=----=[Home page]=----=[Forum]=----=[Forum]=----=[lingua]=----=[lingua]=----=[Statistiche]=----=[Statistiche]=----=[Cerca in questo sito]=----=[Cerca in questo sito]=----=[Info sul copyright]=----=[Info sul copyright]=----=[Scegli le impostazioni che preferisci]=----=[Scegli le impostazioni che preferisci]=----=[Scrivi al webmaster]=--
vPHPvHTMLvCSS