Целью работы является разработка простой программы (программ) преобразования данных для приобретения практических навыков программирования на языке ассемблера и закрепления знаний по режимам адресации.
Для достижения поставленной цели требуется решить следующие задачи:
Презентация к блоку "Ассемблер RISC-V"
В данном практикуме адресация понимается как способ доступа к данным в рамках той или иной управляющей инструкции. Поскольку ассемблерные программы имеют мало выразительных синтаксических средств, то способы работы с данными могут существенно отличаться от программ на языке высокого уровня. В архитектуре RISC-V используются четыре режима адресации: регистровый, непосредственный, базовый и относительно счетчика команд. Первые три режима (регистровый, непосредственный и базовый) определяют способы чтения и записи операндов. Последний режим (относительно счетчика команд) определяет способ записи счетчика команд.
Далее каждый из способов адресации (доступа к данным) будет пояснен на примере операции add как одной из самых простых и интуитивно понятных. Эти объяснения обобщаются на все соответствующие типы инструкций.
При регистровой адресации (Рис. 5.1) регистры используются для всех операндов-источников и операндов-назначений (иными словами - для всех операндов и результата). Все инструкции типа R используют именно такой режим адресации.
(рис 5.1) Регистровая адресация
Пример регистровой адресации:
add rd,rs1,rs2 # rd = rs1 + rs2
При непосредственной адресации (Рис. 5.2) в качестве операндов наряду с регистрами используют константы (непосредственные операнды). Этот режим адресации используют некоторые инструкции типа I, такие как сложение с 12-битной константой (addi) и логическая операция andi.
(рис 5.2) непосредственная адресация
Пример непосредственной адресации:
addi rd,rs1,12 # rd = rs1 + 12 andi rd,rs1,-8 # rd = rs1 0xFF8
Чтобы использовать константы большего размера, используйте инструкцию непосредственной записи в старшие разряды lui (load upper immediate), за которой следует инструкция непосредственного сложения addi. Инструкция lui загружает 20-битное значение сразу в 20 старших битах и помещает нули в младшие биты:
lui s2, 0xABCDE # s2 = 0xABCDE000 addi s2, s2, 0x123 # s2 = 0xABCDE123
При использовании многоразрядных непосредственных операндов, если указанный в addi 12-битный непосредственный операнд отрицательный, старшая часть постоянного значения в lui должна быть увеличена на единицу. Помните, что знак addi расширяет 12-битное непосредственное значение, поэтому отрицательное непосредственное значение будет содержать все единицы в своих старших 20 битах. Поскольку в дополнительном коде все единицы означают число -1, добавление числа, у которого все разряды установлены в 1, к старшим разрядам непосредственного операнда приводит к вычитанию 1 из этого числа. Пример иллюстрирует ситуацию, когда мы хотим в s2 получить постоянное значение 0xFEEDA987:
lui s2, 0xFEEDB # s2 = 0xFEEDB000 (число, которое нужно записать в старшие 20 разрядов (0xFEEDA), предварительно увеличено на 1)
addi s2, s2, ?1657 # s2 = 0xFEEDA987 (0x987 - это 12-битное представление числа -1657)(0xFEEDB000 + 0xFFFFF987 = 0xFEEDA987)
Инструкции для доступа в память, такие как загрузка слова(чтение памяти) (lw) и сохранение слова(запись в память) (sw), используют базовую адресацию (Рис. 5.3). Эффективный адрес операнда в памяти вычисляется путем сложения базового адреса в регистре rs1 и 12-битного смещения с расширенным знаком, являющегося непосредственным операндом. Операции загрузки (lw) - это инструкции типа I, а операции сохранения (sw) - инструкции типа S.
(рис 5.3) Базовая адресация
Пример базовой адресации:
lw rd,36(rs1) # rd = M[rs1+imm][0:31]
Поле rs1 указывает на регистр, содержащий базовый адрес, а поле rd указывает на регистр-назначение. Поле imm, хранящее непосредственный операнд, содержит 12-битное смещение, равное 36. В результате регистр rd содержит значение из ячейки памяти rs1+36
sw rs2,8(rs1) # M[rs1+imm][0:31] = rs2[0:31]
Инструкция сохранения слова sw демонстрирует запись значения из регистра rs2 в слово памяти, расположенное по адресу rs1+8
Инструкции условного перехода, или ветвления, используют адресацию относительно счетчика команд для определения нового значения счетчика команд (Рис. 5.4) в том случае, если нужно осуществить переход. Смещение со знаком прибавляется к счетчику команд (PC) для определения нового значения PC, поэтому тот адрес, куда будет осуществлен переход, называют адресом относительно счетчика команд.
(рис 5.4) Адресация относительно счетчика команд
Инструкции перехода по условию (beq, bne, blt, bge, bltu, bgeu) типа B и jal (переход и связывание) типа J используют для смещения 13- и 21-битные константы со знаком соответственно. Самые старшие значимые биты смещения располагаются в 12- и 20-битных полях инструкций типа B и J. Наименьший значащий бит смещения всегда равен 0, поэтому он отсутствует в инструкции.
beq rs1,rs2,imm # if(rs1 == rs2) PC += imm jal rd,imm #rd = PC+4; PC += imm
Инструкция jal может быть использована как для вызова функций, так и для простого безусловного перехода. Соглашение, используемое в RISC-V таково, что адрес возврата должен быть сохранён в адресе возврата ra ( x1).
Инструкция jal не имеет достаточного места для кодирования полного 32-битного адреса. Это означает, что вы не можете сделать переход куда-либо в коде, если ваша программа больше максимального значения смещения. Но если адрес перехода хранится в регистре, вы можете сделать переход на любой адрес (инструкция jalr типа I).
jalr rd,imm(rs1) # rd = PC + 4, PC = rs1 + imm
Большая разница состоит в том, что переход jalr не происходит относительно PC. Вместо этого он происходит относительно rs1. Для этого можно использовать addi для установки значения регистра rs1, но на практике поступают иначе. Для того, чтобы адрес был относителен к программному счётчику (РС) применяется специальная инструкция auipc. Инструкция auipc (Add Upper Immediate to Program Counter) типа U (сложить старшие разряды константы смещения с PC) также использует адресацию относительно счетчика команд.
auipc rd,imm # rd = PC + imm[31:12] << 12
Инструкция auipc является очень важной при работе с подпрограммами. Об этом подробнее будет рассказано в лабораторной работе №7.
Напишите четыре программы на ассемблере, использующие различные режимы адресации.
n1=511 и n2=-10, заданные с помощью директивы .equ. Константы разместить в регистрах t0 и t1, а результат сложения в регистре t2.n1=511 в регистр t0 и выполнить логическую операцию И с константой -8. Результат операции сохранить в регистре t1.sum = a[0] + a[1] + a[2] + ... + a[n-1], результат записать в память.
Регистровый файл
| X1 | Addr of a[i] |
| X2 | n |
| X3 | sum |
| X10 | 100 |
Память
| 0 | a[0] |
| 4 | a[1] |
| …. | …. |
| a[n-1] | |
| 100 | 0 |
| 104 | n |
| 108 | sum |
c = max(a, b)
Регистровый файл до выполнения программы
| a0 | a |
| a1 | b |
Регистровый файл после выполнения программы
| a0 | c |
Каждую программу скомпилируйте программу и отладьте. Представьте результат в машинном коде.
В качестве варианта повышенной сложности, можно организовать работу всех четырех типов заданий в рамках одной программы.
Скомпилируйте исходную программу и убедитесь в ее работоспособности в RISC-V ОС, либо через qemu-riscv64.
С помощью утилиты objdump дизассемблируйте бинарный файл программы
.text start: .global _start n1 EQU 511 n2 EQU -10 # Регистровая адресация addi t0, zero, n1 addi t1, zero, n2 add t2, t0, t1 # Непосредственная адресация addi t0, zero, n1 andi t1, t0,-8 # Базовая адресация # s10=100 lw s2, 0x0(s10) lw s3, 0x4(s10) add s4, zero, zero loop: lw s5, 0x0(s2) add s4, s4, s5 addi s2, s2, 4 addi s3, s3, -1 bnez s3, loop sw s4, 0x8(s10) #Адресация относительно счетчика команд max: blt a0, a1, second # if a0 < a1 then a1 is larger jal zero, done second: add a0, zero, a1 # make a1 the return value done:
jal и jalr?Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.