asm in c++: beliebige funktionen manuell aufrufen
-
Hallo asm-freaks
Also ich kenne mich mit der linux-gcc asm syntax aus, jetzt will ich aber einen asm code in ein VC++ project einfügen, und da stellen sich mir einige schwierigkeiten
Ich will eine c++ funktion machen, welche folgenden header hat:
// use assembly to push arguments on stack and then call the given function. void make_assembly_call (DWORD func_ptr, DWORD* arg_list, int arg_count, int is_function, char return_type) { // preconditions assert(func_ptr != NULL); // func_ptr may not be NULL. void (*cmd_void_ptr)(void); // definition of command_ptr. takes no arguments, returntype is void. DWORD ret_dword = 0; cmd_void_ptr = (void(__cdecl*)(void))func_ptr; // get command_ptr. // use asm to push function arguments on stack in a loop.
Der comment sagt es ja eigentlich schon; die funktion soll per asm beliebig viele dword argumente auf den stack pushen (sie sind bereits in invertierter Reihenfolge), und dann zum funktions ptr springen (call ausführen).
Danach soll der eax ausgelesen werden und je nach return_type gecastet werden.ok also mein asm code sieht so aus:
// use asm to push function arguments on stack in a loop. __asm { mov ecx, 0 // initialize for-loop-variable. for_loop: // start of for-loop. push arg_list[ecx*4] // push dword of arg_list on stack. inc ecx // increment for-loop-var cmp ecx, arg_count // if ecx < arg_count ... jl for_loop // jmp to for_loop. push return_ptr // else push return_ptr call cmd_void_ptr // and call function return_ptr: // return lbl used to get ptr address. mov ret_dword, eax // store eax(return) in ret_dword add esp, 4 // ???? 'remove' return_ptr ???? add esp, [arg_count*4] // 'remove' pushed args. }
also es happert mit folgendem: die elemente des dword arrays auf den stack pushen, dann wundert mich wieso ich den return_ptr vom stack 'wegaddieren' muss, ich dachte ret popt den return pointer ??
und dann noch der letzte befehl scheint er nich zu mögen (oder doch?)Weiterhin bin ich mir nich sicher ob ich 8byte variablen richtig gesplittet habe (zB double und LONGLONG): im array sind zuerst die hinteren 4 bytes, dann die vorderen.
Es wäre echt toll wenn mir da jemand weiterhelfen könnte, oder auch mit einem link wo ich mir mehr beibringen kann.
Danke!!
gruss,
Barnski
-
call cmd_void_ptr pusht die rückkehradresse implizit - folglich ist das vorherige push return_ptr überflüssig (und du musst es anschliessend wieder aufräumen). ich vermute auch, dass die argumente in der falschen reihenfolge gespeichert werden. das argument array wird von vorne nach hinten durchlaufen, der stack wächst aber zu niedrigen adressen hin, folglich wird hier die reihenfolge umgekehrt (das kann nat. das sein, was du willst, ich kenne ja den rest des codes nicht). add esp, [arg_count*4] wird ebenfalls nicht das tun, was du willst (eigentlich sollte es überhaupt nicht kompilieren) - argumentnamen weren letzlich immer zu etwas der form [esp+x] bzw. [ebp+x] aufgelöst.
wenn wir annehmen, dass das nicht gewollt ist, könnte das ganze etwa so aussehen:__asm { mov ecx, arg_count neg ecx lea esp, [esp+ecx*4] neg ecx mov esi, arg_list mov edi, esp rep movsd call cmd_void_ptr mov ret_dword, eax mov ecx, arg_count lea esp, [esp+ecx*4] }
-
Danke camper, sieht schon viel besser aus.
Zum array der dwords (argumente) arg_list:
Ich speichere das vorhin bereits verkehrt, allerdings is es natürlich besser wenn man es in assembly gleich richtig macht.
Die befehle "rep movsd" sind mir neu. Ich hab gegoogelt und da steht was von string copy im dword schritt. sind edi und esi die pointers? (das s und d in movsd?) und wie wird sicher gestellt wieviele dwords kopiert werden?dann gibt es noch ein prob zu klären, und zwar wusste ich nich wie double und longlong variablen übergeben werden (8 bytes). das werde ich schon herausfinden (einfach zwei dwords pushen), aber was mich wundert is wie man einen 8byte typ zurückgibt?
PS; du hast schon recht, mein ursprünglicher code hat so nicht compiliert, das hat ich einfach so gelassen um den zweck/sinn des codes zu zeigen.
-
Es funktioniert jetzt einwandfrei, vielen Dank!