Как создать метку с номером из переменной в asm
Я хочу написать JIT-компилятор, который будет основан на интерпретаторе Brainfuck. Весь код программы будет написан на языке 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? Это мне очень поможет. Буду благодарен за ответ. Заранее спасибо!
1 ответ
Вы не можете безопасно переходить от одного утверждения asm к другому. Ты можешь использовать asm goto
чтобы сказать компилятору, что вы можете перейти к метке C, а не провалиться.
Но есть и фатальный недостаток, связанный с вашей идеей смешивать asm и C для использования стека вызовов в качестве структуры данных стека:вы не можете оставитьrsp
изменено в конце оператора asm. Вы нарушите сгенерированный компилятором код, который ссылается на стековую память относительно RSP, потому что -fomit-frame-pointer
включен по умолчанию (кроме -O0
). И даже если нет, компилятор предполагает, что он знает, куда указывает RSP, даже в функциях, которые используют указатель кадра.
КСТАТИ, pushl
недопустимо в 64-битном коде, только 16 и 64-битные размеры операндов для push
доступны.
Кроме того, если вы собираетесь pop
в регистр, вы должны использовать выходной операнд для этого ограничения, а не вход.
Есть еще один фатальный недостаток: inline-asm не может JIT. Весь ассм должен быть там во время сборки. Так же, как шаблоны C++, start_of_the_loop<number_of_brackets>
не может работать, если number_of_brackets
не постоянная времени сборки.