Возвращение значения при прыжках между функциями

В процессе разработки виртуальной машины мне понадобилось написать обработчик прерываний BIOS.
Если кратко то:

void bios_call(uint8_t code) {
    switch(code) {
    ...
    case 2:
        goto NMI_CALL;
        break;
    ...
    }
int main()
{
    ...
    NMI_CALL:
        printf("Called interput NMI(int 2)\n");
        system("pause");
        return 1;
}

Из-за goto я не знаю от какой функции return 1; вернёт 1(bios_call или main).
Наверное понадобится что-то типа asm("pop"), чтобы вернуть управление main()

Да, код не работает, да и прерывания должны находиться в IVT(в памяти), а не во внешней функции, так что вопрос бессмыслен, но из-за правил StackOverflow я не могу удалить(на вопрос уже ответили). Простите.


Ответы (3 шт):

Автор решения: HelloWorld

Попробуй функции выхода из <stdlib.h>, например exit

void bios_call(uint8_t code) {
    switch(code) {
    ...
    case 2:
        printf("Called interput NMI(int 2)\n");
        system("pause");
        exit(1);
    ...
    }
int main()
{
    ...
}
→ Ссылка
Автор решения: mazik7512

Есть два варианта решения вашей проблемы:


Первый вариант

Его предложил @HelloWorld в своём ответе. Я его несколько обобщу.

Суть решения: Уход от использования goto (почему не стоит их использовать в высокоуровневых языках можете прочитать здесь или по первой ссылке в поисковике по запросу "почему не стоит использовать goto").

Например, можете либо писать код для действия прямо внутри case, как предложил @HelloWorld, либо писать отдельные функции обработчики каждой инструкции:

// обработчик инструкции NMI_CALL
void NMI_CALL_handler() {
    printf("Called interput NMI(int 2)\n");
    system("pause");
    exit(1);
}

void bios_call(uint8_t code) {
    switch(code) {
    ...
    case 2:
        NMI_CALL_handler();
        break; // если в обработчике будет exit, break не нужен
    ...
    }
int main()
{
    ...
}

Второй вариант

Суть решения: использование списка (enum) инструкций и обрабатывающего цикла.

Судя по приведенному вами ответу, структура вашей программы несколько нетипичная для C++, попробуйте изменить структура вашей программы следующим образом:

enum Instructions {
    INSTR_1 = 1,
    NMI_CALL = 2,
    ...
};

...

// обработчик NMI_CALL
void NMI_CALL_handler() {
    printf("Called interput NMI(int 2)\n");
    system("pause");
    exit(1);
}

...

// обработка итерации цикла
void execution_iter(uint8_t code) {
    switch(code) {
        ...
        case Instructions.NMI_CALL:
            NMI_CALL_handler();
            break;
    }

}

// главный цикл обработки инструкций
void execution_loop(/* список инструкций */) {
    for (/* цикл по списку */) {
        uint8_t code = /* получить след. инструкцию из списка */
        execution_iter(code);
    }
}

int main()
{
    ...
    execution_loop(/* список инструкций */);
    ...

}

→ Ссылка
Автор решения: Serge3leo

Если за C++, то, очевидно, неким аналогом "прерываний" или межпроцедурного goto являются исключения:

void bios_call(uint8_t code) {
    switch(code) {
    ...
    case 2:
        throw NMI_CALL;
    ...
    }
}
int main()
{
    try {
        ...
    } catch(const NMI_CALL& e) {
        printf("Called interput NMI(int 2)\n");
        system("pause");
        return 1;
    }
}

Если за C, то аналог межпроцедурного goto это setjmp()/longjmp() (при использовании в C++, не вызывают деструкторы объектов на стеке, т.е. строго говоря в C++ применимы только для использования функций POSIX с последующим жёстким _Exit(), ни какого либерализма и ни каких return для C++, собственно для чего их в стандарте C++, возможно, и сохранили):

void bios_call(uint8_t code) {
    switch(code) {
    ...
    case 2:
        longjmp(NMI_CALL_buf, NMI_CALL_code);
    ...
    }
}
int main()
{
    if (setjmp(NMI_CALL_buf) {
        // ветка возврата с NMI_CALL_code
        printf("Called interput NMI(int 2)\n");
        system("pause");
        return 1;
    }
    ....
}

Так же аналогом прерываний могут служить сигналы, но это больше про прерывания с обработкой, возвратом и продолжением.

→ Ссылка