Чему соответствует этот ассемблерный код MIPS?

Я изучаю язык ассемблера MIPS. Я пытаюсь понять это упражнение. Вопрос в том:

Чему соответствует следующий код?

Name:   move    $t0,    $zero
Loop:   add     $t1,    $t0,    $t0
        add     $t1,    $t1,    $t1
        add     $t2,    $a0,    $t1
        sw      $zero,  0($t2)
        addi    $t0,    $t0,    1
        slt     $t3,    $t0,    $a1
        bne     $t3,    $zero,  Loop
        jr      $ra

Я уже знаю значение каждой инструкции, как работают директивы и что такое цикл for. Когда я пытаюсь запустить код в MIPS Mars Simulator, он заканчивается ошибкой, вероятно, потому, что значения, содержащиеся в регистрах $ a0 и $ a1, необходимы для начала.

Я не понимаю более широкой картины. Что происходит во время каждой итерации цикла? Это просто часть более крупного алгоритма? Что он должен делать?


person firstName lastName    schedule 04.02.2019    source источник
comment
Судя по всему, он просто очищает кусок памяти (устанавливает для каждого элемента значение 0).   -  person Michael    schedule 04.02.2019
comment
@Michael Да, но почему он каждый раз удваивается $t0? Вот что меня смущает.   -  person m0skit0    schedule 04.02.2019
comment
Фактически он вычисляет $t0 * 4 (потому что каждый элемент в массиве составляет 4 байта). Но понятия не имею, почему они сделали это с двумя дополнениями вместо sll $t1, $t0, 2.   -  person Michael    schedule 04.02.2019
comment
@ m0skit0: это просто запутанный способ перемещать целевой адрес на 4 байта на каждой итерации. $t0 содержит индекс массива слов, который нужно обнулить, затем умножает его на 4, выдавая два сложения.   -  person gusbro    schedule 04.02.2019
comment
@ m0skit0 Означает ли это, что количество адресов памяти $ a1 (предположительно y), начиная с адреса, содержащегося в $ a0 (предположительно addr (x)), установлено в 0, а затем цикл заканчивается?   -  person firstName lastName    schedule 04.02.2019
comment
Пожалуйста, проверьте и улучшите мой ответ. Спасибо.   -  person firstName lastName    schedule 04.02.2019


Ответы (1)


Читая комментарии, я думаю, ответ как-то яснее. В начале кода $a0 и $a1 уже должны иметь какое-то значение, предположим, что x и y соответственно.

Первая строка move $t0, $zero будет int i = 0; на языке программирования высокого уровня или начальным значением цикла do-while (condition).

Следующее:

Loop: add $t1, $t0, $t0
      add $t1, $t1, $t1

это когда цикл начинается и будет выглядеть так:

int j = 2 * i;
    j = 2 * j;

что вкратце означает int j = 4 * i;, итератор умножается на 4, потому что регистры MIPS состоят из 32 бит, что означает 4 байта.

Тогда add $t2, $a0, $t1 соответствует int k = x + j; или, другими словами, int k = x + 4 * i.

Следующая инструкция sw $zero, 0($t2) сохраняет 0 в памяти, адрес которой смещен на 0 от адреса значения, содержащегося в $t2.

addi $t0, $t0, 1 увеличивает i++; и

slt  $t3,  $t0,   $a1
bne  $t3,  $zero, Loop
jr   $ra

проверяет, удовлетворяется ли i < y, что является условием цикла do - while (i < y). Если это все еще верно, цикл переходит к 0 следующему элементу в памяти, в противном случае цикл завершается и возвращается к $ra.

person firstName lastName    schedule 04.02.2019
comment
Вместо int k = x + j; я бы написал либо uintptr_t, либо void *. Я имею в виду, что да, в asm все просто целое число, но если вы используете терминологию C, вы также можете отслеживать, какие целые числа являются адресами действительной памяти и будут разыменованы позже. - person Peter Cordes; 05.02.2019
comment
Это не for-петля. - person EOF; 05.02.2019