Во-первых, you usually want to use$zero
вместо $0
, $v0–$v1
вместо $2–$3
и т.д ... они легче понять (и запомнить), чем простые числа и монтажников также понимают это обозначение, так что нет никаких проблем с этой стороны. Также это абстрагирует ваш код от числа, поэтому, если когда-либо стандартные изменения (например, $ zero больше не $ 0, а $ 256), ваш код все равно будет собран правильно.
В каждой архитектуре ЦП существуют некоторые соглашения о том, как использовать регистры для выполнения вызовов и как вести себя с регистрами внутри функций. Это называется соглашением о звонках . Вы можете увидеть here краткое описание соглашения о вызовах MIPS.
Я слышал, что его вообще хорошая практика, чтобы сохранить регистры чистый т.е. очистить значение регистров 0 в конце программы . Итак, мой первый вопрос - как/почему это необходимо/хорошо? практика?
Я лично никогда не слышал об этой практике, но я не совсем согласен с ней. Лучшей практикой было бы восстановить предыдущие значения до начала программы.
Во-вторых, если у нас есть вызов функции с параметрами (p1, p2), хранящимися в $ 4 и $ 5; в конце нашего определения функции, необходимо ли удалить значения в 4 и 5 долларов или лучше оставить их, как они были на , в начале вызова функции?
Вы должны оставить их так, как они были в начале вызова функции. Для вызывающего абонента нет смысла изменять эти регистры.
Пространство в стеке зарезервировано для $ a0- $ a3, если вызываемому абоненту необходимо сохранить его аргументы, но регистры не сохраняются там вызывающим.
Я также видел примеры нажатия параметров в стек как это. Когда и почему это необходимо/хорошая практика?
Стек, если по определению временное хранилище. Если вы хотите зарезервировать значения регистра (например, вы хотите использовать $ aX или $ sX), вы их помещаете туда. То же самое, чем раньше:
Пространство на стеке резервируется за $ a0- $ a3 в случае вызываемая необходимо сохранить его аргументы
addi $sp, $sp, -8
Перемещает указатель стека регистр (по соглашению это $ 29). Это резервирует 8 байт в стеке.
sw $a0, 0($sp)
sw $a1, 4($sp)
экономит $ a0 к вершине стека и $ a1, как второй в стеке (имейте в виду, что стек растет в сторону более низких адресам). Это заполняет зарезервированное пространство (8 байтов). Это называется протоколом ввода функции .
; At the end of our program:
; You forgot, and it's important:
lw $a0, 0($sp)
lw $a1, 4($sp)
addi $sp, $sp, 8
Восстановление восстановленных регистров и возврат указателя стека к исходному значению. Тогда у вызывающего будет свой стек и параметры нетронутыми. И это называется протоколом выхода .
Если мы хотим использовать некоторые константы в нашей программе, скажем, 4 и 1, это лучше держать их на регистрах или в стеке?
Ни то, ни другое. Константы следует использовать в качестве непосредственных операндов:
li $t0, C ; Load 16-bit constant into $t0
lui $t0, C ; Load upper 16-bit half-word of $t0
Спасибо! Раньше я, возможно, неправильно понимал концепцию «сохранения регистров без изменений», потому что для большинства из них было 0, и я думал, что идея состоит в том, чтобы очистить их до 0 после нашей программы. Но теперь я вижу, что идея состоит в том, чтобы вернуть их обратно к их первоначальным значениям, если мы их используем. –