e non posso usare lo SP, perché un istruzione del genere genera un errore
8086 mette a disposizione alcune modalità di indirizzamento che riguardano la memoria (sono 24) e SP non è presente in queste modalità.
Estrapolo l'immagine da un mio articolo:
Quando avviene una CALL viene modificato il valore in SP e viene salvato l'indirizzo di ritorno sullo stack (che è l'indirizzo dell'istruzione successiva alla CALL).
Il prologo della funzione:
Codice:
push bp
mov bp, sp
ti consente di utilizzare BP e leggere i parametri o accedere alle variabili locali alla funzione.
La convenienza dell'utilizzo di BP è proprio questa: agli offset positivi trovi gli argomenti della funzione, agli offset negativi trovi le variabili locali alla funzione (se ce ne sono).
Quando viene chiamata la funzione viene creato quello che si chiama "stack frame". Il vantaggio è che hai delle posizioni costanti sul dove si trovano i tuoi dati. Per dire, all'offset BP-8 avrai sempre il medesimo valore; se usi direttamente lo stack pointer no, in quanto ogni PUSH/POP altera questi riferimenti.
In 8086 non è appunto possibile indirizzare direttamente della memoria usando SP, ma in x86 e x86-64 è possibile. L'unico vantaggio è quello di evitare prologo ed epilogo; un aspetto che rende più complesso il codice è che l'offset sottratto al registro cambia in base alle PUSH/POP che sono state fatte.
Un esempio penso ti possa chiarire maggiormente il funzionamento (è una versione a 32bit, con MASM):
Codice:
call main
print str$(eax),13,10
inkey
invoke ExitProcess,0
main proc
mov edx, 456
mov dword ptr [esp-8], 123
push edx
mov eax, [esp-8]
pop edx
ret
main endp
Ignora str$, invoke, inkey... sono MACRO per agevolare le operazioni.
L'output se lo esegui è questo:
Codice:
0
Press any key to continue ...
Come noti, in
[esp-8]
, non c'è il valore 123. Se usi ESP (medesimo di SP, ma a 32bit) devi tenere traccia tu dei push/pop che vengono fatti e modificare il valore che vai a sottrarre al registro ESP.In questo caso, trattandosi di x86, a esp bisogna sottrarre 4 e non 8: questo perchè la PUSH del registro EDX ha già sottratto 4 a ESP.
Se utilizzi EBP, fai semplicemente questo:
Codice:
main proc
push ebp
mov ebp, esp
sub esp, 4
mov edx, 456
mov dword ptr [ebp-4], 123
push edx
mov eax, [ebp-4]
pop edx
mov esp, ebp
pop ebp
ret 4
main endp
Come noti si va sempre a sottrarre 4 al registro EBP poichè la posizione rimane costante (in quanto PUSH/POP modificano solo ESP).