JavascriptProva

sabato 21 settembre 2013

Riportare al valore iniziale il puntatore dello stack dopo il passaggio di parametri tramite stack

Nel mio programmino rimane un conto in sospeso con lo stack.
Le due WORD pushate prima di chiamare la procedura, contenenti i parametri, non vengono poi ripoppate o smaltite in qualche modo, cosicchè SP non torna ai valori iniziali fino alla fine del programma.
Seguo in DEBUG i valori prima e dopo la chiamata della procedura Stampa:
AX=0003  BX=0000  CX=0440  DX=0000  SP=0400  BP=0000  SI=0000  DI=0000
DS=1771  ES=1771  SS=1785  CS=1781  IP=0003   NV UP EI PL NZ NA PO NC
1781:0003 B041          MOV     AL,41
-p

AX=0041  BX=0000  CX=0440  DX=0000  SP=0400  BP=0000  SI=0000  DI=0000
DS=1771  ES=1771  SS=1785  CS=1781  IP=0005   NV UP EI PL NZ NA PO NC
1781:0005 B30C          MOV     BL,0C
-p

AX=0041  BX=000C  CX=0440  DX=0000  SP=0400  BP=0000  SI=0000  DI=0000
DS=1771  ES=1771  SS=1785  CS=1781  IP=0007   NV UP EI PL NZ NA PO NC
1781:0007 50            PUSH    AX
-p

AX=0041  BX=000C  CX=0440  DX=0000  SP=03FE  BP=0000  SI=0000  DI=0000
DS=1771  ES=1771  SS=1785  CS=1781  IP=0008   NV UP EI PL NZ NA PO NC
1781:0008 53            PUSH    BX
-p

AX=0041  BX=000C  CX=0440  DX=0000  SP=03FC  BP=0000  SI=0000  DI=0000
DS=1771  ES=1771  SS=1785  CS=1781  IP=0009   NV UP EI PL NZ NA PO NC
1781:0009 E80700        CALL    0013
-
Il valore di base di SP è 0400.
Con il pushaggio dei parametri diventa poi 03FE e 03FC.

-t

AX=0041  BX=000C  CX=0440  DX=0000  SP=03FA  BP=0000  SI=0000  DI=0000
DS=1771  ES=1771  SS=1785  CS=1781  IP=0013   NV UP EI PL NZ NA PO NC
1781:0013 55            PUSH    BP
-
Con la CALL diventa 03FA perchè viene pushato l'indirizzo di ritorno.

-t

AX=0041  BX=000C  CX=0440  DX=0000  SP=03F8  BP=0000  SI=0000  DI=0000
DS=1771  ES=1771  SS=1785  CS=1781  IP=0014   NV UP EI PL NZ NA PO NC
1781:0014 8BEC          MOV     BP,SP
-t>
Con il PUSH BP all'interno della procedura diventa 03F8.

AX=0041  BX=000C  CX=0440  DX=0000  SP=03F8  BP=03F8  SI=0000  DI=0000
DS=1771  ES=1771  SS=1785  CS=1781  IP=0016   NV UP EI PL NZ NA PO NC
1781:0016 8B5E04        MOV     BX,[BP+04]                         SS:03FC=000C
-t

AX=0041  BX=000C  CX=0440  DX=0000  SP=03F8  BP=03F8  SI=0000  DI=0000
DS=1771  ES=1771  SS=1785  CS=1781  IP=0019   NV UP EI PL NZ NA PO NC
1781:0019 8B4606        MOV     AX,[BP+06]                         SS:03FE=0041
-t

AX=0041  BX=000C  CX=0440  DX=0000  SP=03F8  BP=03F8  SI=0000  DI=0000
DS=1771  ES=1771  SS=1785  CS=1781  IP=0019   NV UP EI PL NZ NA PO NC
1781:0019 8B4606        MOV     AX,[BP+06]                         SS:03FE=0041
-t

AX=0041  BX=000C  CX=0440  DX=0000  SP=03F8  BP=03F8  SI=0000  DI=0000
DS=1771  ES=1771  SS=1785  CS=1781  IP=001C   NV UP EI PL NZ NA PO NC
1781:001C B409          MOV     AH,09
-t

AX=0941  BX=000C  CX=0440  DX=0000  SP=03F8  BP=03F8  SI=0000  DI=0000
DS=1771  ES=1771  SS=1785  CS=1781  IP=001E   NV UP EI PL NZ NA PO NC
1781:001E B700          MOV     BH,00
-t

AX=0941  BX=000C  CX=0440  DX=0000  SP=03F8  BP=03F8  SI=0000  DI=0000
DS=1771  ES=1771  SS=1785  CS=1781  IP=0020   NV UP EI PL NZ NA PO NC
1781:0020 B90100        MOV     CX,0001
-t

AX=0941  BX=000C  CX=0001  DX=0000  SP=03F8  BP=03F8  SI=0000  DI=0000
DS=1771  ES=1771  SS=1785  CS=1781  IP=0023   NV UP EI PL NZ NA PO NC
1781:0023 CD10          INT     10
-p

A
AX=0941  BX=000C  CX=0001  DX=0000  SP=03F8  BP=03F8  SI=0000  DI=0000
DS=1771  ES=1771  SS=1785  CS=1781  IP=0025   NV UP EI PL NZ NA PO NC
1781:0025 5D            POP     BP
-p
E resta tale fino ad ora. Quindi il POP BP lo riporta a 03FA.
AX=0941  BX=000C  CX=0001  DX=0000  SP=03FA  BP=0000  SI=0000  DI=0000
DS=1771  ES=1771  SS=1785  CS=1781  IP=0026   NV UP EI PL NZ NA PO NC
1781:0026 C3            RET
-


E con il RET, col recupero dell'indirizzo di ritorno, va a 03FC.
-t

AX=0941  BX=000C  CX=0001  DX=0000  SP=03FC  BP=0000  SI=0000  DI=0000
DS=1771  ES=1771  SS=1785  CS=1781  IP=000C   NV UP EI PL NZ NA PO NC
1781:000C E81800        CALL    0027
-


...per poi restare uguale fino alla fine del programma.
-p

AX=1C0D  BX=000C  CX=0001  DX=0000  SP=03FC  BP=0000  SI=0000  DI=0000
DS=1771  ES=1771  SS=1785  CS=1781  IP=000F   NV UP EI PL NZ NA PO NC
1781:000F B44C          MOV     AH,4C
-p

AX=4C0D  BX=000C  CX=0001  DX=0000  SP=03FC  BP=0000  SI=0000  DI=0000
DS=1771  ES=1771  SS=1785  CS=1781  IP=0011   NV UP EI PL NZ NA PO NC
1781:0011 CD21          INT     21
-p

Program terminated normally
-
C'è quindi un conto in sospeso con lo stack, che rimane 4 bytes, ossia 2 words, più in basso rispetto a quello che dovrebbe essere.

Come "aggiustarlo" alla fine della procedura?
Come "riassorbire", cioè, i due parametri che erano stati pushati prima della chiamata della procedura?
Mi pare di ricordare che posporre un numero a RET determina un riassestamento di SP.
Controlliamo...

extrn Cancella:near

extrn KeyWait:near
;definiamo il segmento
text segment public
;inizio del programma
start:
 
 call Cancella
 
 mov al,'A'
 mov bl,0Ch
 push ax
 push bx
 call Stampa
 
 
 call KeyWait
 
 mov ah,4ch
 int 21H
 
stampa proc near
 push bp
 mov bp,sp
 mov bx,[bp+4]
 mov ax,[bp+6]
 mov ah,09h
 mov bh,00h
 mov cx,1
 int 10h
 pop bp
 ret 4
stampa endp
text ends

stack segment para stack
 db 1024 dup(00H)

stack ends

end start
 

AX=0941  BX=000C  CX=0440  DX=0000  SP=03F8  BP=03F8  SI=0000  DI=0000
DS=1771  ES=1771  SS=1785  CS=1781  IP=0020   NV UP EI PL NZ NA PO NC
1781:0020 B90100        MOV     CX,0001
-p

AX=0941  BX=000C  CX=0001  DX=0000  SP=03F8  BP=03F8  SI=0000  DI=0000
DS=1771  ES=1771  SS=1785  CS=1781  IP=0023   NV UP EI PL NZ NA PO NC
1781:0023 CD10          INT     10
-p
A
AX=0941  BX=000C  CX=0001  DX=0000  SP=03F8  BP=03F8  SI=0000  DI=0000
DS=1771  ES=1771  SS=1785  CS=1781  IP=0025   NV UP EI PL NZ NA PO NC
1781:0025 5D            POP     BP
-t

AX=0941  BX=000C  CX=0001  DX=0000  SP=03FA  BP=0000  SI=0000  DI=0000
DS=1771  ES=1771  SS=1785  CS=1781  IP=0026   NV UP EI PL NZ NA PO NC
1781:0026 C20400        RET     0004
-p

AX=0941  BX=000C  CX=0001  DX=0000  SP=0400  BP=0000  SI=0000  DI=0000
DS=1771  ES=1771  SS=1785  CS=1781  IP=000C   NV UP EI PL NZ NA PO NC
1781:000C E81A00        CALL    0029
-
Ecco. Aggiungendo a RET il numero di bytes che sono stati occupati dai parametri passati, oltre a "rimangiarsi" l'indirizzo di ritorno, si resetta SP 4 bytes più in su, al punto di partenza!

Mi pare che ci fosse anche la possibilità di riportare lo stack al valore di base mediante un'istruzione specifica, ma ciò andrebbe fatto dopo il "rientro" nel programma di base.
extrn Cancella:near

extrn KeyWait:near
;definiamo il segmento
text segment public
;inizio del programma
start:
 
 call Cancella
 
 mov al,'A'
 mov bl,0Ch
 push ax
 push bx
 call Stampa
 
 add sp,4
 call KeyWait
 
 mov ah,4ch
 int 21H
 
stampa proc near
 push bp
 mov bp,sp
 mov bx,[bp+4]
 mov ax,[bp+6]
 mov ah,09h
 mov bh,00h
 mov cx,1
 int 10h
 pop bp
 ret 
stampa endp
text ends

stack segment para stack
 db 1024 dup(00H)

stack ends

end start
 
AX=0941  BX=000C  CX=0001  DX=0000  SP=03F8  BP=03F8  SI=0000  DI=0000
DS=1771  ES=1771  SS=1785  CS=1781  IP=0028   NV UP EI PL NZ AC PE NC
1781:0028 5D            POP     BP
-t

AX=0941  BX=000C  CX=0001  DX=0000  SP=03FA  BP=0000  SI=0000  DI=0000
DS=1771  ES=1771  SS=1785  CS=1781  IP=0029   NV UP EI PL NZ AC PE NC
1781:0029 C3            RET
-t

AX=0941  BX=000C  CX=0001  DX=0000  SP=03FC  BP=0000  SI=0000  DI=0000
DS=1771  ES=1771  SS=1785  CS=1781  IP=000C   NV UP EI PL NZ AC PE NC
1781:000C 83C404        ADD     SP,+04
-t

AX=0941  BX=000C  CX=0001  DX=0000  SP=0400  BP=0000  SI=0000  DI=0000
DS=1771  ES=1771  SS=1785  CS=1781  IP=000F   NV UP EI PL NZ AC PE NC
1781:000F E81800        CALL    002A
-
Ottimo!

Nessun commento:

Posta un commento