Как создать метку с номером из переменной в 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 не постоянная времени сборки.

Другие вопросы по тегам