Я собираюсь написать свой собственный JIT-интерпретатор в рамках курса по виртуальным машинам.У меня много знаний о языках высокого уровня, компиляторах и интерпретаторах, но мало или совсем нет знаний о сборке 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?
Вопрос: Другие вопросы, которые мне следует остерегаться?
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;
}