Подтвердить что ты не робот

Как рассчитать адрес целевого адреса и адрес ветки?

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

4b9b3361

Ответ 1

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 Слайды курса

Ответ 2

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


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 at 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

Ответ 3

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

  • Крис

Ответ 4

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