Разработка цифровых ИС на примере микроконтроллерного ядра SCR1 - прgграммное обеспечение
Условные переходы
Примеры
li t0, 4 -> t0 = 4 li t1, 10 -> t1 = 10 beq t0, t1, label -> t0t1 - перехода нет … label: *some code*
- Инструкции beq rs1, rs2, label и bne rs1, rs2, label совершают переход, если значения в регистрах rs1 и rs2 равны или неравны соответственно.
- Инструкции blt[u] rs1, rs2, label и bge[u] rs1, rs2, label совершают переход, если значение rs1 меньше или больше rs2 соответственно. Инструкции, оканчивающиеся на "u" выполняют беззнаковое сравнение.
Примечание:
Псевдоинструкция li rd, imm выполняет загрузку значения imm в регистр rd.
Операции с памятью
Примеры
la s0, my_data -> s0 = addr(my_data) lw a0, 0(s0) -> Чтение данных в a0 li a1, 0xbeefdead -> a1 = 0xbeefdead sw a1, 0(s0) -> Запись слова из a1 … my_data: .word 0xbeefdead
- Инструкции чтения и записи используются для передачи значений между регистрами и памятью. Адрес образуется путём суммы значения rs1 и знаковому 12-битному смещению (imm).
- lw rd, imm(rs1) копирует значение из памяти по адресу rs1 + imm в регистр rd.
- sw rs2, imm(rs1) копирует значение регистра rs2 в память по адресу rs1 + imm.
- lw, lh, lb загружает 32-, 16- и 8-битное значение из памяти в регистр.
- sw, sh, sb записывает 32-, 16- и 8-битное значение из регистра в память.
Операторы ветвления
if
Реализация операторов ветвления в ассемблере осуществляется с использованием инструкций условных переходов. Ассемблерный код оператора if проверяет условие, противоположное условию в коде на языке высокого уровня.
Если высокоуровневый код проверяет равенство (i == j), то ассемблерный проверяет условие (i != j). Инструкция bne используется для пропуска блока в случае невыполнения условия.
if/else
В случае, если (i != j) истинно, то bne пропустит блок if и выполнит else. Если (i != j) ложно, то выполнится if и с помощью безусловного перехода j 1f будет пропущен блок else.
Оператор множественного выбора: switch
Цикл с предусловием (while)
Цикл с постусловием (do-while) реализуется аналогично. При этом проверка условия завершения осуществляется в конце итерации цикла, а не в начале, как у while.
Цикл со счетчиком (for)
Таким образом, циклы while, do-while и for на ассемблерном уровне практически не отличаются друг от друга.
Лайфхак: вместо инкремента можно использовать декремент и сравнивать значение с нулём, что позволяет использовать на один регистр меньше.