R
Ü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_convention
Parameter 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 und test_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