如何动态生成和运行本机代码?

我想为我编写的玩具语言处理器(纯学术性)编写一个非常小的概念验证JIT编译器,但我在设计的中间阶段遇到了一些麻烦。从概念上讲,我熟悉JIT的工作原理——将字节码编译成(机器或程序集?)代码来运行。然而,在螺母和螺栓的层面上,我不太了解你实际上是如何做的

我(非常“新手”)的下意识反应是,因为我不知道从哪里开始,我会尝试下面的方法:

  1. mmap()内存块,设置对PROT_EXEC的访问
  2. 将本机代码写入块中
  3. 将当前寄存器(堆栈指针等)存储在舒适的地方
  4. 修改当前寄存器以指向映射区域中的本机代码块
  5. 本机代码现在将由计算机执行
  6. 恢复以前的寄存器

这是否与正确的算法非常接近?我试过阅读我知道有JIT编译器要研究的不同项目(如V8),但这些代码库由于其大小而很难使用,我不知道从哪里开始寻找

answer=“4912662”的数据

不确定linux,但这在x86/windows上有效。
更新:http://codepad.org/sQoF6kR8

#包括<标准h>
#包括<windows.h>
typedef无符号字符字节;
int arg1;
int-arg2;
int res1;
类型定义无效(*pfunc)(无效);
联合函数{
pfunc-x;
字节*y;
};
内部主(空){
字节*buf=(字节*)VirtualAllocEx(GetCurrentProcess(),0,1<<16,MEM\u COMMIT,PAGE\u EXECUTE\u READWRITE);
如果(buf==0)返回0;
字节*p=buf;
*p++=0x50;//推送eax
*p++=0x52;//推送edx
*p++=0xA1;//mov eax[arg2]
(int*)p[0]=&arg2;p+=sizeof(int*);
*p++=0x92;//xchg-edx,eax
*p++=0xA1;//mov eax[arg1]
(int*)p[0]=&arg1;p+=sizeof(int*);
*p++=0xF7;*p++=0xEA;//imul edx
*p++=0xA3;//mov[res1],eax
(int*)p[0]=&res1;p+=sizeof(int*);
*p++=0x5A;//pop edx
*p++=0x58;//pop eax
*p++=0xC3;//ret
funcptr func;
func.y=buf;
arg1=123;arg2=321;res1=0;
func.x();//调用生成的代码
printf(“arg1=%i arg2=%i arg1*arg2=%i func(arg1,arg2)=%i\n”,arg1,arg2,arg1*arg2,res1);
}

发表评论