Целью работы является разработка программы преобразования данных для приобретения практических навыков программирования на языке ассемблера и закрепления знаний по работе с массивами и циклами. Задачи:
Презентация к блоку "Ассемблер RISC-V"
Архитектура RISC-V обычно использует прямой порядок байтов (от младшего к старшему; little-endian). RISC-V применяет память с побайтовой адресацией. Это значит, что каждый байт памяти имеет уникальный адрес. Поскольку 32-битное слово состоит из четырех 8-битных байтов, то адрес каждого слова (word address) кратен 4. Старший байт (most significant byte, MSB) находится слева, а самый младший байт (least significant byte, LSB) - справа.
Для обращения к элементу одномерного массива в команде используется формула для вычисления его адреса в памяти.
Адрес эл-та = (адрес нач. массива) + (№эл-та) ? (размер эл-та в байтах)
(рис 6.1) Расчет адресов элементов массива
Имя массива однозначно определяет адрес младшего байта его нулевого элемента. Начальный адрес массива и его размер (число элементов) заносятся в регистры (можно использовать любой свободный), и на каждой итерации указатель изменяется на длину элемента в байтах.
Обращение к элементу массива, к оперативной памяти в RISC-V организовано единственно возможным способом - с помощью базовой адресации со смещением:
la rs1, mas # Загрузить адрес массива lw rd, 0(rs1)#Адрес элемента = Смещение (0) + База (rs1)
Пояснение к примеру:
Другая форма:
li rs1,0 lw rd, mas (rs1) # Адрес элемента = База (mas) +Смещение (rs1)
В языках высокого уровня циклы предназначены для многократного выполнения участка кода в зависимости от условия. В Ассемблере RISC-V нет специальных инструкций для организации цикла. Для перебора элементов массива в цикле требуется продумать самостоятельно вид цикла, регистр-счетчик количества повторений цикла, условие окончания, регистр для хранения флага окончания и временного индикатора для сравнения с индикатором. Проверка условий выполняется операторами "если-то-иначе", организованными командами условного перехода (beq, bne, blt, bge,bgeu, bltu) или безусловного перехода (jal, jalr и псевдокоманды j, jr ).
Команды условного перехода имеют формат типа B.
(рис 6.2) Структура команд типа B
В таблице 6.1 представлены все команды условного перехода
| Instruction | name | opcode | funct3 | description |
|---|---|---|---|---|
beq |
Branch == |
1100011 | 0x0 |
if (rs1 == rs2) pc+= imm |
bne |
Branch != |
1100011 | 0x1 |
if (rs1 != rs2) pc+= imm |
blt |
Branch < |
1100011 | 0x4 |
if (rs1 < rs2) pc+= imm |
bge |
Branch >= |
1100011 | 0x5 |
if (rs1 >= rs2) pc+= imm |
bltu |
Branch < Un |
1100011 | 0x6 |
if (rs1 < rs2) pc+= imm |
bgeu |
Branch >= Un |
1100011 | 0x7 |
if (rs1 >= rs2) pc+= imm |
Команда условного перехода сравнивает значения регистров rs1 и rs2. Если результат сравнения (условие) является истинным, программный счетчик увеличивается на imm. Например, команда blt rs1, rs2, imm проверяет, меньше ли содержимое rs1, чем содержимое rs2. Если это так, то pc = pc + imm. В противном случае работа продолжается со следующей инструкцией в памяти (pc = pc +4).
Инструкции blt и bge используют значения со знаком; а bgeu этого не делает. Использование условного перехода bge и beq
bge s2, s3, else # if (a < b): c = a + 1 addi s4, s2, 1 beq zero, zero, end else: # else: c = b + 2 addi s4, s3, 2 end: # s2=a; s3=b; s4=c;
Использование условного перехода blt
| Адрес | Машинный код | Инструкция | Комментарий |
|---|---|---|---|
0x00 |
0xffb00093 |
addi s2, zero, -5 |
s2 = -5 |
0x04 |
0x00500113 |
addi s3, zero, 5 |
s3 = 5 |
0x08 |
0x0020c463 |
blt s2, s3, 0x8 |
if (s2 < s3) pc = pc+ 8 |
0x0c |
0x00100193 |
addi s4, zero, 1 |
skipped if (s2 <s3): s4 = 1 |
0x10 |
0x00200193 |
addi s4, zero, 2 |
s4 = 2 |
Инструкция по адресу 0x08 проверяет, является ли s2 < s3, то есть -5 < 5. Поскольку это верно, программный счетчик устанавливается на адрес 0x10, а инструкция по адресу 0x0c пропускается.
Если бы команда перехода по адресу 0x08 была bltu, отрицательное значение регистра s2 рассматривалось бы как положительное значение (0xfffffffb как положительное шестнадцатеричное значение для 32-разрядной версии), и результат сравнения был бы ложным.
Ниже приведен более сложный пример программы подсчета количества нулевых элементов в одномерном массиве.
.data
mas: .word -1 -2 -3 -4 1 2 0 4 2000 4096 65535 0
size: .word 12 # длина массива
head: .asciiz "\n Null element amount: "
.text
la t0, mas # загрузить адрес массива - начальный индекс [i]
lw t5, size # загрузить длину массива в регистр
loop:
lw t3, 0(t0) # поместить значение mas[i] в регистр $t3
bne 0, t3, met1 # перейти к met1 если $t3 не '0' и элемент массива не 'zero'
addi t4, t4, 1 # увеличить счетчик нулевых элементов
met1: addi t5, t5, -1 # уменьшить счетчик цикла
addi t0, t0, 4 # увеличить индекс текущего элемента
bge t5, loop # повторить, пока не закончили
la a0, head # загрузить адрес константы заголовка для печати
li v0, 4
ecall # напечатать заголовок
add a0, t4, zero # загрузить значение счетчика нулевых элементов для печати
li v0, 1
ecall # напечатать значение счетчика
Согласно вышеприведенной программе в памяти последовательно расположены 12 четырёхбайтовых элемента массива mas (среди которых есть два нулевых), затем переменная size, содержащая размер массива (12), затем ASCII-коды символов выводимого сообщения head. Далее следуют три инструкции загрузки:
Затем начинается цикл просмотра элементов (метка loop), в котором
mas[i],Далее выполняются два системных вызова
В ряде случаев полезными выступают команды безусловного перехода, являющиеся аналогами инструкции GOTO. Команды безусловного перехода имеют формат типа J или I. Для RISC-V есть две инструкции безусловного перехода (Таблица 6.3).
| Instruction | name | format | opcode | funct3 | description |
|---|---|---|---|---|---|
jal |
Jump and Link |
1101111 | - | rd=PC+4; PC+=imm |
|
jalr |
Jump and Link Register |
I | 1101111 | 0x0 |
rd=PC+4; PC=rs1+imm |
Команда jal rd, imm добавляет непосредственное значение к программному счетчику pc +=imm и записывает в регистр rd адрес после команды jal. Команда jalr rd, rs, imm устанавливает программный счетчик как результат pc = rs + imm, и записывает в rd обратный адрес. Обратный адрес - это инструкция по адресу, указанному после инструкции перехода.
| Адрес | Машинный код | Инструкция | Комментарий |
|---|---|---|---|
0x00 |
0x00c000ef |
jal s2,0xc |
pc = 0x0 + 0xc= 0xc, s2 = pc + 4 = 0x4 |
0x04 |
0x00000013 |
addi zero, zero, 0 |
no operation |
0x08 |
0x00010093 |
addi s2, s3, 0 |
s2= s3 |
0x0c |
0x00008167 |
jalr s3, s2, 0 |
pc = s2, s3= pc + 4 = 0x10 |
0x10 |
0x00100093 |
addi s2, zero, 1 |
s2= 1 |
Последовательность выполнения программы выглядит следующим образом. Программа начинается с команды перехода jal s2, 0xc по адресу 0х00. Эта команда записывает обратный адрес в регистр2 и переходит к 0х0c. В 0х0c команда перехода jalr s3, s2, 0 записывает свой соответствующий обратный адрес (0х10)в регистр s3 и выполняет переход (возвращает) к адресу, сохраненному в регистре s2, который равен 0х04. Программа продолжает выполнение инструкции в 0х04, которая ничего не делает. Следующая команда в 0х08 перемещает значение 0х10 (обратный адрес jalr) в регистр s2. После этого второй проход jalr в 0xc переходит к 0х10, значение регистра s2. Последовательность счетчика команд 0х00, 0х0c, 0х04, 0х08, 0х0c, и 0х10.
Скомпилируйте исходную программу и убедитесь в ее работоспособности в RISC-V ОС, либо через qemu-riscv64.
Напишите программу сложения целых чисел от 0 до 100:
t0 используйте для текущего индекса quot;iquot; для циклаt1 хранит величину для сравнения с текущим индексом (в данном примере 100)t2 хранит текущую сумму (по окончанию программы - результат)Код решения:
andi t0, t0, 0 # Clearing contents of register t0 andi t1, t1, 0 # Clearing contents of register t1 andi t2, t2, 0 # Clearing contents of register t2 # Functions as variable "sum" li t1, 100 # Load t1 with value 100 loop: add t2, t2, t0 # Sum = Sum+i addi t0, t0, 1 # Increment index "i" blt t0, t1, loop # Iterate if t0<t1 End: j End # End of WHILE loop
ВАРИАНТЫ ЗАДАНИЙ
А и запомнить их номера и адреса в переменных в памяти A_min, A_max. Вывести переменные, и предусмотреть случай (вывести сообщение), когда имеются все/несколько минимальных или максимальных элементов.А посчитать и запомнить количество нулевых/отрицательных/положительных элементов. Вывести сообщения с этими значениями и предусмотреть случай (вывести сообщение), когда какие-то типы элементов отсутствуют.А, содержащие 2 единицы в двоичном представлении и запомнить их номера и адреса в новых одномерных массивах B_nom и B_adr, предусмотреть случай, когда таких элементов нет. Вывести сообщение о количестве таких элементов или об их отсутствии.А составить новый массив В, каждый элемент которого В[i] соответствует № первого слева (старшего) нулевого разряда элемента А[i] . Предусмотреть случай отсутствия нулевых разрядов элемента. Вывести сообщение с числом таких элементов или штатном режиме - весь массив В заполнен.А составить новый массив В, каждый элемент которого В[i] соответствует № первого справа (младшего) единичного разряда элемента А[i]. Предусмотреть случай отсутствия единичных разрядов элемента. Вывести сообщение с числом таких элементов или штатном режиме - весь массив В заполнен.А составить новый массив В, каждый элемент которого В[i] равен сумме единиц в двоичном представлении элемента А[i]. Посчитать общее количество единиц. Предусмотреть случай отсутствия единичных разрядов элементов. Вывести сообщение с общим количеством единиц или об их отсутствии.А, число нулевых элементов, число четных и нечетных элементов и запомнить эти 5 значений в указанном порядке в одномерном массиве В. Вывести сообщения о полученных результатах, предусмотреть случай, когда некоторые виды элементов отсутствуют.А, запомнить эти значения в памяти и вывести эти значения или сообщение об отсутствии некоторых видов битов.А рассчитать разницу между максимальным и минимальным элементом и вывести это число. Предусмотреть случай их отсутствия (когда все элементы массива равны) и вывести об этом сообщение.А, больше заданной переменной. Вывести сообщения о полученных результатах, предусмотреть случай, когда такие элементы отсутствуют.А составить новый одномерный массив символьных строк В. Первым символом строки В[i] будет символ "Р" (positive), если элемент А[i] положительный и "N", если отрицательный. Вторым символом строки В[i] будет "-", третьим символом строки В[i] будет "Z", если элемент А[i] нулевой. Вывести сообщения об отсутствии одного из типов элементов и числе положительных элементов.int (32 бита) с именем arr 0. Указатель на первый элемент arr0, хранится в регистре a1. Ответьте на следующие вопросы.
arr 0 в регистр t1?t1 + 16? Сохраните результат в регистре t2t2 /16 и t2 %16. Сохраните результаты в t3 и t4 соответственно. Обратите внимание, что / - это целочисленное деление, а % - операция по модулю. (подсказка: использование сдвига и логических операций)int (32 бита) с именем arr1. Указатель на первый элемент arr1 хранится в регистре a2. У нас также есть регистры
t1 = 0xAAAAAAAA, t2 = 0xFEDCBA98
Ответьте на следующие вопросы:
t3 для следующей последовательности инструкций?
slli t3, t1, 4 srli t3, t3, 4
t3 для следующей последовательности инструкций?
slli t3, t2, 3 srai t3, t3, 3
t1 t2 в регистре t4;t4 в первом элементе arr1;t4 во втором элементе arr1.li t1, 0 li t2, 1 li t3, 1 li t4, 10 LOOP: beq t1, t4, DONE add t5, t2, t3 addi t2, t3, 0 addi t3, t5, 0 addi t1, t1, 1 jal x0, LOOP DONE: # end of the program
LOOP и DONE)?t2 на каждой итерации цикла.t3 на каждой итерации цикла.Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.