Нет, beq
берет 2 регистра и сравнивает их, вот и все. Помните, что язык ассемблера отражает то, что машинный код может выполнять в одной инструкции. Для выполнения чего-то более сложного часто требуется больше инструкций.
Для &&
нескольких условий вместе, вам нужно либо
несколько beq
и / или bne
инструкций;цепочка ветвей
или создайте значение в одном регистре, которое представляет логические и множественные условия перед ветвлением. Например, загрузите все 3 байта и xori
их с 'a'
, 'b'
и 'c'
соответственно. (Производство 0
для матча). Затем or
эти результаты вместе и посмотрите, будет ли окончательный результат 0
(с bne
или beq
против $zero
). Если так, то ни в одном из 3 байтов не было несовпадающих битов, поэтому условиеtrue.
2-й способ оптимизирует устранение короткого замыкания, которое имеет логика C. Обратите внимание, что в выражении C a[1]
даже не доступен, если a[0] != 'a'
, поэтому он не будет ошибаться, даже если a
был указателем на последний байт страницы, а следующая страница не отображалась. (Предполагая, что a[0] == 0
или что-то еще, пустая строка с нулем в конце).
Но если вы do знаете, что можете безопасно получить доступ ко всем 3 байтам строки / массива, это вариант.
Это проще / эффективнее в качестве оптимизации, когда условие что-то наподобие if (x < 5 && y < 10)
, которое вы можете реализовать с помощью инструкций 2x slti
для сравнения в регистры И этих регистров вместе, затем beq $t0, $zero, skip_if_body
В этом особом случае, когда вы проверяете 3 смежных байта, это в основном memcmp(a, "abc", 3)
.
Если вы знаете, что a
выровнено по словам,Вы можете выполнить загрузку слов, чтобы получить 3 байта, которые вы хотите, плюс один байт мусора, который мы должны игнорировать.
MARS моделирует систему MIPS с прямым порядком байтов, поэтому 3 байта, которые мы хотим, - это 3 наименеезначащие байты в слове. (В общем случае MIPS может работать с большим или младшим порядковым номером.)
# assuming a[] is a word-aligned static array
# and little-endian MIPS
lw $t0, a # pseudo-instruction for lui / lw to construct the full address
li $t1, 'abc' << 8 # 0x63626100 if your assemble doesn't like multi-char literals
sll $t0, $t0, 8 # shift out the 4th byte which we need to ignore
bne $t0, $t1, skip_if_body
# if body: a[0] == 'a' && a[1] == 'b' && a[2] == 'c'
...
skip_if_body:
...
jr $ra
Конечно, вы также можете использовать это, если a
на самом деле указатель в регистре, который, как известно, выровнен по словам. lw $t0, ($a0)
.
Я переместил нежелательный байт из нагрузки вместо того, чтобы маскировать его с помощью AND, потому что andi
не может кодировать 0x00FFFFFF
.
Если a
не былокак известно, выровнены, возможно, lwl
/ lwr
для не выровненной нагрузки стоило бы использовать.
или lhu
+ lbu
для загрузки 16 бит и 8 бит отдельно, если у нас есть 2-выравнивание байтов;мы можем проверить 16 битов одновременно с xori
, используя всю ширину немедленного, если мы все еще хотим объединить для одной ветви. Или просто с помощью li
/ beq
.
Для построения 'abc' << 8
в регистре требуется 2 инструкции (lui + addiu
или ori
)