Попытка понять эту функцию MIPS, которая разветвляется, если ее вход отрицателен - PullRequest
0 голосов
/ 22 марта 2019

Я читаю следующую выдержку о коде на ассемблере:

"Метки могут использоваться в сборке вместо [sic] вычисления точных значений для инструкций перехода и перехода. Ниже приведен пример."

int isNeg(int a0) {
  if (a0 < 0) {
    return 1;
  } else {
    return 0;
  }
}

isNeg:
  slt  $t0 $a0 $0
  beq $t0 $0 isPos
  jr $ra
isPos:
  add $v0 $0 $0
  jr $ra

Вот как я интерпретирую это (пожалуйста, исправьте меня при любых неверных предположениях, которые я сделал):

isNeg:
  slt $t0 $a0 $0 // store ($a0 < 0) in $t0
  beq $t0 $0 isPos // if ($t0 == 0) branch by 0 bytes
  jr  $ra
isPos:
  add $v0 $0 $0 // store 0+0=0 in $v0
  jr  $ra

Так что, если мои предположения здесь верны, то если $a является отрицательным, мы ничего не делаем, и если $ a является положительным, то мы разветвляемся на 0, что эквивалентно бездействию.Кто-нибудь может пролить свет на это?

1 Ответ

1 голос
/ 22 марта 2019

Кто-нибудь может пролить свет на это?

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

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

если $ a отрицательно, мы ничего не делаем

Исправить (предполагая, что jr $ra это , а не a ветвь с задержкой , как в реальных процессорах MIPS)

Я предполагаю, что автор книги забыл инструкцию addi $v0 $0 -1.

beq $t0 $0 isPos

если $ a положительно, то мы разветвляемся на 0

Это было бы правильно, если бы beq было a отложенным ответвлением .

В этом случае ЦП сначала выполнит команду сразу после инструкции beq или jr перед фактическим переходом / прыжком.

Однако в этом случае инструкция jr, следующая непосредственно за командой beq, не будет разрешена на большинстве реальных процессоров MIPS. Поэтому я не думаю, что это так.

Если используется эмулятор, не эмулирующий интервалы задержки, инструкция beq переместится на 4 байта (по сравнению с инструкцией jr).

Если настоящий процессор MIPS и ассемблер вставляют инструкции nop (например, add $0 $0 $0) после каждой инструкции перехода / перехода (опция .set reorder в GNU), инструкция beq будет переходить на 8 байт ( над инструкцией jr и инструкцией nop, которая следует за ней). После этого перехода выполняется инструкция add $v0 $0 $0.

...