私は自分のJITインタープリタをVM上のコースの一部として書くつもりです。私は高水準の言語、コンパイラ、インタプリタについて多くの知識を持っていますが、x86アセンブリ(またはそれに関してはC)に関する知識はほとんどまたはまったくありません。私は自分自身のJITインタープリタを書いています。生成された命令をどのように実行すればよいですか?
実際、私はJITの仕組みが分かりませんが、ここでは私の取り組みです:プログラムでいくつかの中間言語を読んでください。 x86命令にコンパイルしてください。最後の命令がVMコードのどこかに戻っていることを確認してください。命令をメモリのどこに格納しますか。最初の命令に無条件にジャンプします。 Voila!
#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命令を格納するためので、私の意図がある、ジャンプ:
だから、このことを念頭に置いて、私は次の小さなCプログラムを持っています(私はプログラムをメインに戻すための方法を設定していないので)おそらくクラッシュします。
質問:私は正しい道にいるのですか?
質問:メインのどこかに戻る方法を見つけ出すために変更されたプログラムを表示できますか?
質問:その他の注意すべき点はありますか?
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;
}
別のオプションは、単に/ wの命令または中間コードを解釈することですo何かを直接実行する。 –
@Alex:それは言語を実装する別のオプションですが、定義上、JITではありません。 –