Sezione

Indirizzi Base Registri Interni
Area Comunicazione BIOS Funzioni BIOS Funzioni DOS
Prefazione Capitolo 1 Capitolo 2 Schede
Libreria ASM Libreria MAC Palestra Progetti ASM
Info Download INDICE

Schede del Tutorial

Home » Programma il Computer » Tutorial Assembly

Le Schede del Tutorial

  Stack - Definizione e Gestione

SCHEDA n° 06 [ 6  di 7] 

    

           Aggiornato 11 gennaio 2009
    Lo Stack nella gestione con PUSH e POP
     
bulletIl set delle istruzioni di un processore prevede altre possibilità di scrittura e lettura dello stack, non legate a fatti strutturali come quelli descritti nelle pagine precedenti; in sostanza anche il programmatore è messo in condizione di condividere con la Cpu questa importante risorsa.
bulletNon va comunque dimenticato che lo Stack è una struttura delicata e degna della massima attenzione: un piccolo errore di gestione può distruggere il programma in esecuzione e bloccare il computer.. ed è noto che l'errore lo può compiere solo il programmatore....
bulletDunque: 
bulletcon PUSH XX ci è concessa la possibilità si scrivere la word contenuta in XX nello stack: l'idea è quella di spingerci (push) dentro qualcosa...
bulletcon POP XX possiamo disporre dell'operazione opposta, cioè leggere una word dallo stack e copiarla in XX (cioè tirare (pop) fuori qualcosa..)
bulletL'oggetto XX coinvolto nelle operazioni è generalmente un registro a 16 bit (come AX, DI, ecc.) ma può essere anche il contenuto di una locazione di memoria.
bulletLo Stack è nato per garantire l'eseguibilità dei programmi, a beneficio sostanzialmente esclusivo del processore che li esegue: se, bontà sua, ne tollera la condivisione dobbiamo come minimo rispettare le sue regole; una di queste è già stata data in fase di presentazione ma non guasta ricordarla ancora:

      

Ricorda... Nello Stack: quello che si scrive deve essere, prima o poi, tolto, cioè per ogni PUSH deve esserci un POP !

      

bulletLa coppia PUSH/POP è ideale quando è necessario usare un registro senza rischiare di perderne il contenuto; può succedere infatti di avere tutti i registri caricati con valori importanti e, non avendone altri (dato il loro limitato numero...) di non sapere che santi pigliare...
bulletIn effetti  è sempre possibile salvare il valore di ciascun registro nello stack, riutilizzare a sazietà ciascuno di essi, e ripristinarlo alla fine, prelevandolo nei registri di partenza dallo stack.
bulletTutte le procedure fatte a regola d'arte (personali e di sistema) dovrebbero come prime istruzioni salvare nello Stack tutti i registri da esse utilizzati, e recuperarli alla fine, prima di tornare.

      

Suggerimento Con tecnica PUSH/POP è comunque possibile salvare (nello Stack) un registro, per esempio AX, e recuperare (dallo Stack) in un altro registro, per esempio BX (nel caso proposto otterremo lo stesso risultato di MOV BX;AX). Questa opportunità si dimostra l'unica strada perseguibile con registri (o altro) che non possono essere travasati con MOV, come quelli di segmento.

      

bulletQuando il processore esegue un'istruzione PUSH XX provvede ai seguenti compiti:
bulletdecrementa il valore corrente di SP e lo utilizza per puntare la locazione in cui scrivere la parte alta del dato a 16 bit contenuto in XX.
bulletdecrementa ancora il valore di SP e lo utilizza per puntare la locazione in cui scrivere la parte bassa del dato a 16 bit contenuto in XX.
bulletSe non si provvede altrimenti lo Stack rimane sporco, cioè con 2 bytes in più rispetto alla condizione precedente l'esecuzione dell'istruzione: la cosa è fastidiosa ma non ancora critica... ma se l'operazione fosse ripetuta sciaguratamente troppe volte si rischia, scrivendo all'indietro, di sovrascrivere il programma mentre è in esecuzione... 

      

bulletQuando il processore esegue un'istruzione POP XX provvede ai seguenti compiti:
bulletpreleva il byte contenuto nella locazione attualmente puntata da SP, lo trasferisce nella parte bassa dell'oggetto a 16 bit indicato da XX.
bulletincrementa il valore di SP e lo utilizza per puntare la locazione da cui prelevare il byte da utilizzare come parte alta dell'oggetto a 16 bit indicato da XX.
bulletincrementa ancora SP.
bulletL'azione di POP è benedetta e dovrebbe essere esercitata nella misura dei PUSH effettuati in precedenza; ma è facile pensare che anche l'esecuzione di un POP senza aver prima spinto qualcosa nello Stack è sciagurata: in questo caso, pur non essendo traumatica per il programma in esecuzione, sono i dati recuperati in XX ad essere inattendibili, con inevitabili malfunzionamenti.

      

bulletI movimenti del processore e dei suoi registri possono essere monitorati, sviluppati e analizzati in ambiente Debug, con l'aiuto di una semplice sequenza di istruzioni usata come banco di prova; a sinistra osserviamo i valori dei registri e a destra l'aspetto dello Stack, nelle varie fasi:

      

1192:0100 B80201  MOV AX,0102
1192:0103 50      PUSH AX      
1192:0104 90      NOP
1192:0105 58      POP BX       
1192:0106 B44C    MOV AH,4C  
1192:0108 CD21    INT 21       
1192:010A 90      NOP

-R   punto *1* --------------------------
AX=0000 BX=0000 CX=0000  DX=0000  SP=FFFE
DS=1192 ES=1192 SS=1192 CS=1192 IP=0100
1192:0100 B80000  MOV AX,0102

-T   punto *2* --------------------------
AX=0102 BX=0000 CX=0000  DX=0000  SP=FFFE
DS=1192 ES=1192 SS=1192 CS=1192 IP=0103
1192:0103
50      PUSH AX

-T   punto *3* --------------------------
AX=0102 BX=0000 CX=0000  DX=0000  SP=FFFC
DS=1192 ES=1192 SS=1192 CS=1192 IP=0104
1192:
0104 90      NOP

-T   punto *4* --------------------------
AX=0102 BX=0000 CX=0000  DX=0000  SP=FFFC
DS=1192 ES=1192 SS=1192 CS=1192 IP=0105
1192:
0105 58      POP BX

-T   punto *5* --------------------------
AX=0102 BX=0102 CX=0000  DX=0000  SP=FFFE
DS=1192 ES=1192 SS=1192 CS=1192 IP=0106
1192:0106 B44C    MOV AH,4C
--- punto *1* e *2* ---
1192:FFFC ??
1192:FFFD ??
1192:FFFE 00 <- SP=FFFE
1192:FFFF 00

--- punto *3* ---------
1192:FFFA ??
1192:FFFB ??
1192:FFFC 02 <- SP=FFFC
1192:FFFD 01
1192:FFFE 00 
1192:FFFF 00

--- punto *4* ---------
1192:FFFA ??
1192:FFFB ??
1192:FFFC 02 <- SP=FFFC
1192:FFFD 01
1192:FFFE 00 
1192:FFFF 00


--- punto *5* ---------
1192:FFFA ??
1192:FFFB ??
1192:FFFC 02 Lo AX
1192:FFFD 01 Hi AX
1192:FFFE 00 <- SP=FFFE
1192:FFFF 00 

      

bulletAll'inizio (punto *1*), poichè la coppia di registri CS:IP contiene 1192:0100, il processore si trova costretto ad eseguire l'istruzione MOV AX,0102
bulletil puntatore di Stack punta la locazione SP=FFFE, a dimostrazione del fatto che il sistema operativo ha già consumato per sè una posizione di Stack (leggi la nota, PSP- offset 0000, se non ricordi o non sai il perché) caricandoci 2 bytes a 00H.
bulletDopo l'esecuzione di MOV AX,0102 (punto *2*), la coppia di registri CS:IP contiene 1192:0103: il processore si accinge ad eseguire PUSH AX il puntatore di Stack non è stato influenzato dall'istruzione MOV: il suo valore è ancora SP=FFFE.
bulletDopo l'esecuzione di PUSH AX (punto *3*):
bulletil puntatore di codice CS:IP contiene 1192:0104CS è ovviamente inalterato e IP punta l'istruzione successiva, NOP.
bulletil puntatore di Stack punta la locazione SP=FFFC, a dimostrazione del fatto che è stata consumata un'altra posizione di Stack: il dettaglio a destra mostra che nello Stack è finito il contenuto del registro AX, cioè i 2 bytes a 01H e 02H, nell'ordine indicato, per rispettare la tecnica Lo-Hi.
bulletDopo l'esecuzione di NOP (punto *4*), la coppia di registri CS:IP contiene 1192:0105: il processore si accinge ad eseguire POP BX il puntatore di Stack non è stato influenzato dall'istruzione NOP: il suo valore è ancora SP=FFFC.
bulletDopo l'esecuzione di POP BX (punto *5*):
bulletil puntatore di codice CS:IP contiene 1192:0106: il processore si accinge ad eseguire l'istruzione MOV AH,4C.
bulletil puntatore di Stack punta la locazione SP=FFFE, a dimostrazione del fatto che ha recuperato la posizione di Stack indotta in precedenza dalla PUSH AX.
bulletil registro BX contiene ora il valore 0102H, esattamente quello copiato in precedenza nello Stack da AX.

      

bulletRiassumiamo la dinamica dello Stack, dopo la gestione di una coppia PUSH/POP:
bulletil puntatore di Stack ha il valore che aveva prima di iniziare il servizio di salvataggio-recupero (nell'esempio SP=FFFE).
bulletsi può sottolineare che, in accordo con le definizioni, SP sta puntando la locazione successiva a quella che sarà caricata, in futuro, cioè sempre esterna all'area utile corrente dello Stack!
bulletle 2 locazioni precedenti quella puntata da SP mostrano ancora i 2 valori introdotti con PUSH AX; la figura mette in evidenza che la scrittura è avvenuta con la tecnica Lo-Hi (cioè prima la parte bassa, Low,  e poi la parte alta, High, di AX).
bulletil fatto che la ram sia rimasta sporca dei 2 bytes precedentemente caricati è irrilevante: le prossime operazioni che coinvolgeranno lo Stack in scrittura si limiteranno semplicemente a sovrascrivere questi valori.
bulletin ogni caso le prime 2 locazioni dello Stack sono sempre precaricate con 2 bytes a 00H dal sistema operativo (per le note vicende).

      

SP:FFFA ?? non ancora utilizzato
SP:FFFB ?? non ancora utilizzato
SP:FFFC 02 Lo AX
SP:FFFD 01 Hi AX
SP:FFFE 00 <- SP=FFFE
SP:FFFF 00 

    

Pagina Precedente Scheda n° 06 Pagina Successiva Stack - Definizione e Gestione Torna al Menu delle Schede del "Tutorial" Lezioni - Vai al DownLoad dei files DOC Torna al Menu del "Tutorial"
Scheda n° 06 -  6
1 2 3 4 5 6 7

    

SCHEDE » 1.Header EXE 2.PseudoOp MASM 3.Differenza tra Macro e Procedure
4.
Tabella Vettori 5.PSP 6.Stack 7.Istruzioni 80x86
8.La misura dell'Informazione 9.Numeri e Logica Binaria
TUTORIAL » Indirizzi Base | Registri Interni | Area Comunicaz. BIOS | Funzioni BIOS | Funzioni DOS
Prefazione | CAP 1 | CAP 2 | Schede | Palestra
Libreria ASM | Libreria MAC | Progetti ASM | Download | Info | Indice
Home 
Pascal|Manuali|Tabelle|Schede
Tutorial Assembly|Palestra Assembler
Aggiungi Giobe®2000 ai preferiti  
Motore
Ricerca
  Rendi Giobe®2000 pagina di Default
© 2001-2010  -  Studio Tecnico ing. Giorgio OBER
Tutti i diritti sono riservati