Конвертировать C в MIPS - вложенные массивы - PullRequest
5 голосов
/ 04 октября 2011

Я изучаю язык ассемблера MIPS и наткнулся на этот пример в книге, и мне он кажется неверным.Если это не так, то это будет не первая ошибка, которую я обнаружил в этой книге.

Переменным f и g назначены регистры $s0 и $s1 соответственно, базовые адреса для массивов.A и B - $s6 и $s7 соответственно.

Пример кода c:

f = g - A[B[4]];

И соответствующая сборка MIPS:

lw  $t0, 16($s7)
lw  $s0, 0($t0)
sub $s0, $s1, $s0

Насколько я понимаю, приведенный выше код MIPS загружает некоторые случайные данные из памяти по адресу, предоставленному $t0, а затем вычитает их из $s1 и не обращается к индексу $t0 массива, обозначенному в $s6.

Правильная сборка MIPS, насколько я понимаю, будет выглядеть следующим образом:

lw  $t0, 4($s7)
add $t0, $t0, $s6
sll $t0, $t0, 2
lw  $s0, 0($t0)
sub $s0, $s1, $s0

Я прав, что это ошибка в книге или я что-то неправильно понимаю.


Редактировать: Исправлена ​​ошибка в исправленном коде MIPS, указанная Крисом Доддом

Ответы [ 3 ]

5 голосов
/ 14 сентября 2012

Это для всех (возможно, студентов CprE 381), которые могут наткнуться на это в поисках хорошего примера.Отредактированный код OP по-прежнему неверен.Смещение в первой функции слова загрузки должно быть 16. Может быть 4, если ширина памяти составляет 32 бита, но тогда сдвиг / умножение не потребуется.Предполагая, что объем памяти составляет 8 бит, функции добавления и сдвига необходимо переключать.В коде OP это умножение адреса A [B [4] / 4] на 4. Сначала сдвиг / умножение получит правильный индекс.Правильный код:

lw  $t0, 16($s7)   # gets the value of B[4]
                   # offset could be 4 depending on memory width
                   # but then the shift would not be needed
sll $t0, $t0, 2    # this multiplies the index by 4 to get the address offset
add $t0, $t0, $s6  # adds the base address of A and the offset
lw  $t0, 0($t0)    # loads the value at the address
sub $s0, $s1, $t0  # performs subtraction and stores in f

На случай, если кто-то запутается в отношении полного смещения 16 против 4 и необходимости смещения, позвольте мне объяснить.Если ширина памяти составляет 32 бита, то все 32-битное целое число может храниться в одной ячейке памяти.Если это так, то индекс массива совпадает со смещением адреса.Однако, если объем памяти составляет всего 8 бит (1 байт), то 32-разрядное целое число сохраняется в 4 ячейках памяти (1 адрес на каждый байт).Вот почему вам нужно сместить индекс на 2 (или умножить на 4), чтобы получить правильное смещение адреса.

0 голосов
/ 06 октября 2011

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

0 голосов
/ 04 октября 2011

Но вполне может быть, что автор скопировал код до времени ссылки.Это оставило бы открытой возможность того, что компоновщик заполняет адрес памяти A [] вместо 0 в операторе

  lw  $s0, 0($t0)

в конечном исполняемом файле.Я не знаю, разрешает ли MIPS смещения такого размера (то есть диапазон адресов, в котором наконец помещается A []).Это, конечно, не очень хороший способ объяснить что-то в книге, молча нарушая собственные принципы и вообще не зная, что происходит.

...