BREAKING CHANGE! Сдвиг нумерации в лабах

Лабу по дейзи-цепочке необходимо вставить сразу после лабы по интеграции
контроллера прерываний, поэтому приходится увеличить нумерацию
оставшихся лаб.
This commit is contained in:
Andrei Solodovnikov
2024-02-04 11:08:37 +03:00
parent d4d813a7ea
commit 45585ff9c4
60 changed files with 37 additions and 37 deletions

View File

@@ -0,0 +1,65 @@
_start:
# Инициализируем начальные значения регистров
0: 030000b7 li x1 , 0x03000000 # сохраняем базовый адрес клавиатуры
4: 04000137 li x2 , 0x04000000 # сохраняем базовый адрес хекс-контроллера
8: 0e000193 li x3 , 0x000000e0 # сохраняем сканкод e0
c: 0f000213 li x4 , 0x000000f0 # сохраняем сканкод f0
10: 00e00413 li x8 , 0x0000000e # сохраняем значение e
14: 00f00493 li x9 , 0x0000000f # сохраняем значение f
18: 00000593 li x11, 0x00000000 # сохраняем ноль
1c: 00100293 li x5 , 0x00000001 # подготавливаем маску прерывания единственного
# (нулевого) входа
20: 30429073 csrw mie, x5 # загружаем маску в регистр маски
24: 03400293 la x5, trap_handler # псевдоинструкция la аналогично li загружает число,
28: 00028293 # только в случае la это число является адресом
# указанного места (адреса обработчика перехвата)
# данная псевдоинструкция будет разбита на две
# инструкции: lui и addi
2c: 30529073 csrw mtvec, x5 # устанавливаем вектор прерывания
# Вызов функции main
main:
30: 00000063 beq x0, x0, main # бесконечный цикл, аналогичный while (1);
# ОБРАБОТЧИК ПЕРЕХВАТА
# Без стороннего вмешательства процессор никогда не перейдет к инструкциям ниже,
# однако в случае прерывания в программный счетчик будет загружен адрес первой
# нижележащей инструкции.
# Сохраняем используемые регистры на стек
trap_handler:
34: 0000a383 lw x7, 0(x1) # загружаем сканкод
38: 04338263 beq x7, x3, print_e0 # если сканкод e0, отображаем с помощью print_e0
3c: 04438c63 beq x7, x4, print_f0 # если сканкод f0, отображаем с помощью print_f0
40: 00700333 add x6, x0, x7 # дублируем сканкод
44: 00435313 srl x6, x6, 4 # сдвигаем на 4, чтобы получить старший нибл
48: 00612223 sw x6, 4(x2) # записываем старший нибл в первый семисегментник
4c: 00f3f393 andi x7, x7, 0xf # маскируем с f, чтобы получить младший нибл
50: 00712023 sw x7, 0(x2) # записываем младший нибл в нулевой семисегментник
54: 00b04c63 blt x0, x11, print_code # пропускаем обнуление старших хексов
58: 00012a23 sw x0, 20(x2)
5c: 00012823 sw x0, 16(x2) # обнуляем 2-5 семисегментники
60: 00012623 sw x0, 12(x2)
64: 00012423 sw x0, 8(x2)
68: 00300513 addi x10, x0, 3
print_code:
6c: 000005b3 add x11, x0, x0 # обнуляем счетчик
70: 00356513 ori x10, x10, 3 # инициализируем маску, включающую 2 младших хекса
74: 02a12023 sw x10, 32(x2) # записываем маску
78: 30200073 mret # возвращаем управление программе (pc = mepc)
# что означает возврат в бесконечный цикл
print_e0:
7c: 00812a23 sw x8, 20(x2) # записываем e в 5ый семисегментник
80: 00012823 sw x0, 16(x2) # записываем 0 в 4ый семисегментник
84: 03056513 ori x10, x10, 0x30 # включаем отображение 4-5 хексов в маске
88: 02a12023 sw x10, 32(x2) # записываем маску
8c: 00158593 addi x11, x11, 1 # инкрементируем счетчик
90: 30200073 mret
print_f0:
94: 00912623 sw x9, 12(x2) # записываем f в 3ый семисегментник
98: 00012423 sw x0, 8(x2) # записываем 0 в 2ый семисегментник
9c: 00c56513 ori x10, x10, 0xc # включаем отображение 3-2 хексов в маске
a0: 02a12023 sw x10, 32(x2) # записываем маску
a4: 00158593 addi x11, x11, 1 # инкрементируем счетчик
a8: 30200073 mret

View File

@@ -0,0 +1,37 @@
_start:
# Инициализируем начальные значения регистров
0: 030000b7 li x1, 0x03000000 # сохраняем базовый адрес клавиатуры
4: 07000137 li x2, 0x07000000 # сохраняем базовый адрес vga-контроллера
8: 070011b7 li x3, 0x07000960 # количество символов на экране
c: # данная псевдоинструкция будет разбита на две
# инструкции: lui и addi
10: 96018193 li x5, 0x00000001 # подготавливаем маску прерывания единственного
# (нулевого) входа
14: 00100293 csrw mie, x5 # загружаем маску в регистр маски
18: 30429073 la x5, trap_handler # псевдоинструкция la аналогично li загружает число,
# только в случае la это число является адресом
# указанного места (адреса обработчика перехвата)
# данная псевдоинструкция будет разбита на две
# инструкции: lui и addi
1c: 30529073 csrw mtvec, x5 # устанавливаем вектор прерывания
# Вызов функции main
main:
20: 00000063 beq x0, x0, main # бесконечный цикл, аналогичный while (1);
# ОБРАБОТЧИК ПЕРЕХВАТА
# Без стороннего вмешательства процессор никогда не перейдет к инструкциям ниже,
# однако в случае прерывания в программный счетчик будет загружен адрес первой
# нижележащей инструкции.
# Сохраняем используемые регистры на стек
trap_handler:
24: 0000a383 lw x7, 0(x1) # загружаем сканкод
28: 00038403 lb x8, 0(x7) # берем данные из таблицы подстановки
2c: 00812023 sw x8, 0(x2) # загружаем ascii-значение в vga
30: 00110113 addi x2, x2, 1 # инкрементируем адрес vga
34: 00315463 bge x2, x3, wrap_addr # если адрес vga вышел за границы, то обнуляем
38: 30200073 mret # возвращаем управление программе (pc = mepc)
# что означает возврат в бесконечный цикл
wrap_addr:
3c: 07000137 li x2, 0x07000000 # сохраняем базовый адрес vga-контроллера
40: 30200073 mret

View File

@@ -0,0 +1,34 @@
_start:
# Инициализируем начальные значения регистров
0: 050000b7 li x1 , 0x05000000 # сохраняем базовый адрес uart_rx
4: 04000137 li x2 , 0x04000000 # сохраняем базовый адрес хекс-контроллера
8: 0001c1b7 li x3 , 0x0001c200 # устанавливаем бодрейт 115200
c: 20018193
10: 0030a623 sw x3 , 0x0c(x1)
14: 00100213 li x4 , 0x00000001 # устанавливаем parity_bit
18: 0030a823 sw x4 , 0x10(x1)
1c: 00100293 li x5 , 0x00000001 # подготавливаем маску прерывания единственного
# (нулевого) входа
20: 30429073 csrw mie, x5 # загружаем маску в регистр маски
24: 03400293 la x5, trap_handler # псевдоинструкция la аналогично li загружает число,
28: 00028293 # только в случае la это число является адресом
# указанного места (адреса обработчика перехвата)
# данная псевдоинструкция будет разбита на две
# инструкции: lui и addi
2c: 30529073 csrw mtvec, x5 # устанавливаем вектор прерывания
# Вызов функции main
main:
30: 00000063 beq x0, x0, main # бесконечный цикл, аналогичный while (1);
# ОБРАБОТЧИК ПЕРЕХВАТА
# Без стороннего вмешательства процессор никогда не перейдет к инструкциям ниже,
# однако в случае прерывания в программный счетчик будет загружен адрес первой
# нижележащей инструкции.
# Сохраняем используемые регистры на стек
trap_handler:
34: 0000a383 lw x7, 0(x1) # загружаем пришедший байт
38: 00700333 add x6, x0, x7 # дублируем сканкод
3c: 00435313 srl x6, x6, 4 # сдвигаем на 4, чтобы получить старший нибл
40: 00612223 sw x6, 4(x2) # записываем старший нибл в первый семисегментник
44: 00f3f393 andi x7, x7, 0xf # маскируем с f, чтобы получить младший нибл
48: 00712023 sw x7, 0(x2) # записываем младший нибл в нулевой семисегментник
4c: 30200073 mret

View File

@@ -0,0 +1,50 @@
_start:
# Инициализируем начальные значения регистров
0: 050000b7 li x1, 0x05000000 # сохраняем базовый адрес uart_rx
4: 02000137 li x2, 0x02000000 # сохраняем базовый адрес светодиодов
8: 0001c1b7 li x3, 0x0001c200 # устанавливаем бодрейт 115200
c: 20018193
10: 0030a623 sw x3, 0x0c(x1)
14: 00100213 li x4, 0x00000001 # устанавливаем parity_bit
18: 0040a823 sw x4, 0x10(x1)
1c: 000011b7 li x3, 0x00000D0D # сохраняем спец-код для режима моргания
20: d0d18193
24: 00008237 li x4, 0x00000808 # сохраняем спец-код для сброса
28: f7f20213
2c: 0ff00493 li x9, 0x000000ff # сохраняем маску для обнуления старшей части
30: 00100313 li x6, 0x00000001 # сохраняем единицу
34: 00100293 li x5, 0x00000001 # подготавливаем маску прерывания единственного
# (нулевого) входа
38: 30429073 csrw mie, x5 # загружаем маску в регистр маски
3c: 04c00293 la x5, trap_handler # псевдоинструкция la аналогично li загружает число,
40: 00028293 # только в случае la это число является адресом
40: 00028293 # указанного места (адреса обработчика перехвата)
# данная псевдоинструкция будет разбита на две
# инструкции: lui и addi
44: 30529073 csrw mtvec, x5 # устанавливаем вектор прерывания
# Вызов функции main
main:
48: 00000063 beq x0, x0, main # бесконечный цикл, аналогичный while (1);
# ОБРАБОТЧИК ПЕРЕХВАТА
# Без стороннего вмешательства процессор никогда не перейдет к инструкциям ниже,
# однако в случае прерывания в программный счетчик будет загружен адрес первой
# нижележащей инструкции.
# Сохраняем используемые регистры на стек
trap_handler:
4c: 0000a383 lw x7, 0(x1) # загружаем значение из uart rx
50: 00947433 and x8, x8, x9 # обнуляем старые 3 байта
54: 00841413 slli x8, x8, 8 # Сдвигаем регистр x8 на 1 байт влево
58: 00746433 or x8, x8, x7 # записываем считанный из rx байт на освободившееся место
5c: 00340863 beq x8, x3, blink_mode # если пришел спец-код моргания, переходим в blink_mode
60: 00440a63 beq x8, x4, reset # если пришел спец-код сброса, переходим в reset
64: 00812023 sw x8, 0(x2) # записываем значением с переключателей в светодиоды
68: 30200073 mret # возвращаем управление программе (pc = mepc)
# что означает возврат в бесконечный цикл
blink_mode:
6c: 00612223 sw x6, 4(x2) # записываем 1 в led_mode
70: 30200073 mret
reset:
74: 02612223 sw x6, 0x24(x2) # записываем 1 в led_reset
78: 30200073 mret

View File

@@ -0,0 +1,32 @@
_start:
# Инициализируем начальные значения регистров
0: 050000b7 li x1 , 0x05000000 # сохраняем базовый адрес uart_rx
4: 06000137 li x2 , 0x06000000 # сохраняем базовый адрес uart_tx
8: 0001c1b7 li x3 , 0x0001c200 # устанавливаем бодрейт 115200
c: 20018193
10: 0030a623 sw x3 , 0x0c(x1)
14: 00312623 sw x3 , 0x0c(x2)
18: 00100213 li x4 , 0x00000001 # устанавливаем parity_bit
1c: 0040a823 sw x4 , 0x10(x1)
20: 00412823 sw x4 , 0x10(x2)
24: 00100293 li x5 , 0x00000001 # подготавливаем маску прерывания единственного
# (нулевого) входа
28: 30429073 csrw mie, x5 # загружаем маску в регистр маски
2c: 03c00293 la x5, trap_handler # псевдоинструкция la аналогично li загружает число,
30: 00028293 # только в случае la это число является адресом
# указанного места (адреса обработчика перехвата)
# данная псевдоинструкция будет разбита на две
# инструкции: lui и addi
34: 30529073 csrw mtvec, x5 # устанавливаем вектор прерывания
# Вызов функции main
main:
38: 00000063 beq x0, x0, main # бесконечный цикл, аналогичный while (1);
# ОБРАБОТЧИК ПЕРЕХВАТА
# Без стороннего вмешательства процессор никогда не перейдет к инструкциям ниже,
# однако в случае прерывания в программный счетчик будет загружен адрес первой
# нижележащей инструкции.
# Сохраняем используемые регистры на стек
trap_handler:
3c: 0000a383 lw x7, 0(x1) # загружаем пришедший байт
40: 00712023 sw x7, 0(x2)
44: 30200073 mret

View File

@@ -0,0 +1,40 @@
_start:
# Инициализируем начальные значения регистров
0: 010000b7 li x1, 0x01000000 # сохраняем базовый адрес переключателей
4: 02000137 li x2, 0x02000000 # сохраняем базовый адрес светодиодов
8: 0000b1b7 li x3, 0x0000aaaa # сохраняем спец-код для режима моргания
c: aaa18193
10: 00005237 li x4, 0x00005555 # сохраняем спец-код для сброса
14: 55520213
18: 00100313 li x6, 0x00000001 # сохраняем единицу
1c: 00100293 li x5, 0x00000001 # подготавливаем маску прерывания единственного
# (нулевого) входа
20: 30429073 csrw mie, x5 # загружаем маску в регистр маски
24: 03400293 la x5, trap_handler # псевдоинструкция la аналогично li загружает число,
28: 00028293 # только в случае la это число является адресом
# указанного места (адреса обработчика перехвата)
# данная псевдоинструкция будет разбита на две
# инструкции: lui и addi
2c: 30529073 csrw mtvec, x5 # устанавливаем вектор прерывания
# Вызов функции main
main:
30: 00000063 beq x0, x0, main # бесконечный цикл, аналогичный while (1);
# ОБРАБОТЧИК ПЕРЕХВАТА
# Без стороннего вмешательства процессор никогда не перейдет к инструкциям ниже,
# однако в случае прерывания в программный счетчик будет загружен адрес первой
# нижележащей инструкции.
# Сохраняем используемые регистры на стек
trap_handler:
34: 0000a383 lw x7, 0(x1) # загружаем значение на переключателях
38: 00338863 beq x7, x3, blink_mode # если пришел спец-код моргания, переходим в blink_mode
3c: 00438a63 beq x7, x4, reset # если пришел спец-код сброса, переходим в reset
40: 00712023 sw x7, 0(x2) # записываем значением с переключателей в светодиоды
44: 30200073 mret # возвращаем управление программе (pc = mepc)
# что означает возврат в бесконечный цикл
blink_mode:
48: 00612223 sw x6, 4(x2) # записываем 1 в led_mode
4c: 30200073 mret
reset:
50: 02612223 sw x6, 0x24(x2) # записываем 1 в led_reset
54: 30200073 mret