Volevo fare una domanda che mi trascino....

Stato
Discussione chiusa ad ulteriori risposte.

xXStephXx

Utente Electrum
28 Aprile 2008
389
16
1
125
1)
Se io metto:
Codice:
TEST eax, eax
jz <label>

in teoria dovrebbe eseguire AND su eax, senza caricare il valore sulla dst, ma settando lo ZeroFlag a 1 se eax corrisponde a 0 giusto?

cioè l'istruzione

TEST eax, eax potrebbe sostituire:

Codice:
CMP eax, 0
je.....

2)
Se all'interno di una procedura faccio un
SUB ESP, 12

mi posso liberare tre sezioni da 4 byte su cui posso metterci dei dati col mov?
ES:

Codice:
push ebp
MOV ebp, esp
SUB esp, 12
MOV [ebp+4], num
MOV [ebp+8], num2
MOV [ebp+12], num3

.......
........
.......
ADD esp, 12 ; per poppare tutto
MOV esp, ebp
POP ebp
RET


Voglio dire, posso fare così, oppure è scorretto?
 
1) Risposta:
il risultato per l'esempio da te riportato è il medesimo.
però ricorda che TEST confronta copie di bits simulando AND, mentre CMP confronta operandi simulando SUB.

2) Risposta:
non ho capito bene cosa intendi fare...
se vuoi mettere dei dati nello stack usa
push num
push num2
push num3
oppure se prima vuoi per forza siano vuori
push 0
push 0
push 0
e poi
mov eax, num
MOV DWORD PTR[ESP],eax
mov eax, num2
MOV DWORD PTR[ESP+4],eax
mov eax, num3
MOV DWORD PTR[ESP+8],eax

piccolo appunto, quando dici : ADD esp, 12 ; per poppare tutto
non poppa niente, fa un ADD di 12 sul registro esp spostando il puntatore di 12 (ovvero 0xC)
il pop è fatto dal comando pop.

Potrei sbagliarmi ma penso hai parecchia parecchia confusione riguardo l'asm

Preddy
 
bè ci hai azzeccato.... XD

Ma devo fare per forza POP esp?
Io quando vedo le procedure alla fine trovo sempre quel ADD esp, tot...
 
non so cosa stai guardando tu ma add e pop son due cose ben diverse e questo mi fa capire che non sai a cosa serve il registro ESP :)
pop lo fai se prima hai dei push. Ricorda che lo stack deve sempre avere un equilibrio.
Ammenochè tu non stia facendo una cosa ben precisa e in modo consapevole, in tutte funzioni quando pushi qualcosa nello stack devi fare pop
altriementi se arrivi al ret, salterai a all'offset sbagliato e chissa' dove, sballando tutto e molto molto probabilmente crashando l'applicazione.
 
forse ho capito male.... ma questo tizio...
prima usa sub 20 allo stack pointer per liberare 5 celle da 4 bytes.... poi usa add 20 per poppare tutte i valori messi in quelle 5 celle

http://quequero.org/Lezione_1_Assembly#Il_vostro_primo_listato
 
Lo stack pointer funziona così:

- Una add di n bytes sullo stack pointer equivale a liberare n/P bytes sullo stack (dove P è il parallelismo della macchina). Se ad esempio faccio add esp,20 su una macchina a 32 bit dico "guarda, ci sono 5 byte (20 = 5*4) sullo stack che non mi servono più, alza lo stack pointer così puoi tornarci a scrivere su".

- Una sub di n bytes sullo stack pointer equivale ad allocare n/P bytes sullo stack. Fare sub esp,20 equivale a dire "guarda, mi servono 5 byte sullo stack, tu allocameli poi vedo io come riempirli".

Alla luce di questo puoi tranquillamente riscrivere push e pop con delle sequenze di sub/add - mov. Ad esempio

Codice:
push eax

equivale (su una macchina a 32 bit) a

Codice:
sub esp,4
mov [esp],eax

così come

Codice:
pop eax

equivale a

Codice:
mov eax,[esp]
add esp,4
 
Ti ringrazio XD... beati voi che siete così esperti....
volevo fare un'altra domandina... il ret.address dove si ficca? Da quanto ho capito al momento della call dovrebbe ficcarsi immediatamente sopra ai parametri pushati? O mi confondo anche qui?

XD un'altra domanda che non ho capito....

a volte trovo cose del tipo

Codice:
MOV [ebp-4], eax

mi domando, come fa un parametro a stare sotto il base pointer?
 
ret si mette dove vuoi, ma dipende come lo vuoi usare.
Il comando ret esegue un jump all'offset attualmente nello stack.
l'uso più comune di ret lo trovi per esempio per ritornare al punto di origine di una chiamata,
cioè quando esegui una Call ed entri in una funzione. Terminata la funzione c'è il RET che ti riporta da dove è stata eseguita la CALL. tutto questo se nello stack c'è equilibrio.


MOV [ebp-4], eax
non ha nulla di particolare, significa che 4 byte prima nell'offset del valore contenuto in EBP metterai il valore contenuto in EAX.
 
La ret è semplicemente un'istruzione che pesca il return address salvato sullo stack (ogni volta che viene chiamata una funzione via call il primo parametro salvato sullo stack della nuova funzione è l'indirizzo di ritorno, in modo che la funzione sappia dove tornare una volta che è terminata). Supponendo che l'indirizzo di ritorno della funzione sia localizzato 8 byte prima del base pointer (ipotesi altamente probabile, anzi è la prassi comune praticamente in tutti i formati eseguibili), una ret equivale semplicemente a

Codice:
mov  eip,[ebp+8]

(in realtà questo è pseudo-Assembly, in quanto il registro eip non è direttamente accessibile). Ovvero, metti in eip l'indirizzo di ritorno della funzione, in modo che la funzione vada lì.

mi domando, come fa un parametro a stare sotto il base pointer?

Occhio a non confonderti e ricorda come funziona lo stack. Lo stack parte da indirizzi alti e va a decrescere ogni volta che gli infili della roba. Quindi se il mio stack comincia all'indirizzo 0xc0000000 (la norma sotto sistemi Linux a 32 bit) e faccio una push di 4 byte, il mio primo valore salvato sullo stack si troverà all'indirizzo 0xc0000000 e lo stack pointer varrà 0xbffffffc (ovvero il prossimo indirizzo utilizzabile è quello). Se faccio un'altra push di 4 byte, il nuovo valore verrà salvato all'indirizzo 0xbffffffc e lo stack pointer varrà 0xbffffff8, e così via. Quindi [ebp-4] in realtà identifica i 4 byte immediatamente successivi al base pointer.
 
BlackLight ha detto:
Quindi [ebp-4] in realtà identifica i 4 byte immediatamente successivi al base pointer.
ovviamente successivi relativi alla posizione dello stack, ma se parliamo di offset sono antecedenti.
 
XD Ho le idee molto confuse XD Perchè c'è una guida che fa l'esempio a torretta XD Poi un altra che lo mette come serpentone XDXD

Ma in definitiva.... se i parametri sono pushati dopo aver pushato ebp e averci copiato lo sp, non dovrebbero stare solo sotto?.... XD Scusate per la confusione.... ma se si infilano andando verso la Low Mem, da che dipende se stanno sopra o sotto?

XD praticamente....

come fa ad esserci sia ebp-4 che ebp+4 se si dovrebbero infilare sempre sotto il precedente?
 
ebp punta inizialmente, quando effettui una call, al primo indirizzo dello stack usabile dal codice stesso, infatti una delle prime istruzioni Assembly di ogni funzione non fa altro che uguagliare ebp ed esp (ovvero "lo stack parte da qui per questa funzione"). Quindi è normale, per dire, che l'indirizzo di ritorno sia salvato prima dell'ebp (a ebp+8), in quanto non dovrebbe essere modificato dal codice di norma. Cioè, di norma indirizzi più alti di ebp (ovvero indirizzi precedenti a ebp sullo stack) non "DOVREBBERO" essere manipolati dal codice, ma ciò non vuol dire che non siano accessibili (ovvio che se vado a modificare l'indirizzo di ritorno, che è messo a un indirizzo più alto del base pointer, non mi devo poi lamentare se il mio codice crasha).

Comunque lo stack parte da indirizzi alti e va verso gli indirizzi bassi, la norma è questa. Se vuoi un esempio, vedilo come una pila di piatti al contrario (cioè la base è in alto e ogni volta che aggiungi un piatto lo aggiungi sotto).
 
Lo stack, come dice la parola, funziona come una pila.
immagina di avere dei piatti: quando li metti nello stack li appoggi uno sopra l'altro, percio' l'ultimo messo (push) è il primo che verra' prelevato (pop).
è abbastanza elementare, non capisco dove ti perdi.

esempio
mov eax,0Ah ;metti il valore esadecimale A nel registor eax
push eax ;metti nello stack il valore di eax cioè 0xA
...varie operazioni...
pop eax ;prendi dallo stak il primo valore in eax ora c'è 0xA cioè il valore pushato all'inizio.

se tu sposti EBP aggiungendo o sottraendo valori non fai altro che spostarti nello stack. Al momento del pop, prelevi da dove sei.

black mi ha preceduto mentre scrivevo,
Mariusp ma ora mi sorge un quesito.... che stai combinando?
 
XD Nulla leggo le guide in giro... ma sono tutte fatte a caxx... eccetto quelle di quequero XD

Comunque prima o poi, preddy lo farò santo!!! La sua guida è l'unica dove ho capito bene sta cosa dello stack... XD Mi auguro che tu abbia intenzione di finirla XDXD
Grz blacklight per avermi chiarito le idee... il fatto è che tutti gli esperti di asm, danno per scontato che i nabbi come me sappiano già tutto XD Allora scrivono due cose..... XD
Thx per la guida preddy ( solo adesso me ne sono accorto ).
 
Stato
Discussione chiusa ad ulteriori risposte.