Хочу добавить JIT в свой интерпретатор скриптового языка. Проблема в том, что на x86 данные в памяти могут быть доступны только либо для записи, либо для выполнения. Т.е. если записать в массив байты (опкоды машинных инструкций с RET в конце), то вызвать его как функцию уже нельзя. Погуглив, нашел, что в виртуальных машинах, упаковщиках, протекторах и т.п. используется такая схема: сначала сгенерированные опкоды записываются в стек, а стек уже может быть вызван как функция. Написал такой код:
#include <stdio.h>
#define MAX_CODE_SIZE 65536
typedef int (*FN_CALLBACK)();
int invoke(int size, unsigned char *source)
{
unsigned char buffer[MAX_CODE_SIZE];
register unsigned char *src;
register unsigned char *dest;
unsigned char *limit;
if (size <= 0 || size >= MAX_CODE_SIZE)
return 0;
src = source;
dest = buffer;
limit = buffer + size;
while (dest < limit)
*dest++ = *src++;
return ((FN_CALLBACK)((void*)buffer))();
}
unsigned char prog[] = {
0x31, 0xC0, // xor eax, eax
0x40, // inc eax
0x40, // inc eax
0xC3 // ret
};
int main(int argc, char *argv[])
{
int r;
r = invoke(5, prog);
printf("Result: %d\n", r);
return 0;
}