【发布时间】:2012-01-26 08:36:50
【问题描述】:
我打算编写自己的 JIT 解释器作为 VM 课程的一部分。我对高级语言、编译器和解释器有很多知识,但对 x86 汇编(或 C 语言)知之甚少。
实际上我不知道 JIT 是如何工作的,但这是我的看法:用某种中间语言读入程序。将其编译为 x86 指令。确保最后一条指令返回到 VM 代码中正常的地方。将指令存储在内存中的某个位置。无条件跳转到第一条指令。瞧!
因此,考虑到这一点,我有以下小型 C 程序:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int main() {
int *m = malloc(sizeof(int));
*m = 0x90; // NOP instruction code
asm("jmp *%0"
: /* outputs: */ /* none */
: /* inputs: */ "d" (m)
: /* clobbers: */ "eax");
return 42;
}
好的,所以我的目的是让这个程序将 NOP 指令存储在内存中的某个位置,然后跳转到那个位置,然后可能会崩溃(因为我没有设置任何方法让程序返回到 main)。
问题:我走对了吗?
问题:你能告诉我一个修改后的程序,它设法找到回到 main 内部某个地方的路吗?
问题:我应该注意的其他问题?
PS:我的目标是获得理解,并不一定要以正确的方式做每一件事。
感谢所有反馈。以下代码似乎是在我的 Linux 机器上开始和工作的地方:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
unsigned char *m;
int main() {
unsigned int pagesize = getpagesize();
printf("pagesize: %u\n", pagesize);
m = malloc(1023+pagesize+1);
if(m==NULL) return(1);
printf("%p\n", m);
m = (unsigned char *)(((long)m + pagesize-1) & ~(pagesize-1));
printf("%p\n", m);
if(mprotect(m, 1024, PROT_READ|PROT_EXEC|PROT_WRITE)) {
printf("mprotect fail...\n");
return 0;
}
m[0] = 0xc9; //leave
m[1] = 0xc3; //ret
m[2] = 0x90; //nop
printf("%p\n", m);
asm("jmp *%0"
: /* outputs: */ /* none */
: /* inputs: */ "d" (m)
: /* clobbers: */ "ebx");
return 21;
}
【问题讨论】:
-
另一种选择是只解释指令或中间代码,而无需直接执行任何操作。
-
@Alex:这是实现语言的另一种选择,但根据定义,它不是 JIT。