Что хранится в $ ra, прежде чем мы выполним JAL в рекурсивной функции - PullRequest
0 голосов
/ 03 мая 2020

enter image description here

На 1-й итерации этой функции мы можем выполнить recur: и выполнить следующую строку: sw $ra, 0($sp), которая выполняется перед любым оператором jal. Из того, что я понимаю, оператор jal (переход и ссылка) будет введен в регистр $ra, местоположение непосредственно после jal. Так что же происходит в примере, если в $ra еще ничего не сохранено?

1 Ответ

2 голосов
/ 03 мая 2020

Это функция; при записи $ra содержит адрес возврата, на который ваш абонент хочет, чтобы вы перескочили назад.

Наряду с наличием первых 4 целочисленных аргументов в $ a0 .. $ a3, это является частью контракта между вызывающим и вызываемым абонентом. это необходимо для того, чтобы они согласились заставить вызовы функций работать. Эта часть соглашения о вызовах , конечно, разработана на основе инструкции MIPS jal, поэтому вызов / возврат функции может быть выполнен с помощью одной инструкции каждая. Именно поэтому $31 имеет символ c name $ra = обратный адрес.


Регистр не может содержать «ничто», это всегда 32-битное значение.

Если какой-то код установит $ra в 0 или неверный адрес и перейдет к этой функции с помощью j вместо jal, он вернется к sh, когда вернется, и это будет ошибкой вызывающего. Ваша функция может просто предположить, что $ra содержит действительный адрес возврата при входе в функцию, будь то рекурсивный вызов или какой-либо другой вызывающий объект.

(Это своего рода точка рекурсивных функций, которую вы действительно просто выполняем вызов функции для этой функции, и не имеет значения, откуда вы вызвали.)


Обратите внимание, что метка верхнего уровня в программе (например, в симуляторе MARS) равна не строго функция.

В MARS этот ярлык обычно называют main, несмотря на тот факт, что $ra содержит мусор или 0 в этой точке, поэтому он должен выйти с выход из системного вызова; jr $ra приведет к sh.

(В C, main - это истинная функция, которая обычно достигается из точки входа _start, которая устанавливает вещи перед вызовом main. В C Сам по себе main может быть рекурсивным без каких-либо специальных уловок. Если вы пишете программы для запуска под реальной ОС, а не игрушечной системой, которую эмулирует MARS, вы обычно используете метку _start: для своей истинной точки входа из ядра, или вы просто напишите основную и ссылку с кодом запуска, предоставляемым библиотекой C, которая вызывает main.)

...