C -> ASM -> C (prob. mit dem Argument)

Hi
Ich möchte von einer C-Funktion aus eine in ASM geschreibene Funktion aufrufen, die widerum eine C-Funktion aufruft. Dabei soll jeweils ein argument (das selbe) übergeben werden:

C-Funktion, die die ASM-Funktion aufruft:
Code:
   asmfunktion = (int (*)(int))address;
   int retvalue = asmfunktion(argument);

ASM-Funktion, die eine weitere Funktion aufrufen soll und "argument" übergeben soll
Code:
  mov ebp, esp
  mov ebx, [esp+4]

  push ebx ;jetzt ist das argument für _main
  call _cfunktion02
  pop ebx ;argument runterholen

  mov eax, 0x00FF00FF ;TEST

  ret

die C-Funktion "cfunktion02"
Code:
int cfunktion02(int argument)
{
funktion03 = (int (*)(int,int)) argument;
int x = funktion03(0, 0);

return 0;
}

Das Problem:
der "hinweg" funktioniert. allerdings wird "funktion03" 2 mal aufgerufen, und dann hängt alles.

Wo liegt das Problem??

Compiler: gpp
Assembler: NASM
System: keins, freestanding
 
ich würde hier auf C und STDCALLs ungereimheiten tippen. Deine Asm Funktion ist eigentlich nichts von beidem. Ich nehme an, Du möchtest in der ASM Funktion C-Konvention nehmen:
Du musst also als erstes EBX,EDI,ESI,ESP und EBP wieder so zurückgeben, wie Du sie bekommen hast.
http://en.wikipedia.org/wiki/X86_calling_conventions#cdecl
In Deiner ASM Funktion veränderst Du aber sowohl EBX wie EBP Werte, wobei EBP immer "tödlich" ist, da hier der Stack durcheinander gebracht wird.

Zusätzlicher Tipp: greife auf Argumente immer über EBP zu - dafür ist der "Base Pointer" da, denn ESP verändert man meistens (lokale Variablen etc).
Man sichert EBP wert, kopiert den ESP darein und hat sozusagen neue "Stackbasis" für die aktuelle Funktion, in der man auf lokale Variablen und Argumente zugreifen kann.

Code:
push ebp ;sichern
mov ebp, esp
push ebx ;jetzt ebx und andere benutze Register sichern
  mov ebx, [ebp+8] ;erstes Argument, wegen der EBP sicherung "verschiebt" sich alles

  push ebx ;jetzt ist das argument für _main
  call _cfunktion02
  pop ebx ;argument runterholen

  mov eax, 0x00FF00FF ;TEST
pop ebx ;ebx wiederherstellen
pop ebp ;ebp wiederherstellen
ret

Ansonten müsste eigentlich der Aufruf der asmfunktion auch mit Deinem Code gehen (nur dass danach Fehler auftreten, ist sehr wahrscheinlich).

Aus dem vorliegendem Code und der Fehlerbeschreibung kann ich nur folgern, dass die _cfunktion02 als STDCALL kompiliert wird. Dann verschiebt sich der Stack um 1 DWORD und RET springt dahin, wo das übergebene Argument hinzeigt (ich nehme an, dass es die Adresse der 3 Funktion ist). Die nächste Verschiebung führt dann ins "Nirvana".
 
OK, Jetzt wird jede Funktion nur noch 1 mal aufgerufen.
Allerdings funktioniert der Rücksprung immer noch nicht.

Allerdings kann ich irgendwie nicht bestimmen, das die Funktion als "cdecl-Funktion" compiliert wird.
Dieser Code verursacht einen Syntaxerror:
Code:
int _cdecl main(int);
int _cdecl main(int apiaddr)
{
 //...
}

Compiler: gpp
Script:
Code:
gpp -c -Os -nostdlib -fno-builtin -fno-rtti -fno-exceptions -o x:\main.obj x:\main.cpp
 
zu meinen C Zeiten habe ich das immer unter GCC mit __cdecl/__fastcall/__stdcall geregelt.Mit gpp habe ich nich nicht gearbeitet.

Es gibt aber auch noch andere Konventionenen - "fastcall"/"Thiscall". Habe irgendwie gedacht dass Du das Ganze unter C machen wolltest und sehe jetzt "main.cpp". Was jetzt gpp genau benutzt, weiß ich nicht (am besten schaut man im Disassembler nach: http://en.wikibooks.org/wiki/Reverse_Engineering/Examples/Calling_Conventions).Du müsstest allerdings sicherstellen, mit welcher Konvention Deine ASM Funktion aufgerufen wird und wie die funktion02 aufzurufen ist. Du könntest auch mal eine Binary anhängen (egal ob ELF oder EXE) und ich schau mir im Disassembler an, was der Compiler daraus macht.
 
Zurück
Oben