Странное поведение ассемблера MIPS с инструкцией перехода (и ссылки)
====================================================================

Итак, мы изучаем архитектуру MIPS в школе и внедряем архитектуру MIPS32. Я думал, что я буду использовать GNU cross-binutils в качестве ассемблера, но я получаю странный вывод при работе с инструкциями jal, j и jr. Кажется, ассемблер вставляет инструкции в неправильных местах. Я понятия не имею, почему это происходит, и я сомневаюсь, что ассемблер MIPS будет так сломан, поэтому я предполагаю, что это должно произойти.

Вот мой фиктивный файл сборки:

Однако, когда я разбираю, я получаю этот вывод:

Это какая-то архитектурная причуда? Если да, то в чем причина этого?

РЕДАКТИРОВАТЬ: Протестировано добавление некоторых NOP только для черта ...

и это дает мне что-то, что кажется несколько правильным.

Почему jal и j меняются местами с последней инструкцией?

MIPS имеет явную опасность для трубопроводов; Инструкция, следующая непосредственно за инструкцией перехода или перехода, всегда будет выполняться (эту инструкцию иногда называют «интервалом задержки перехода»). Если ваш код был действительно собран именно так, как вы его написали:

тогда`add` Инструкция будет выполняться дважды за то время, что`jal` происходит: один раз в интервале задержки и один раз в следующем цикле, когда изменение счетчика программы действительно вступило в силу.

По умолчанию ассемблер GNU переупорядочивает инструкции для вас: ясно, что второй`addi` всегда должен выполняться, поэтому его можно поменять местами с`jal` инструкция, так что`addi` перемещается в отсек задержки. (В случаях, когда ассемблер не может сделать вывод, что это безопасно, он вставит`nop` вместо этого в отсек задержки.)

Если вы не хотите, чтобы он делал это для вас, добавьте директиву

в верхней части вашего исходного файла. В этом случае вы сами должны разобраться с опасностями. Если вы сделаете это, я рекомендую пометить слоты задержки так, чтобы они выделялись, например добавив дополнительный пробел (или два) отступа. Например: