RISOLTO rimuovere dallo stack 'indirizzo di ritorno

Stato
Discussione chiusa ad ulteriori risposte.

Matteo34

Nuovo Utente
104
3
CPU
i5-10500 3.2Ghz
Dissipatore
Non specificato
Scheda Madre
Non specificata
HDD
M.2 251GB e M.2 500GB
RAM
16GB DDR4 2666mhz
GPU
Grafica Intel® UHD 630
Audio
Non specificata
Monitor
1920x1080 27"
PSU
Non specificato
Case
Non specificato
Periferiche
Nono specificato
Net
Eolo
OS
Ubuntu
No, non mi riferisco all'istruzione "ret", stavo studiando le procedure a basso livello quando riflettendoci un po capisco che molto probabilmente se la funzione chiamata eseguisse una "pop", verebbe rimosso dallo stack l'indirizzo di ritorno e memorizzato nell'operando specificato, a questo punto l'istruzione "ret" eseguirebbe una "pop" della locazione indirizzata dello SP che non è più l'indirizzo di ritorno bensì una locazione da me inizializzata a 3h, infatti lo SP e stato incrementato all'esecuzione della pop.
Lo so che questo non si dovrebbe mai fare, infatti il programma si blocca, ma mentre eseguivo il debbug mi accorgo che il registro nella quale memorizzo il dato rimosso dallo stack, non contiene l'indirizzo di ritorno ma un valore che non capacito a capire da dove provenga:
Questo è il codice:
Codice:
;non ho bisogno di un segmento logico per  dati
;MASM 6.14
;ISA: x86-16bit
;SO: MS-DOS
stack SEGMENT PARA STACK

        dw      3h

stack ENDS

code SEGMENT PARA PUBLIC

        ASSUME cs: code, ss: stack

      cosa PROC NEAR

       pop     ax ;memorizzo in ax l'indirizzo di ritorno
       ret ;dovrebbe eseguire una rimozione dallo stack errata

      cosa ENDP

_start:
       call     cosa

       mov      ah, 04ch
       mov      al, 1
       int      21h

code ENDS
        END _start
Come si può notare l'istruzione "pop" memorizza in "AX" l'indirizzo di ritorno e l'istruzione "ret" dovrebbe memorizzare nello "IP" il byte allocato nello stack e inizializzato a tre.
Il debbuger però non la pensa come me : )
Schermata del 2021-04-16 21-13-11.png
Dopo l'istruzione il valore di[ "AX" è pari a 5 e non 4, la memorizzazione della seguente istruzione "call" richiede 3byte, se così però l'istruzione successiva si dovrebbe trovare alla locazione con offset 0004h e non 0005h. Perché accade ciò?
 
Ultima modifica:

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,221
1,853
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
Ciò che succede è che alla locazione SP=0000h è presente il valore 3h. Il registro SP viene inizializzato con il valore 0002h.
Quando viene eseguita la CALL, SP viene decrementato di 2byte: in quello stesso momento viene memorizzato l'indirizzo di ritorno, che è dato dall'indirizzo dall'istruzione della CALL (0002h) + 3byte, quindi 0005h.
Quindi l'indirizzo 0000h puntato da SP contiene il valore 0005h.

In questo stesso momento hai sovrascritto il valore 3h posto in 0000h.
Quando fai POP AX, il valore 5h viene inserito nel registro AX e in quello stesso momento il registro SP viene incrementato di 2byte puntando nuovamente alla locazione 0002h.

Quando viene eseguita la RET, il registro SP viene incrementato nuovamente di 2byte, quindi il valore è 0004h.

Devi considerare che il valore iniziale di IP, prima della CALL, è 0002h. Quindi 0002h + 3h = 0005h, che è l'indirizzo della prossima istruzione.

Ovviamente così facendo hai "sballato" l'indirizzo di ritorno, quindi non funzionerà nulla e non verrà eseguita l'istruzione successiva alla call.
Se vuoi "giocare" un pò, puoi togliere ad esempio la RET e usare jmp ax. Così facendo salti all'istruzione successiva alla CALL.
 

Matteo34

Nuovo Utente
104
3
CPU
i5-10500 3.2Ghz
Dissipatore
Non specificato
Scheda Madre
Non specificata
HDD
M.2 251GB e M.2 500GB
RAM
16GB DDR4 2666mhz
GPU
Grafica Intel® UHD 630
Audio
Non specificata
Monitor
1920x1080 27"
PSU
Non specificato
Case
Non specificato
Periferiche
Nono specificato
Net
Eolo
OS
Ubuntu
Si, ma se il debugger mi comunica che la prossima istruzione da eseguire dopo la call ha offset pari a 4, perché in AX viene memorizzato 5? Non è l'offset della prossima locazione contenente l'istruzione. Se l'istruzione è decodificata su un word l'IP pointer punta solo alla Word più significativa è quella meno significativa non la dovrebbe leggere.
Ciò che succede è che alla locazione SP=0000h è presente il valore 3h. Il registro SP viene inizializzato con il valore 0002h.
Quando viene eseguita la CALL, SP viene decrementato di 2byte: in quello stesso momento viene memorizzato l'indirizzo di ritorno, che è dato dall'indirizzo dall'istruzione della CALL (0002h) + 3byte, quindi 0005h.
Quindi l'indirizzo 0000h puntato da SP contiene il valore 0005h.

In questo stesso momento hai sovrascritto il valore 3h posto in 0000h.
Quando fai POP AX, il valore 5h viene inserito nel registro AX e in quello stesso momento il registro SP viene incrementato di 2byte puntando nuovamente alla locazione 0002h.

Quando viene eseguita la RET, il registro SP viene incrementato nuovamente di 2byte, quindi il valore è 0004h.

Devi considerare che il valore iniziale di IP, prima della CALL, è 0002h. Quindi 0002h + 3h = 0005h, che è l'indirizzo della prossima istruzione.

Ovviamente così facendo hai "sballato" l'indirizzo di ritorno, quindi non funzionerà nulla e non verrà eseguita l'istruzione successiva alla call.
Se vuoi "giocare" un pò, puoi togliere ad esempio la RET e usare jmp ax. Così facendo salti all'istruzione successiva alla CALL.

Inviato da MI 8 tramite App ufficiale di Tom\'s Hardware Italia Forum
 

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,221
1,853
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
No, non è 4 e lo si vede anche dallo screen parziale che hai riportato: fai riferimento all'istruzione CALL, guarda il valore di AX (EAX, ma ok). C'è scritto 0002h.
Tu è al valore di IP che devi sommare la lunghezza della CALL. Quindi 3h + 2h = 5h. Quando avviene la CALL il valore che va sullo stack è questo.
Non capisco dove dici che il debugger ti comunica che l'indirizzo della prossima istruzione è 4... dove lo vedi?

IP è inizializzato con 0002h, giusto? La CALL è "in alto", all'indirizzo 0000h. Qui viene eseguita la POP e la RET, entrambe istruzioni di 1-byte (ecco perch IP = 0002h). Quindi 3-byte dopo a questo valore trovi la MOV.
 

Matteo34

Nuovo Utente
104
3
CPU
i5-10500 3.2Ghz
Dissipatore
Non specificato
Scheda Madre
Non specificata
HDD
M.2 251GB e M.2 500GB
RAM
16GB DDR4 2666mhz
GPU
Grafica Intel® UHD 630
Audio
Non specificata
Monitor
1920x1080 27"
PSU
Non specificato
Case
Non specificato
Periferiche
Nono specificato
Net
Eolo
OS
Ubuntu
Ho ricontrollato per bene, e effettivamente avevo visto male, forse mentre eseguivo il debbug avevo cambiato qualcosa nel programma per vedere cosa comportava l'istruzione dopo, in questo modo l'istruzione era esplicata in altra locazione con offset diverso.
No, non è 4 e lo si vede anche dallo screen parziale che hai riportato: fai riferimento all'istruzione CALL, guarda il valore di AX (EAX, ma ok). C'è scritto 0002h.
Tu è al valore di IP che devi sommare la lunghezza della CALL. Quindi 3h + 2h = 5h. Quando avviene la CALL il valore che va sullo stack è questo.
Non capisco dove dici che il debugger ti comunica che l'indirizzo della prossima istruzione è 4... dove lo vedi?

IP è inizializzato con 0002h, giusto? La CALL è "in alto", all'indirizzo 0000h. Qui viene eseguita la POP e la RET, entrambe istruzioni di 1-byte (ecco perch IP = 0002h). Quindi 3-byte dopo a questo valore trovi la MOV.

Inviato da MI 8 tramite App ufficiale di Tom\'s Hardware Italia Forum
 

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,221
1,853
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
Mi sembrava strano infatti vedessi indirizzi differenti, in quanto l'IP puntava proprio all'indirizzo 0002h e di conseguenza sommando 3byte si otteneva proprio 0005h.
Risolto quindi?
 
  • Mi piace
Reazioni: Mursey

Matteo34

Nuovo Utente
104
3
CPU
i5-10500 3.2Ghz
Dissipatore
Non specificato
Scheda Madre
Non specificata
HDD
M.2 251GB e M.2 500GB
RAM
16GB DDR4 2666mhz
GPU
Grafica Intel® UHD 630
Audio
Non specificata
Monitor
1920x1080 27"
PSU
Non specificato
Case
Non specificato
Periferiche
Nono specificato
Net
Eolo
OS
Ubuntu
Stato
Discussione chiusa ad ulteriori risposte.

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!