Von C Werte an Assembler Funktion übergeben
-
Moin,
weil rkhb meinte ich soll meine Frage nochmal am besten hier stellen mach ich das jetzt :Ich möchte von C Werte an eine Assemblerfunktion geben, nur weiß ich nicht wie ich die Daten da dann verarbeiten kann.
Ich nutze Win64 (Windows 8), mein Compiler ist GCC und ich nutze Intel-Syntax.LG
-
-
Übergabe und Rückgabe von Parametern richtet sich nach der Microsoft-x64-Calling Convention:
http://msdn.microsoft.com/en-us/library/9b372w95.aspx
http://en.wikipedia.org/wiki/X86_calling_conventions#Microsoft_x64_calling_conventionParameter werden in RCX, RDX, R8 und R9 übergeben, wobei die C-Deklaration dabei von links nach rechts gelesen wird, d.h. der erste Parameter kommt nach RCX, der zweite nach RDX usw.
Die Rückgabe geschieht normalerweise in RAX.
callee.s:
.data msg1: .asciz "EXTERN" result: .int 1 .section .text .global test_intel, test_intel_with_puts .extern puts .intel_syntax noprefix test_intel: # kein Prolog und Epilog xor eax, eax # obere Bits von EAX löschen cmp rcx, '~' setz al ret test_intel_with_puts: # Prolog, Epilog wg. Wine-C-Funktion push rbp # Prolog mov rbp,rsp sub rsp, 32 # shadow space für puts cmp rcx, '~' setz [rbp+16] # im eigenen shadow space speichern, da RCX durch puts zerstört wird lea rcx, [rip + msg1] # RIP-relative Adressierung # mov rcx, OFFSET msg1 # absolute Adressierung call puts mov al, [rbp+16] # passt scho: puts ist mit rax=13 zurückgekommen leave # Epilog ret
Hier gibt es zwei Funktionen:
test_intel
undtest_intel_with_puts
. Das liegt vorrangig daran, dass vor dem Aufruf einer Funktion ein sogenannter "shadow space" reserviert werden muss, den die Funktion dann (vielleicht) nutzt. Mein Wine stürzt ab, wenn dieser Platz nicht reserviert wird. Der shadow space kann frei genutzt werden (macht GCC genauso). Beide Funktionen vergleichen die Übergabe mit dem Buchstaben '~' und geben entsprechende Wahrheitswerte zurück. Intel-Syntax musst Du extra mit der Instruktion ".intel_syntax noprefix" einstellen.caller.c:
#include <stdio.h> extern int test_intel (int); extern int test_intel_with_puts (int); char msg0[] = "INTERN"; int test_intern (char a) { puts (msg0); return (a == '~'); } int main ( void ) { unsigned char a = '~'; int b = 99; puts ("Hallo Welt"); b = test_intern (a); printf ("%i\n",b); b = test_intel (a); printf ("test_intel\n%i\n",b); b = test_intel_with_puts (a); printf ("%i\n",b); return 0; }
Zu kompilieren mit:
gcc -m64 -o caller.exe -xassembler callee.s -xc caller.c
Du kannst auch getrennt assemblieren/kompilieren:
`as --64 -o callee.obj callee.s
gcc -m64 -o caller.exe -Wl,callee.obj caller_win64.c`
Ich hoffe, das klappt bei Dir. Ich konnte hier nur mit Wine testen. Wenn Du gar ein 32-Bit-Programm auf Deinem 64-Bit-Betriebssystem herstellen willst, dann melde Dich nochmal und teile genau(!) mit, welchen Compiler Du benutzt:
gcc --version.
viele grüße
ralph