#if defined(_WIN32) || defined(WIN32) #define OS_WINDOWS #endif #include #include #include #ifdef OS_WINDOWS #include #else #include #endif #ifdef _MSC_VER #define STDCALL __stdcall #else #define STDCALL __attribute__((stdcall)) #endif char data[1<<16]; // __stdcall makes the callee pop the arguments from the stack upon return void STDCALL Put(char ch) { printf("%c", ch); } void STDCALL PutLn() { printf("\n"); } int main(int argc, char* argv[]) { /* check arguments */ if (argc != 2) { printf("usage: %s \n", argv[0]); return -1; } /* load the code file */ FILE* fin = fopen(argv[1], "rb"); if (fin == NULL) { printf("couldn't open %s\n", argv[1]); return -2; } #ifdef OS_WINDOWS char* code = (char*) VirtualAllocEx(GetCurrentProcess(), 0, 1<<16, MEM_COMMIT, PAGE_EXECUTE_READWRITE); #else char* code = (char*) mmap(NULL, 1<<16, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); #endif size_t size = fread(code, 1, 1<<16, fin); fclose(fin); printf("loaded %i bytes\n", size); printf("executing...\n"); /* setup the global data block */ memset(data, 0, sizeof(data)); ((void**)data)[0] = (void*)Put; ((void**)data)[1] = (void*)PutLn; /* set edi and jump to the code block */ void* start = code; #ifdef __GNUC__ __asm__ ("call *%%eax" : /* */ : "a" (start), "D" (data) : /* */ ); #else __asm { lea edi, data; call start; }; #endif printf("finished...\n"); #ifdef OS_WINDOWS #else munmap(code, 1<<16); #endif return 0; }