我想编写将基于Brainfuck解释器的JIT编译器。程序的整个代码将用C编写。我创建了除循环外的所有指令。我有一个想法来计算匹配的循环括号的偏移量,但是要做到这一点,我需要在具有唯一编号的asm中创建本地标签。但是标签名称中的每个数字都应该是变量中的一个值。这就是我要在C中执行的操作:
void jit(struct bf_state *state, char *source)
{
size_t number_of_brackets = 0;
while (source[state->source_ptr] != '\0')
{
switch (source[state->source_ptr])
{
case '[':
{
number_of_brackets++;
__asm__ ("start_of_the_loop<number_of_brackets>:\n\t"
"pushl <number_of_brackets>\n\t"
"cmpb $0, (%%rax)\n\t"
"je <end_of_the_loop<number_of_brackets>>"
:
: "a" (state->memory_segment), "d" (number_of_brackets));
}
break;
case ']':
{
__asm__ ("end_of_the_loop<number_of_brackets>:\n\t"
"popl %%edx\n\t"
"cmpb $0, (%%rax)\n\t"
"jne <start_of_the_loop<number_of_brackets>>"
:
: "a" (state->memory_segment), "d" (number_of_brackets));
}
break;
}
}
}
我可以用asm中变量的数字创建标签吗?这对我有很大帮助。我将不胜感激。预先谢谢你!
答案 0 :(得分:1)
您不能安全地从一个asm语句跳转到另一个。您可以使用asm goto
来告诉编译器,您可能会跳转到C标签而不是失败。
但是您的整个想法存在致命缺陷,那就是将asm和C混合使用以将调用堆栈用作堆栈数据结构:您不能在asm语句的末尾修改rsp
。您将破坏编译器生成的代码,这些代码引用相对于RSP的堆栈内存,因为默认情况下-fomit-frame-pointer
处于启用状态(-O0
除外)。即使没有,编译器仍假定即使在使用帧指针的函数中,RSP仍指向何处。
顺便说一句,pushl
在64位代码中是非法的,push
仅提供16和64位操作数大小。
此外,如果要将pop
放入寄存器,则应将输出操作数用于该约束,而不是输入。
还有另一个致命缺陷: inline-asm无法JIT 。所有asm必须在构建时存在。就像C ++模板一样,如果start_of_the_loop<number_of_brackets>
不是汇编时间常量,number_of_brackets
就无法工作。