ASM Indirizzo SP mix asm e C

Stato
Discussione chiusa ad ulteriori risposte.

dante.cpp

Utente Silver
25 Novembre 2011
34
13
0
57
Il codice seguente dovrebbe stampare a video l'indirizzo della cima dello stack, ossia la cella puntata dallo stack pointer.
Codice:
#include <stdio.h>
unsigned long get_sp()
{
unsigned long stp;
__asm
{
mov
eax, esp
}
}
void main(void)
{
printf("\n0x%x", get_sp());
}


tuttavia questo codice non mi gira, e sinceramente ho dei problemi anche a disassemblarlo, qualcuno mi può aiutare a capire l'errore e il codice!!!
 
Codice:
#include <windows.h>

#include <stdio.h>
unsigned long get_sp()
{
	unsigned long stp;
	__asm mov stp, esp //se la funzione non è dichiarata come naked devi spostare esp
	return stp; //su una var temporanea da ritornare
}

__declspec(naked) unsigned long get_sp_naked()
{
	__asm {
		mov	eax, esp //se la funzione è dichiarata come naked, il mov su eax va più che bene perchè
		retn //per standard il valore di ritorno viene preso da lì 
	}
}


int _tmain(int argc, _TCHAR* argv[])
{
	printf("\n0x%x", get_sp());
	printf("\n0x%x", get_sp_naked());
	system("pause");
	return 0;
}
 
  • Mi piace
Reazioni: dante.cpp
Il codice seguente dovrebbe stampare a video l'indirizzo della cima dello stack, ossia la cella puntata dallo stack pointer.
Codice:
#include <stdio.h>
unsigned long get_sp()
{
unsigned long stp;
__asm
{
mov
eax, esp
}
}
void main(void)
{
printf("\n0x%x", get_sp());
}


tuttavia questo codice non mi gira, e sinceramente ho dei problemi anche a disassemblarlo, qualcuno mi può aiutare a capire l'errore e il codice!!!

comunque quel codice dovrebbe funzionare (e a me funziona)

x86 cdecl, stdcall, -> ritorno in eax
x64 microsoft, amd -> ritorno in rax

---------- Post added at 18:18 ---------- Previous post was at 18:11 ----------

(in realtà un problema ci sarebbe: durante la chiamata di una funzione normale esp viene modificato)
 
comunque quel codice dovrebbe funzionare (e a me funziona)

x86 cdecl, stdcall, -> ritorno in eax
x64 microsoft, amd -> ritorno in rax

---------- Post added at 18:18 ---------- Previous post was at 18:11 ----------

(in realtà un problema ci sarebbe: durante la chiamata di una funzione normale esp viene modificato)

difatti per correttezza, sarebbe meglio utilizzare una funzione dichiarata come naked imho, che senza prologo ed epilogo non si fila di striscio lo stack e quindi ottieni il valore reale in quel punto.
 
Ma quando chiamiamo una funzione lo stack pointer viene modificato, poiché nella pila viene PUSHato l'indirizzo di ritorno al programma principale, non capisco perché non restituisce l'indirizzo. Se pur non restituisce l'indirizzo a cui punta lo SP al momento dell'avio del programma, dovrebbe renderci quello a cui punta in quell'istante; o no???
 
Ma quando chiamiamo una funzione lo stack pointer viene modificato, poiché nella pila viene PUSHato l'indirizzo di ritorno al programma principale, non capisco perché non restituisce l'indirizzo. Se pur non restituisce l'indirizzo a cui punta lo SP al momento dell'avio del programma, dovrebbe renderci quello a cui punta in quell'istante; o no???
sì... a me quel codice funziona così come è.

l'unica cosa a cui dovresti fare attenzione è ad eventuali ottimizzazioni del compilatore
 
se vuoi che qualcuno ti aiuti a capire qualcosa devi fornire le informazioni necessarie per permetterlo.
Che compilatore c++ usi?
In quale versione?
Che errori ti restituisce il compilatore?

"questo codice non mi gira" e compagnia bella non sono di nessun aiuto nella risoluzione dei problemi.
 
esatto, prova a dare qualche informazione in piu,
comunque è tutto vero, il codice deve funzionare, ma è anche vero che non ti torna l'ESP che ti aspetti tu, perchè come ti hanno fatto notare se la funzione non è naked ti devi aspettare che prima di arrivare al tuo "mov eax,esp" il compilatore ci ha infilato di suo almeno un paio di push e quindi ti ha scombinato la vita.
E' giusto anche il consiglio di togliere le ottimizzazioni per vedere il codice in modo piu "chiaro"

Ad esempio con Visual C++ di MS la cosa migliore per avere un .exe facilmente comprensibile è compilare in "release" e nelle opzioni del compilatore, sotto ottimizzazioni mettere "disabled", a quel punto ti apri l'exe con Olly e vai in cima alla prima riga, dovresti trovarci la tua funzione in chiaro.
 
Premetto:
Come compilatore C e C++ utilizzo CodeBlock che è un compilatore free e open source ottimo. Quest'anticipazione è di dovere perché dipendentemente dal tipo di compilatore utilizzato può variare la sintassi del codice per quanto riguarda l'Inline Assembly (ho riscontrato problemi in passato).


Il codice da te postato è il seguente:

Codice:
#include <stdio.h>
unsigned long get_sp()
{
unsigned long stp;
    __asm
    {
       mov eax, esp
    }
}
void main(void)
{
    printf("\n0x%x", get_sp());
}



Visto che uso un compilatore che adotta la sintassi AT&T per le istruzioni inline-assembly ho dovuto convertire:

[mov eax, esp] in [movl %esp, %eax] che sono praticamente la stessa cosa.

Il codice risultante, adattato al mio compilatore (che usa "(" al posto di "{" e la sintax AT&T) è il seguente:


Codice:
#include <stdio.h>
unsigned long get_sp()
{
   asm
          (
                "movl %esp, %eax;"
          );
}

void main(void)
{
        printf("\n0x%x", get_sp());
}

Puoi notare che ho rimosso la variabile unsigned long stp che hai dichiarato all'interno della procedura get_sp() perché non viene utilizzata.
Dato che il codice sul mio compilatore funziona correttamente suppongo che i tuoi problemi siano legati al compilatore che hai adottato.

Non riesco poi a capire questi discorsi che avete fatto riguardo il prendere prima o dopo il valore del registro ESP, a quale scopo?

c'è da dire che funziona anche il seguente codice che evita di chiamare procedure e quindi di fare push superflue prima di prendere il valore di esp, il metodo consiste come passare il contenuto di esp in eax e poi storarlo in una variabile globale (limitazione, se non mi sbaglio, di ASM-inline su code-block):

Codice:
#include <stdio.h>
unsigned long regesp;

void main(void)
{
    asm
      (
         "movl %esp, %eax;"
         "movl %eax, _regesp;"
      );
    printf("\n0x%x", regesp);
}

Quest'ultimo codice stampa a video un diverso valore dello stack pointer perché non viene eseguita la procedura get_sp().
Ciao ciao.
 
Stato
Discussione chiusa ad ulteriori risposte.