Существует лот сложности, который входит в любой вид полного ответа здесь.Однако для сборки MIPS мы можем [см. Комментарии ниже] получить небольшой перерыв.
Нам нужно будет рассмотреть режимы адресации и концепцию относительной адресации против абсолютная адресация .Это связано с тем, что, как отмечал zwol в комментарии , выходные данные компиляторов и ассемблеров, как правило, на самом деле не готовы к работе код , а скорее являются объектными файлами полный инструкций, которые интерпретируются компоновщиком и / или загрузчиком .
компоновщик - это программа, которая принимает несколько объектных файлов и объединяет их вболее полная программа.Это может принимать форму другого объектного файла или библиотеки, которая по сути является коллекцией объектных файлов.Если формат библиотеки достаточно прост, библиотека может быть построена просто путем объединения объектных файлов с возможностью добавления оглавления, но иногда вы хотите выполнить определенное количество предварительных ссылок, чтобы соединить конкретные объектные файлы вместе внеразрушимый блок для последующего связывания с другими объектными файлами или библиотеками.Компоновщики могут быть довольно сложными, поскольку им, возможно, придется иметь дело с символическими именами (именами функций и переменных) и предоставлять информацию для отладчиков (таблиц символов, описаний областей памяти и т. Д.).
A loader принимает объектные файлы, которые часто по крайней мере частично разрешаются компоновщиком, иногда полностью разрешаются, и загружают их в память.Некоторые загрузчики сами по себе являются компоновщиками типа, обычно называемого runtime linker или runtime loader.Это позволяет исполняемым объектным файлам загружать другие объектные файлы во время выполнения, а не предварительно связывать все заранее.
Так или иначе, хотя обычно операция времени загрузки назначает фактическоеадреса к коду и данным.Объектный файл может содержать инструкции, которые говорят, что код может выполняться где угодно или что код должен выполняться по какому-то определенному (фиксированному) адресу.Те же правила могут применяться к данным.Если требуется фиксированный адрес, возможно, этот адрес недоступен, поэтому часто желательно перемещаемый код - код, который можно переместить с какого-либо адреса по умолчанию на другой другой адрес.
Это приводит к концепции относительной адресации .Предположим, что машина работает, выполняя несколько очень простых шагов:
- Загрузка инструкции с адреса, указанного в регистре IP (указатель инструкций) или ПК (счетчик команд).
- Увеличьте этот регистр нанекоторая константа, например 4.
- Выполнить только что загруженную инструкцию.
A ответвление инструкция состоит из директивы change theРегистр IP / ПК, либо до какого-либо нового значения, либо путем добавления или вычитания некоторого значения.
Теперь предположим, что исполняемый объектный файл рекомендует чтобы программа загружалась, например, по адресу 0x04000000
.Предположим далее, что десятая инструкция, которая будет находиться по адресу 0x04000028
, является инструкцией ветвления, и что она должна быть настроена так, чтобы инструкция next была загружена из 0x0400000c
, т.е. третья инструкция:
04000000 instruction#0
04000004 instruction#1
04000008 instruction#2
0400000c loop: instruction#3
04000010 #4
04000014 #5
04000018 #6
0400001c #7
04000020 #8
04000024 #9
04000028 j loop
0400002c
Учитывая нашу модель выше, регистр IP или ПК будет, во время выполнения инструкции # 10, j loop
, который переходит к инструкции # 3,удерживайте значение 0400002c
, потому что мы описали операцию как «загрузить, увеличить на 4, выполнить».
Еслинам нужно использовать абсолютную адресацию, нам нужна актуальная j loop
инструкция, чтобы вставить буквальное значение 0400000c
непосредственно в регистр указателя инструкций.Однако только загрузчик может знать, действительно ли программа работает с 04000000
.Если этот адрес использовался, загрузчик мог вместо этого переместить программу на 08000000
, и вместо этого значение для вставки в регистр ip теперь 0800000c
.
Если мы используем относительныйТем не менее, , обращаясь к инструкции j loop
, необходимо собрать в машинный код, который говорит не «перейти к 0400000c
», а «идти вперед или назад от того места, где мы сейчас находимся, 0400002c
, туда, где мыхочу быть на 0400000c
".Это, очевидно, обратный скачок, на 0400002c - 0400000c
или 20 (шестнадцатеричный, 32 десятичный) байт или на восемь инструкций.
Редактировать : см. Комментарии ниже, следующая часть была неправильной -Я полагался на другой ответ StackOverflow и на веб-страницу, на которую я ссылаюсь, чтобы предположить переходы с ПК.Я обновил это, чтобы использовать абсолютную адресацию для команд j
.
Процессоры MIPS используют регистр с именем pc
(но труднодоступный) и поддерживают относительную адресацию в условных ветвях (например, beq
; см. Сборочный режим относительной адресации ПК ).Следовательно, некоторые из сложностей могут исчезнуть: нам нужно только поручить ЦПУ перейти назад на восемь инструкций, т. Е. Добавить отрицательную восьмерку в регистр ПК.CPU автоматически умножает это значение на 4, так что оно добавляет отрицательное значение-32.Если бы мы были действительно загружены в 04000000
, pc
будет 0400002c
, и перемещение его назад сильно изменит его на 0400000c
, что мы и хотим.Если бы мы действительно были загружены в 08000000
вместо этого, то же самое движение относительно приводит нас к 0800000c
, что мы и хотим.
Это было бы так, если бы мы использовали b
инструкция.Но инструкции j
являются абсолютными в пределах области 256 МБ: они просто перезаписывают младшие 28 бит счетчика программы.
Как правило, у нас будет ассемблер, выводящий нашу абсолютную инструкцию jump
с типом перемещенияэто говорит любому загрузчику во время выполнения: добавьте любое необходимое смещение во время загрузки. Поэтому нам просто нужно убедиться, что при сборке мы знаем, куда мы намереваемся загрузить - будь топросто 0
, или 04000000
, или что-то еще - и мы выдадим для j
инструкции абсолютный адрес целевой команды, но также некоторые дополнительные инструкции компоновщика / загрузчика, которые говорят: константаВ этой инструкции может потребоваться настройка во время соединения или загрузки. Обратите внимание, что компоновщик и загрузчик должны быть достаточно умными, чтобы понимать ограничения адресации: не ОК, чтобы переместить программу так, чтобы она соответствовалаодна область 256 МБ, теперь охватывает две такие области, если сегмент кода использует инструкции j
для перехода в одну область.
(веб-сайт https://en.wikibooks.org/wiki/MIPS_Assembly/MIPS_Details утверждает, что инструкции j
являются относительными, но это, похоже, неправильно;см. комментарии.)
(Обратите внимание, что отрицательные числа представляются в виде дополнения до двух. Поскольку инструкция j
принимает 26-битный относительный адрес, который она автоматически умножает на 4, она может представлять 28-битнуюдиапазон адресов от -2 27 до 2 27 -1 или -08000000..07fffffc
с шагом 4.)