#include #include #include #include #include typedef struct { void *data; size_t pos, sz; } args; args a_new(size_t sz); void a_destroy(args *a); void a_push(args *a, void *arg); void a_print(args a); int __fastcall a_exec(args a, FARPROC fun); args a_new(size_t sz) { args a = (args) { .pos = 0, .sz = (sz+3) & ~3, // align to 4 bytes }; if (!(a.data = calloc(a.sz, 1))) { perror("calloc"); exit(errno); } return a; } void a_destroy(args *a) { memset(a->data, -1, a->sz); free(a->data); memset(a, 0, sizeof(args)); } void a_push(args *a, void *arg) { if (a->pos == a->sz) { a->sz *= 2; void *old = a->data; if (!(a->data = realloc(a->data, a->sz))) { a_destroy(old); perror("realloc"); exit(errno); } memset(a->data + a->sz/2, 0, a->sz/2); } memcpy(a->data + a->pos, arg, 4); a->pos += 4; } void a_print(args a) { for (unsigned int i = 0; i < a.sz; i+=4) { if (i == 0 || i == a.pos) puts("################################"); int val = *(int*)(a.data + i); printf("%.2d %.8x\n", i, val); } } int __fastcall a_exec(args a, FARPROC fun) { int res; __asm__ __volatile__ ( "movl %1, %%esi # source = a->data \n\t" "subl %2, %%esp # make space on stack \n\t" "movl %%esp, %%edi # dest = stack \n\t" "shrl $2, %2 # dword == 4 bytes \n\t" "rep movsd # copy args onto stack \n\t" "call *%3 # call fun (stdcall) \n\t" "movl %%eax, %0 # preserve result \n\t" : "=r" (res) : "r" (a.data), "c" (a.pos), "r" (fun) : "%esi", "%edi", "%eax" ); return res; } int main(int c, char *v[static 3]) { void *dll = LoadLibrary(v[1]); if (!dll) return -1; FARPROC fun = GetProcAddress(dll, v[2]); if (!fun) return -2; args a = a_new(64); for (int i=3; i