Какая особенность C ++ использует инструкции JR? - PullRequest
0 голосов
/ 21 октября 2019

Инструкция MIPS Jump Register (JR) часто встречается в двоичном коде C ++. В результате, какая функция в C ++ использует инструкции JR и почему она использует эти инструкции?

1 Ответ

1 голос
/ 21 октября 2019

Как прокомментировал Николь, многие вещи могут его использовать, но для одного простого примера это указатель функции или таблица переходов (как в большом блоке переключателей). Vtable в C ++ также является примером указателя функции

typedef int (*func)(int);

int doSomething(func f, int x, int y)
{
    switch(x)
    {
        case 0:
            return f(x + y);
        case 1:
            return f(x + 2*y);
        case 2:
            return f(2*x + y);
        case 3:
            return f(x - y);
        case 4:
            return f(3*x + y);
        case 5:
            return f(x * y);
        case 6:
            return f(x);
        case 7:
            return f(y);
        default:
            return 3;
    }
}

GCC компилирует приведенный выше код в

doSomething(int (*)(int), int, int):
        sltu    $2,$5,8
        beq     $2,$0,$L2 # x >= 8: default case
        move    $25,$4

        lui     $2,%hi($L4)
        addiu   $2,$2,%lo($L4)  # load address of $L4 to $2
        sll     $5,$5,2         # effective address = $L4 + x*4
        addu    $5,$2,$5
        lw      $2,0($5)
        nop
        j       $2
        nop

$L4:
        .word   $L11
        .word   $L5
        .word   $L6
        .word   $L7
        .word   $L8
        .word   $L9
        .word   $L10
        .word   $L11
$L11:
        jr      $25
        move    $4,$6

$L9:
        sll     $4,$6,2
        jr      $25
        addu    $4,$4,$6
# ... many more cases below

Полный вывод можно увидеть в Compiler Explorer

$L4 - это таблица переходов, содержащая адрес места, к которому вы переходите, то есть блоков case в этом фрагменте. Его адрес хранится в $2, и jr необходимо использовать для перемещения указателя инструкции на этот адрес. j $2 показано выше, но я думаю, что это ошибка дизассемблера, так как j не может получить операнд регистра. Как только вы попали в правильный регистр, тогда jr снова используется для вызова указателя функции f

В общем, в любом случае, целевой адрес не известен статически и должен быть рассчитан / загружен ввремя выполнения тогда jr должно быть использовано

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...