Лабораторная работа №4. Логические и арифметические операции, операции сравнения и сдвига
4.1 Цель и задачи
Целью работы является разработка изучение логических и арифметических операций, операций сравнения и сдвига в рамках языка ассемблер RISC-V. Для этого необходимо выполнить следующие задачи:
- Изучить логические и арифметические операции I-type.
- Изучить логические и арифметические операции R-type.
Презентация к блоку "Ассемблер RISC-V"
4.2. Основные теоретические сведения
4.2.1 Логические и арифметические операции I-type
Instruction | name | opcode | funct3 | description |
---|---|---|---|---|
addi | ADD immediate | 0010011 | 0x0 | rd=rs1 + imm |
xori | XOR immediate | 0010011 | 0x4 | rd=rs1 ^ imm |
ori | OR immediate | 0010011 | 0x6 | rd=rs1 | imm |
andi | AND immediate | 0010011 | 0x7 | rd=rs1 & imm |
slli | Shift Left Logical Imm | 0010011 | 0x1 | Imm(11:5)=0x00, rd=rs1<< imm(4:0) |
srli | Shift Right Logical Imm | 0010011 | 0x5 | Imm(11:5)=0x00, rd=rs1>> imm(4:0) |
srai | Shift Right Arith Imm | 0010011 | 0x5 | Imm(11:5)=0x20, rd=rs1>> imm(4:0) |
stli | Set Less Than Imm | 0010011 | 0x2 | rd=(rs1 < imm)?0:1 |
sltiu | Set Less Than Imm. Unsigned | 0010011 | 0x3 | rd=(rs1 < imm)?0:1 |
Команды I-type (Таблица 4.1) принимают непосредственное значение imm (константу), исходный регистр rs1 и целевой регистр rd.
Поскольку инструкция addi rd, rs1, imm использует значение imm в качестве значения со знаком, она работает для арифметического сложения (imm = 0...2047) и вычитания (imm = -2048…-1), т.е. нет команды subi.
Инструкции xori, ori и andi rd, rs1, imm выполняют побитовую операцию xor, or, and соответственно. Например, пусть значение регистра x1 равно 0?9; в двоичной системе счисления (обозначается префиксом 0b) это 0b1001. Команда xori x1, x1, 0?3 выполняет операцию xor над содержимым регистра x1, таким образом
x1 = x1 xor 0?3 = 0b1001 xor 0b0011 = 0b1010 = 0xa.
Инструкции slli, srli и srai выполняют операции сдвига, используя непосредственное значение в качестве количества сдвигов. Непосредственным значением является положительное число из 5 бит (0...31).
Логический сдвиг влево выполняется с помощью команды slli rd, rs1, imm. Она перемещает влево каждый бит значения исходного регистра rs1 на число бит, заданное непосредственным значением, и записывает результат в rd. При каждом сдвиге младший значащий бит устанавливается равным нулю, а старший значащий бит отбрасывается.
Логический сдвиг вправо выполняется аналогично с помощью srli rd, rs1, imm. Регистр rs1 побитово сдвигается вправо на immediate, и результат поступает в rd. Здесь самый старший бит заполняется нулем, а младший бит отбрасывается.
Обработка или заполнение старшего значащего бита отличается для арифметического сдвига вправо, выполняемого с помощью srai rd, rs1, imm. Самый старший бит (msb) сохраняется. Если msb равен 0 перед сдвигом, то msb заполняется значением 0 после сдвига. Если msb равен 1 перед сдвигом, то msb заполняется значением 1. Например, пусть значение регистра x1 равно 0?9, в двоичной системе счисления это 0b1001. Командаslli x1, x1, 0?2 выполняет логический сдвиг содержимого регистра x1 влево таким образом
x1 = x1 << 0?2 = 0b1001 << 2 = 0b100100 = 0?24.
Оставшиеся две инструкции slti rd, rs1, imm и sltiu rd, rs1,imm сравнивают содержимое исходного регистра rs1 с непосредственным значением (imm) и устанавливают в rd значение 0, если значение исходного регистра rs1 < imm. Разница между обеими инструкциями заключается в том, что slti использует значения со знаком, и в сравнении используются значения со знаком. Примеры
addi x3, x1, 3 # x3 = x1 + 3 andi x3, x1, 3 # x3 = x1 & 3 slli x3, x1, 3 # x3 = x1 << 3 addi x3, x1, -3 # x3 = x1 - 3
4.2.2 Логические и арифметические операции R-type
Операции R-type (Таблица 4.2) включают арифметические и логические операции, которые используют два регистра в качестве источника и один регистр в качестве приемника. Большинство инструкций являются аналогом операций с непосредственными значениями.
Instruction | name | opcode | funct3 | description |
---|---|---|---|---|
add | ADD | 0110011 | 0x0 | rd=rs1 + rs2 |
sub | SUB | 0110011 | 0x0 | rd=rs1 - rs2 |
xor | XOR | 0110011 | 0x4 | rd=rs1 ^ rs2 |
or | OR | 0110011 | 0x6 | rd=rs1 | rs2 |
and | AND | 0110011 | 0x7 | rd=rs1 & rs2 |
sll | Shift Left Logical | 0110011 | 0x1 | rd=rs1<< rs2 |
srl | Shift Right Logical | 0110011 | 0x5 | rd=rs1>> rs2 |
sra | Shift Right Arith | 0110011 | 0x5 | rd=rs1>> rs2 |
stl | Set Less Than | 0110011 | 0x2 | rd=(rs1 < rs2)?0:1 |
sltu | Set Less Than Un | 0110011 | 0x3 | rd=(rs1 < rs2)?0:1 |
Примеры
add x3, x1, x2 # x3 = x1 + x2 slt x3, x1, x2 # if x1 < x2 then x3 = 1 else x3 = 0 and x3, x1, x2 # x3 = x1 & x2 sll x3, x1, x2 # x3 = x1 << x2
Пример сложения I-type и R -type описан в Таблице 4.3.
Адрес | Машинный код | Инструкция | Комментарий |
---|---|---|---|
0x0 | 0x00100093 | addi x1, x0, 1 | # x1=1 |
0x4 | 0x00108093 | addi x1, x1, 1 | # x1=2 |
0x8 | 0x00108133 | add x2, x1, x1 | # x2=4 |
Рассмотрим пример сложных вычислений a = ((b+3) >> c) - 1. Предположим, что a, b, c находятся в регистрах s2, s3 и s4 соответственно. Используйте регистр s5 для y0 и регистр s6 для y1.
addi s5, s3, 3 # y0 = b + 3 srl s6, s5, s4 # y1 = y0 >> c addi s2, s6, -1 # a = y1 - 1
4.3. Задание к лабораторной работе
- Создать программу согласно варианту, которая
- выполняет заданные действия,
- выводит на экран сообщения о результатах/ошибках.
- Откомпилировать программу и запустить на исполнение.
- Отладить программу, проследить изменения в регистрах.
Варианты заданий
Напишите программы, которые вводят два целых значения x и y, вычисляют следующие выражения и выводят результат:
- (x + 5) - (y - 7)
- (x >> 2) + ((y - 1) << 3) (>> - логический сдвиг)
- (x << y) - 10
- (x >> y) + 10 (>> - арифметический сдвиг)
- ((x << 2) - y + 5) >> 1 (>> - арифметический сдвиг)
- x * 6 - y * 3 (выполнить умножение, используя сдвиг, сложение, вычитание)
- 2 * x * x - 3 * y + 4
- (x + 5) / y + 10 / (y - 1)
- (x / y) * y + x % y
- x & (-1 << 5)
- x | (-1 >> 27) (>> - логический сдвиг)
- Установите y-ий бит x в 1 (номера битов начинаются с 0)
- Установите y-ий бит x в 0 (номера битов начинаются с 0)
- x > y ? 0 : 1
- (x == (y + 3)) ? 0 : 1
- x < -5 & y > 10
4.3.1 Описание последовательности выполнения работы
Скомпилируйте исходную программу и убедитесь в ее работоспособности в RISC-V ОС, либо через qemu-riscv64.
4.3.2 Пример выполнения задания на защиту
Напишите программу, которая:
- очищает регистры t0, t1,t2 (использовать andi);
- загружает 0x1A352A9C и 0x1B2D4C6A соответственно в регистры t0, t1;
- добавляет в регистр t0 константу 0x1CB;
- складывает регистры t0, t1, результат помещает в t2.
Результат
andi t0, t0, 0 # Clear register t0 andi t1, t1, 0 # Clear register t1 andi t2, t2, 0 # Clear register t2 li t0, 0x1A352A9C # Loading register t0 with a value li t1, 0x1B2D4C6A # Loading register t1 with a value addi t0, t0, 0x1CB # Add t0 with an immediate value add t2, t0, t1 # Add -- t0 with t1 and place the result in t2
4.4. Вопросы для контроля
- Как выполнить эти операции без использования инструкции умножения?
x * 2
x * 3
x * 4
x * 5
x * 8
x * 31
- Как выполнить эти операции без использования инструкции деления?
x / 2
x / 3
x / 5
x / 8
x / 31