Skip to content

Instantly share code, notes, and snippets.

@DanielKeep
Created March 13, 2011 10:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DanielKeep/868009 to your computer and use it in GitHub Desktop.
Save DanielKeep/868009 to your computer and use it in GitHub Desktop.
module ouro.util.invokeImpl.X86_Windows.cdecl;
/**
Invokes the given function pointer.
Params:
fp = Function pointer.
ss = Size of argument stack.
sp = Pointer to bottom of argument stack.
eax = Pointer to storage for result eax register.
edx = Pointer to storage for result edx register.
st0 = Pointer to storage for result ST(0) register.
Note that this argument may be null, in which case ST(0) is
not popped.
*/
extern(C) void invoke(void* fp, uint ss, void* sp,
uint* eax, uint* edx, double* st0)
{
asm
{
naked;
push EBP;
mov EBP, ESP;
// Save registers. We can probably drop some of these.
// push EAX;
push EBX;
// push ECX;
// push EDX;
push ESI;
push EDI;
// The arguments to f(a, b, c) get pushed in reverse order. However,
// since the stack grows downwards, they end up in order in memory.
//
// We need to reduce ESP by ss to make room for them, then copy them
// onto the stack from sp.
mov ECX, ss;
sub ESP, ECX;
mov ESI, sp;
mov EDI, ESP;
cld;
loop: movsb;
dec ECX;
cmp ECX, 0;
jne loop;
// Ready to make the call.
mov EAX, fp;
call EAX;
// Clean up the stack
mov ECX, ss;
add ESP, ECX;
// We need to save EAX and EDX.
mov EDI, eax;
mov EBX, edx;
mov [EDI], EAX;
mov [EBX], EDX;
// Save ST(0) if we have a non-zero pointer.
mov EDI, st0;
cmp EDI, 0;
je noFloat;
fstp qword ptr [EDI];
noFloat:
pop EDI;
pop ESI;
// pop EDX;
// pop ECX;
pop EBX;
// pop EAX;
pop EBP;
ret;
}
}
import tango.io.Stdout;
extern(C) int add(int a, int b)
{
return a+b;
}
extern(C) int sub(int a, int b)
{
return a-b;
}
extern(C) float fsub(float a, float b)
{
return a-b;
}
void main()
{
{
int[2] args = [1, 2];
uint eax, edx;
Stdout.formatln("Calling add...");
auto fp = &add;
auto ss = args.length * 4;
auto sp = args.ptr;
Stdout.formatln(" fp = {,8:x}", fp);
Stdout.formatln(" ss = {,8:x}, sp = {,8:x}", ss, sp);
Stdout.formatln(" eax = {,8:x}, edx = {,8:x}", &eax, &edx);
tramp(fp, args.length*4, args.ptr, &eax, &edx, null);
Stdout.formatln("Returned.");
Stdout.formatln(" eax = {,8:x}", eax);
Stdout.formatln(" edx = {,8:x}", edx);
}
{
int[2] args = [1, 2];
uint eax, edx;
Stdout.formatln("Calling sub...");
auto fp = ⊂
auto ss = args.length * 4;
auto sp = args.ptr;
Stdout.formatln(" fp = {,8:x}", fp);
Stdout.formatln(" ss = {,8:x}, sp = {,8:x}", ss, sp);
Stdout.formatln(" eax = {,8:x}, edx = {,8:x}", &eax, &edx);
tramp(fp, args.length*4, args.ptr, &eax, &edx, null);
Stdout.formatln("Returned.");
Stdout.formatln(" eax = {,8:x}", eax);
Stdout.formatln(" edx = {,8:x}", edx);
}
{
float[2] args = [3.0, 0.5];
uint eax, edx; double st0;
Stdout.formatln("Calling fsub...");
auto fp = &fsub;
auto ss = args.length * 4;
auto sp = args.ptr;
Stdout.formatln(" fp = {,8:x}", fp);
Stdout.formatln(" ss = {,8:x}, sp = {,8:x}", ss, sp);
Stdout.formatln(" eax = {,8:x}, edx = {,8:x}", &eax, &edx);
tramp(fp, args.length*4, args.ptr, &eax, &edx, &st0);
Stdout.formatln("Returned.");
Stdout.formatln(" eax = {,8:x}", eax);
Stdout.formatln(" edx = {,8:x}", edx);
Stdout.formatln(" st0 = {,8}", st0);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment