Как рассчитать целевой адрес перехода и целевой адрес филиала? - PullRequest
29 голосов
/ 05 августа 2011

Я новичок в Язык ассемблера .Я читал об архитектуре MIPS и застрял с целевым адресом перехода и целевым адресом филиала и как рассчитать каждый из них .

Ответы [ 4 ]

65 голосов
/ 21 марта 2012

1. Расчет адреса филиала

В инструкции ветки MIPS есть только 16-битное смещение для определения следующей команды. Нам нужен регистр, добавленный к этому 16-битному значению, чтобы определить следующую инструкцию, и этот регистр фактически подразумевается архитектурой. Это регистр ПК, так как ПК обновляется (ПК + 4) во время цикла выборки, так что он содержит адрес следующей инструкции.

(На рисунках ниже PC - это адрес слота задержки ветвления, а не сама инструкция ветвления. Но в тексте мы скажем PC + 4.)

Мы также ограничиваем расстояние ветвления инструкцией -2^15 to +2^15 - 1 из (инструкция после) инструкции ветвления. Однако это не является реальной проблемой, поскольку большинство филиалов в любом случае являются локальными.

Итак, шаг за шагом:

  • Знак расширяет 16-битное значение смещения, чтобы сохранить его значение.
  • Умножьте полученное значение на 4. Причина этого заключается в том, что если мы собираемся разветвлять какой-то адрес, а ПК уже выровнен по словам, то непосредственное значение также должно быть выровнено по словам. Тем не менее, нет смысла делать непосредственное выравнивание по словам, потому что мы бы потеряли два младших бита, сделав их равными 00.
  • Теперь у нас есть 32-битный адрес. Добавьте это значение к ПК + 4, и это ваш адрес филиала.

Branch address calculation


2. Расчет адреса перехода

Для инструкции перехода Mips имеет только 26 бит для определения местоположения перехода. Кроме того, прыжки относительно ПК в MIPS. Как и ветвь, значение немедленного перехода должно быть выровнено по слову, поэтому нам нужно умножить 26-битный адрес на четыре.

Снова шаг за шагом:

  • Умножить 26-битное значение на 4.
  • Поскольку мы прыгаем относительно значения ПК + 4, объединяем первые четыре бита значения ПК + 4 слева от нашего адреса перехода.
  • Результирующий адрес является значением скачка.

Другими словами, замените младшие 28 бит ПК + 4 на младшие 26 бит выбранной инструкции, сдвинутые влево на 2 бита.

enter image description here

Переходы относятся к региону относительно интервала задержки ветвления, не обязательно к самой ветви. На приведенной выше диаграмме ПК уже перешел в слот задержки ветвления перед вычислением скачка. (В 5-ступенчатом конвейере классического RISC BD выбирался в том же цикле, в котором декодируется переход, так что следующий адрес инструкции PC + 4 уже доступен для переходов, а также переходов, и вычисление относительно собственного адреса перехода будет потребовалась дополнительная работа для сохранения этого адреса.)

Источник: Bilkent University CS 224 Слайды курса

19 голосов
/ 05 августа 2011

Обычно вам не нужно беспокоиться об их вычислении, так как ваш ассемблер (или компоновщик) предпримет правильные вычисления.Допустим, у вас есть небольшая функция:


func:
  slti $t0, $a0, 2
  beq $t0, $zero, cont
  ori $v0, $zero, 1
  jr $ra
cont:
  ...
  jal func
  ... 

При преобразовании вышеуказанного кода в двоичный поток инструкций ассемблер (или компоновщик, если вы впервые собрали его в объектный файл) будет определять, где в памятифункция будет постоянно (давайте пока проигнорируем независимый от позиции код).Где он находится в памяти, обычно указывается в ABI или дается вам, если вы используете симулятор (например, SPIM , который загружает код в 0x400000 - обратите внимание на ссылкутакже содержит хорошее объяснение процесса).

Если мы говорим о случае SPIM, и наша функция находится в памяти первой, инструкция slti будет находиться в 0x400000, beq в 0x400004 и так далее.Теперь мы почти у цели!Для инструкции beq целевой адрес ветви является адресом cont (0x400010), если смотреть на ссылку на инструкцию MIPS , мы видим, что она закодирована как 16-битнаяподписывается непосредственно относительно следующей инструкции (делится на 4, так как все инструкции должны в любом случае находиться на 4-байтовом выровненном адресе).

То есть:

Current address of instruction + 4 = 0x400004 + 4 = 0x400008
Branch target = 0x400010
Difference = 0x400010 - 0x400008 = 0x8
To encode = Difference / 4 = 0x8 / 4 = 0x2 = 0b10

Кодировка beq $t0, $zero, cont

0001 00ss ssst tttt iiii iiii iiii iiii
---------------------------------------
0001 0001 0000 0000 0000 0000 0000 0010

Как вы можете видеть, вы можете переходить с точностью до -0x1fffc .. 0x20000 байтов.Если по какой-либо причине вам необходимо прыгнуть дальше, вы можете использовать батут (безусловный переход к реальной цели, помещенной в заданный предел).

Адреса цели перехода , в отличие от ветвицелевые адреса, закодированные с использованием абсолютного адреса (снова разделенного на 4).Так как кодирование команды использует 6 битов для кода операции, для адреса остается только 26 битов (фактически 28, учитывая, что 2 последних бита будут 0), поэтому при формировании адреса используются 4 старших бита старшего разряда регистра ПК (не имеет значения, если вы не собираетесь перепрыгивать границы 256 МБ).

Возвращаясь к приведенному выше примеру, кодировка jal func:

Destination address = absolute address of func = 0x400000
Divided by 4 = 0x400000 / 4 = 0x100000
Lower 26 bits = 0x100000 & 0x03ffffff = 0x100000 = 0b100000000000000000000

0000 11ii iiii iiii iiii iiii iiii iiii
---------------------------------------
0000 1100 0001 0000 0000 0000 0000 0000

Вы можете быстро проверить это, ипоиграйтесь с разными инструкциями, используя этот онлайн-ассемблер MIPS , с которым я столкнулся (обратите внимание, что он не поддерживает все коды операций, например slti, поэтому я просто изменил его на slt здесь):

00400000: <func>    ; <input:0> func:
00400000: 0000002a  ; <input:1> slt $t0, $a0, 2
00400004: 11000002  ; <input:2> beq $t0, $zero, cont
00400008: 34020001  ; <input:3> ori $v0, $zero, 1
0040000c: 03e00008  ; <input:4> jr $ra
00400010: <cont>    ; <input:5> cont:
00400010: 0c100000  ; <input:7> jal func
0 голосов
/ 25 февраля 2014

Для небольших функций, подобных этой, вы можете просто вручную посчитать, сколько прыжков к цели, из инструкции под инструкцией ветвления. Если оно ответвляется назад, сделайте это число скачков отрицательным. если это число не требует всех 16 битов, то для каждого числа слева от самого значимого из вашего числа прыжков сделайте их 1, если число прыжков положительное, сделайте все 0, так как большинство ветвей близко к цели, это экономит много лишней арифметики для большинства случаев.

  • Крис
0 голосов
/ 05 августа 2011

Я думаю, что было бы довольно сложно рассчитать их, потому что целевой адрес филиала определяется во время выполнения, и этот прогноз делается аппаратно. Если вы объяснили проблему более подробно и описали, что вы пытаетесь сделать, вам было бы немного легче помочь. (

...