English version draft

Assisted-by: Claude:claude-4.6-sonnet
This commit is contained in:
Andrei Solodovnikov
2026-04-12 13:53:25 +03:00
parent 63260f434e
commit f3fcd27387
74 changed files with 5133 additions and 5875 deletions

View File

@@ -9,67 +9,67 @@ See https://github.com/MPSU/APS/blob/master/LICENSE file for licensing details.
* ------------------------------------------------------------------------------
*/
_start:
# Инициализируем начальные значения регистров
0: 030000b7 li x1 , 0x03000000 # сохраняем базовый адрес клавиатуры
4: 04000137 li x2 , 0x04000000 # сохраняем базовый адрес hex-контроллера
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: 03400293 la x5, trap_handler # псевдоинструкция la аналогично li загружает число,
20: 00028293 # только в случае la это число является адресом
# указанного места (адреса обработчика перехвата)
# данная псевдоинструкция будет разбита на две
# инструкции: lui и addi
24: 30529073 csrw mtvec, x5 # устанавливаем вектор прерывания
28: 000102b7 li x5 , 0x00010000 # подготавливаем маску прерывания единственного
# (нулевого) входа
2c: 30429073 csrw mie, x5 # загружаем маску в регистр маски
# Initialize register values
0: 030000b7 li x1 , 0x03000000 # save keyboard base address
4: 04000137 li x2 , 0x04000000 # save hex-controller base address
8: 0e000193 li x3 , 0x000000e0 # save scan code e0
c: 0f000213 li x4 , 0x000000f0 # save scan code f0
10: 00e00413 li x8 , 0x0000000e # save value e
14: 00f00493 li x9 , 0x0000000f # save value f
18: 00000593 li x11, 0x00000000 # save zero
1c: 03400293 la x5, trap_handler # the la pseudo-instruction loads a number similarly to li,
20: 00028293 # but in the case of la the number is the address
# of the specified location (the trap handler address);
# this pseudo-instruction will be split into two
# instructions: lui and addi
24: 30529073 csrw mtvec, x5 # set the interrupt vector
28: 000102b7 li x5 , 0x00010000 # prepare the interrupt mask for the single
# (zeroth) input
2c: 30429073 csrw mie, x5 # load the mask into the mask register
# Вызов функции main
# Call main function
main:
30: 00000063 beq x0, x0, main # бесконечный цикл, аналогичный while (1);
30: 00000063 beq x0, x0, main # infinite loop, equivalent to while (1);
# ОБРАБОТЧИК ПЕРЕХВАТА
# Без стороннего вмешательства процессор никогда не перейдет к инструкциям ниже,
# однако в случае прерывания в программный счетчик будет загружен адрес первой
# нижележащей инструкции.
# Сохраняем используемые регистры на стек
# TRAP HANDLER
# Without external intervention the processor will never reach the instructions below;
# however, upon an interrupt the program counter will be loaded with the address of
# the first instruction below.
# Save used registers to the stack
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 # пропускаем обнуление старших хексов
34: 0000a383 lw x7, 0(x1) # load scan code
38: 04338263 beq x7, x3, print_e0 # if scan code is e0, display using print_e0
3c: 04438c63 beq x7, x4, print_f0 # if scan code is f0, display using print_f0
40: 00700333 add x6, x0, x7 # duplicate scan code
44: 00435313 srl x6, x6, 4 # shift right by 4 to obtain the upper nibble
48: 00612223 sw x6, 4(x2) # write upper nibble to the first seven-segment display
4c: 00f3f393 andi x7, x7, 0xf # mask with f to obtain the lower nibble
50: 00712023 sw x7, 0(x2) # write lower nibble to the zeroth seven-segment display
54: 00b04c63 blt x0, x11, print_code # skip clearing of the upper hex displays
58: 00012a23 sw x0, 20(x2)
5c: 00012823 sw x0, 16(x2) # обнуляем 2-5 семисегментники
5c: 00012823 sw x0, 16(x2) # clear seven-segment displays 25
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)
# что означает возврат в бесконечный цикл
6c: 000005b3 add x11, x0, x0 # reset the counter
70: 00356513 ori x10, x10, 3 # initialize the mask enabling the 2 lower hex displays
74: 02a12023 sw x10, 32(x2) # write the mask
78: 30200073 mret # return control to the program (pc = mepc),
# which means returning to the infinite loop
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 # инкрементируем счетчик
7c: 00812a23 sw x8, 20(x2) # write e to the 5th seven-segment display
80: 00012823 sw x0, 16(x2) # write 0 to the 4th seven-segment display
84: 03056513 ori x10, x10, 0x30 # enable display of hex digits 45 in the mask
88: 02a12023 sw x10, 32(x2) # write the mask
8c: 00158593 addi x11, x11, 1 # increment the counter
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
94: 00912623 sw x9, 12(x2) # write f to the 3rd seven-segment display
98: 00012423 sw x0, 8(x2) # write 0 to the 2nd seven-segment display
9c: 00c56513 ori x10, x10, 0xc # enable display of hex digits 23 in the mask
a0: 02a12023 sw x10, 32(x2) # write the mask
a4: 00158593 addi x11, x11, 1 # increment the counter
a8: 30200073 mret

View File

@@ -9,40 +9,40 @@ See https://github.com/MPSU/APS/blob/master/LICENSE file for licensing details.
* ------------------------------------------------------------------------------
*/
_start:
# Инициализируем начальные значения регистров
0: 030000b7 li x1 , 0x03000000 # сохраняем базовый адрес клавиатуры
4: 02000137 li x2 , 0x02000000 # сохраняем базовый адрес led-контроллера
8: 0e000193 li x3 , 0x000000e0 # сохраняем сканкод e0
0с: 00000593 li x11, 0x00000000 # сохраняем ноль
10: 02800293 la x5, trap_handler # псевдоинструкция la аналогично li загружает число,
14: 00028293 # только в случае la это число является адресом
# указанного места (адреса обработчика перехвата)
# данная псевдоинструкция будет разбита на две
# инструкции: lui и addi
18: 30529073 csrw mtvec, x5 # устанавливаем вектор прерывания
1c: 000102b7 li x5 , 0x00010000 # подготавливаем маску прерывания единственного
# (нулевого) входа
20: 30429073 csrw mie, x5 # загружаем маску в регистр маски
# Initialize register values
0: 030000b7 li x1 , 0x03000000 # save keyboard base address
4: 02000137 li x2 , 0x02000000 # save LED controller base address
8: 0e000193 li x3 , 0x000000e0 # save scan code e0
0с: 00000593 li x11, 0x00000000 # save zero
10: 02800293 la x5, trap_handler # the la pseudo-instruction loads a number similarly to li,
14: 00028293 # but in the case of la the number is the address
# of the specified location (the trap handler address);
# this pseudo-instruction will be split into two
# instructions: lui and addi
18: 30529073 csrw mtvec, x5 # set the interrupt vector
1c: 000102b7 li x5 , 0x00010000 # prepare the interrupt mask for the single
# (zeroth) input
20: 30429073 csrw mie, x5 # load the mask into the mask register
# Вызов функции main
# Call main function
main:
24: 00000063 beq x0, x0, main # бесконечный цикл, аналогичный while (1);
24: 00000063 beq x0, x0, main # infinite loop, equivalent to while (1);
# ОБРАБОТЧИК ПЕРЕХВАТА
# Без стороннего вмешательства процессор никогда не перейдет к инструкциям ниже,
# однако в случае прерывания в программный счетчик будет загружен адрес первой
# нижележащей инструкции.
# Сохраняем используемые регистры на стек
# TRAP HANDLER
# Without external intervention the processor will never reach the instructions below;
# however, upon an interrupt the program counter will be loaded with the address of
# the first instruction below.
# Save used registers to the stack
trap_handler:
28: 0000a383 lw x7, 0(x1) # загружаем сканкод
2c: 00338663 beq x7, x3, change_mode # если сканкод e0, переключаем режим светодиодов
30: 00712023 sw x7, 0(x2) # выводим сканкод на светодиоды
34: 30200073 mret # возвращаем управление программе (pc = mepc)
# что означает возврат в бесконечный цикл
28: 0000a383 lw x7, 0(x1) # load scan code
2c: 00338663 beq x7, x3, change_mode # if scan code is e0, toggle LED mode
30: 00712023 sw x7, 0(x2) # output scan code to LEDs
34: 30200073 mret # return control to the program (pc = mepc),
# which means returning to the infinite loop
change_mode:
38: 00412403 lw x8, 4(x2) # считываем значение текущего режима
3c: 00144413 xori x8, x8, 1 # инвертируем его младший бит
40: 00812223 sw x8, 4(x2) # записываем инвертированный режим
44: 30200073 mret # возвращаем управление программе (pc = mepc)
# что означает возврат в бесконечный цикл
38: 00412403 lw x8, 4(x2) # read the current mode value
3c: 00144413 xori x8, x8, 1 # invert its least significant bit
40: 00812223 sw x8, 4(x2) # write the inverted mode back
44: 30200073 mret # return control to the program (pc = mepc),
# which means returning to the infinite loop

View File

@@ -9,37 +9,37 @@ See https://github.com/MPSU/APS/blob/master/LICENSE file for licensing details.
* ------------------------------------------------------------------------------
*/
_start:
# Инициализируем начальные значения регистров
0: 030000b7 li x1, 0x03000000 # сохраняем базовый адрес клавиатуры
4: 07000137 li x2, 0x07000000 # сохраняем базовый адрес vga-контроллера
8: 070011b7 li x3, 0x07000960 # количество символов на экране
c: 96018193 # данная псевдоинструкция будет разбита на две
# инструкции: lui и addi
10: 02400293 la x5, trap_handler # псевдоинструкция la аналогично li загружает число,
# только в случае la это число является адресом
# указанного места (адреса обработчика перехвата)
14: 30529073 csrw mtvec, x5 # устанавливаем вектор прерывания
18: 000102b7 li x5 , 0x00010000 # подготавливаем маску прерывания единственного
# (нулевого) входа
1c: 30429073 csrw mie, x5 # загружаем маску в регистр маски
# Initialize register values
0: 030000b7 li x1, 0x03000000 # save keyboard base address
4: 07000137 li x2, 0x07000000 # save VGA controller base address
8: 070011b7 li x3, 0x07000960 # total number of characters on screen
c: 96018193 # this pseudo-instruction will be split into two
# instructions: lui and addi
10: 02400293 la x5, trap_handler # the la pseudo-instruction loads a number similarly to li,
# but in the case of la the number is the address
# of the specified location (the trap handler address)
14: 30529073 csrw mtvec, x5 # set the interrupt vector
18: 000102b7 li x5 , 0x00010000 # prepare the interrupt mask for the single
# (zeroth) input
1c: 30429073 csrw mie, x5 # load the mask into the mask register
# Вызов функции main
# Call main function
main:
20: 00000063 beq x0, x0, main # бесконечный цикл, аналогичный while (1);
20: 00000063 beq x0, x0, main # infinite loop, equivalent to while (1);
# ОБРАБОТЧИК ПЕРЕХВАТА
# Без стороннего вмешательства процессор никогда не перейдет к инструкциям ниже,
# однако в случае прерывания в программный счетчик будет загружен адрес первой
# нижележащей инструкции.
# Сохраняем используемые регистры на стек
# TRAP HANDLER
# Without external intervention the processor will never reach the instructions below;
# however, upon an interrupt the program counter will be loaded with the address of
# the first instruction below.
# Save used registers to the stack
trap_handler:
24: 0000a383 lw x7, 0(x1) # загружаем сканкод
28: 00038403 lb x8, 0(x7) # берем данные из таблицы подстановки
2c: 00810023 sb 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)
# что означает возврат в бесконечный цикл
24: 0000a383 lw x7, 0(x1) # load scan code
28: 00038403 lb x8, 0(x7) # fetch data from the lookup table
2c: 00810023 sb x8, 0(x2) # write ASCII value to VGA
30: 00110113 addi x2, x2, 1 # increment VGA address
34: 00315463 bge x2, x3, wrap_addr # if VGA address is out of bounds, wrap it
38: 30200073 mret # return control to the program (pc = mepc),
# which means returning to the infinite loop
wrap_addr:
3c: 07000137 li x2, 0x07000000 # сохраняем базовый адрес vga-контроллера
3c: 07000137 li x2, 0x07000000 # restore VGA controller base address
40: 30200073 mret

View File

@@ -9,37 +9,37 @@ See https://github.com/MPSU/APS/blob/master/LICENSE file for licensing details.
* ------------------------------------------------------------------------------
*/
_start:
# Инициализируем начальные значения регистров
0: 050000b7 li x1 , 0x05000000 # сохраняем базовый адрес uart_rx
4: 04000137 li x2 , 0x04000000 # сохраняем базовый адрес hex-контроллера
8: 0001c1b7 li x3 , 0x0001c200 # устанавливаем бодрейт 115200
# Initialize register values
0: 050000b7 li x1 , 0x05000000 # save UART RX base address
4: 04000137 li x2 , 0x04000000 # save hex-controller base address
8: 0001c1b7 li x3 , 0x0001c200 # set baud rate to 115200
c: 20018193
10: 0030a623 sw x3 , 0x0c(x1)
14: 00100213 li x4 , 0x00000001 # устанавливаем parity_bit
14: 00100213 li x4 , 0x00000001 # set parity bit
18: 0040a823 sw x4 , 0x10(x1)
1c: 03400293 la x5, trap_handler # псевдоинструкция la аналогично li загружает число,
20: 00028293 # только в случае la это число является адресом
# указанного места (адреса обработчика перехвата)
# данная псевдоинструкция будет разбита на две
# инструкции: lui и addi
24: 30529073 csrw mtvec, x5 # устанавливаем вектор прерывания
28: 000102b7 li x5 , 0x00010000 # подготавливаем маску прерывания единственного
# (нулевого) входа
2c: 30429073 csrw mie, x5 # загружаем маску в регистр маски
1c: 03400293 la x5, trap_handler # the la pseudo-instruction loads a number similarly to li,
20: 00028293 # but in the case of la the number is the address
# of the specified location (the trap handler address);
# this pseudo-instruction will be split into two
# instructions: lui and addi
24: 30529073 csrw mtvec, x5 # set the interrupt vector
28: 000102b7 li x5 , 0x00010000 # prepare the interrupt mask for the single
# (zeroth) input
2c: 30429073 csrw mie, x5 # load the mask into the mask register
# Вызов функции main
# Call main function
main:
30: 00000063 beq x0, x0, main # бесконечный цикл, аналогичный while (1);
# ОБРАБОТЧИК ПЕРЕХВАТА
# Без стороннего вмешательства процессор никогда не перейдет к инструкциям ниже,
# однако в случае прерывания в программный счетчик будет загружен адрес первой
# нижележащей инструкции.
# Сохраняем используемые регистры на стек
30: 00000063 beq x0, x0, main # infinite loop, equivalent to while (1);
# TRAP HANDLER
# Without external intervention the processor will never reach the instructions below;
# however, upon an interrupt the program counter will be loaded with the address of
# the first instruction below.
# Save used registers to the stack
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) # записываем младший нибл в нулевой семисегментник
34: 0000a383 lw x7, 0(x1) # load the received byte
38: 00700333 add x6, x0, x7 # duplicate the scan code
3c: 00435313 srl x6, x6, 4 # shift right by 4 to obtain the upper nibble
40: 00612223 sw x6, 4(x2) # write upper nibble to the first seven-segment display
44: 00f3f393 andi x7, x7, 0xf # mask with f to obtain the lower nibble
48: 00712023 sw x7, 0(x2) # write lower nibble to the zeroth seven-segment display
4c: 30200073 mret

View File

@@ -9,52 +9,52 @@ See https://github.com/MPSU/APS/blob/master/LICENSE file for licensing details.
* ------------------------------------------------------------------------------
*/
_start:
# Инициализируем начальные значения регистров
0: 050000b7 li x1, 0x05000000 # сохраняем базовый адрес uart_rx
4: 02000137 li x2, 0x02000000 # сохраняем базовый адрес светодиодов
8: 0001c1b7 li x3, 0x0001c200 # устанавливаем бодрейт 115200
# Initialize register values
0: 050000b7 li x1, 0x05000000 # save UART RX base address
4: 02000137 li x2, 0x02000000 # save LED controller base address
8: 0001c1b7 li x3, 0x0001c200 # set baud rate to 115200
c: 20018193
10: 0030a623 sw x3, 0x0c(x1)
14: 00100213 li x4, 0x00000001 # устанавливаем parity_bit
14: 00100213 li x4, 0x00000001 # set parity bit
18: 0040a823 sw x4, 0x10(x1)
1c: 000011b7 li x3, 0x00000D0D # сохраняем спец-код для режима моргания
1c: 000011b7 li x3, 0x00000D0D # save special code for blink mode
20: d0d18193
24: 00008237 li x4, 0x00000808 # сохраняем спец-код для сброса
24: 00008237 li x4, 0x00000808 # save special code for reset
28: f7f20213
2c: 0ff00493 li x9, 0x000000ff # сохраняем маску для обнуления старшей части
30: 00100313 li x6, 0x00000001 # сохраняем единицу
34: 04c00293 la x5, trap_handler # псевдоинструкция la аналогично li загружает число,
38: 00028293 # только в случае la это число является адресом
# указанного места (адреса обработчика перехвата)
# данная псевдоинструкция будет разбита на две
# инструкции: lui и addi
3c: 30529073 csrw mtvec, x5 # устанавливаем вектор прерывания
40: 000102b7 li x5 , 0x00010000 # подготавливаем маску прерывания единственного
# (нулевого) входа
44: 30429073 csrw mie, x5 # загружаем маску в регистр маски
2c: 0ff00493 li x9, 0x000000ff # save mask for clearing the upper bytes
30: 00100313 li x6, 0x00000001 # save one
34: 04c00293 la x5, trap_handler # the la pseudo-instruction loads a number similarly to li,
38: 00028293 # but in the case of la the number is the address
# of the specified location (the trap handler address);
# this pseudo-instruction will be split into two
# instructions: lui and addi
3c: 30529073 csrw mtvec, x5 # set the interrupt vector
40: 000102b7 li x5 , 0x00010000 # prepare the interrupt mask for the single
# (zeroth) input
44: 30429073 csrw mie, x5 # load the mask into the mask register
# Вызов функции main
# Call main function
main:
48: 00000063 beq x0, x0, main # бесконечный цикл, аналогичный while (1);
# ОБРАБОТЧИК ПЕРЕХВАТА
# Без стороннего вмешательства процессор никогда не перейдет к инструкциям ниже,
# однако в случае прерывания в программный счетчик будет загружен адрес первой
# нижележащей инструкции.
# Сохраняем используемые регистры на стек
48: 00000063 beq x0, x0, main # infinite loop, equivalent to while (1);
# TRAP HANDLER
# Without external intervention the processor will never reach the instructions below;
# however, upon an interrupt the program counter will be loaded with the address of
# the first instruction below.
# Save used registers to the stack
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)
# что означает возврат в бесконечный цикл
4c: 0000a383 lw x7, 0(x1) # load value from UART RX
50: 00947433 and x8, x8, x9 # clear the upper 3 bytes
54: 00841413 slli x8, x8, 8 # shift register x8 left by 1 byte
58: 00746433 or x8, x8, x7 # write the byte read from RX into the vacated position
5c: 00340863 beq x8, x3, blink_mode # if blink special code received, jump to blink_mode
60: 00440a63 beq x8, x4, reset # if reset special code received, jump to reset
64: 00812023 sw x8, 0(x2) # write the value to LEDs
68: 30200073 mret # return control to the program (pc = mepc),
# which means returning to the infinite loop
blink_mode:
6c: 00612223 sw x6, 4(x2) # записываем 1 в led_mode
6c: 00612223 sw x6, 4(x2) # write 1 to led_mode
70: 30200073 mret
reset:
74: 02612223 sw x6, 0x24(x2) # записываем 1 в led_reset
74: 02612223 sw x6, 0x24(x2) # write 1 to led_reset
78: 30200073 mret

View File

@@ -9,35 +9,35 @@ See https://github.com/MPSU/APS/blob/master/LICENSE file for licensing details.
* ------------------------------------------------------------------------------
*/
_start:
# Инициализируем начальные значения регистров
0: 050000b7 li x1 , 0x05000000 # сохраняем базовый адрес uart_rx
4: 06000137 li x2 , 0x06000000 # сохраняем базовый адрес uart_tx
8: 0001c1b7 li x3 , 0x0001c200 # устанавливаем бодрейт 115200
# Initialize register values
0: 050000b7 li x1 , 0x05000000 # save UART RX base address
4: 06000137 li x2 , 0x06000000 # save UART TX base address
8: 0001c1b7 li x3 , 0x0001c200 # set baud rate to 115200
c: 20018193
10: 0030a623 sw x3 , 0x0c(x1)
14: 00312623 sw x3 , 0x0c(x2)
18: 00100213 li x4 , 0x00000001 # устанавливаем parity_bit
18: 00100213 li x4 , 0x00000001 # set parity bit
1c: 0040a823 sw x4 , 0x10(x1)
20: 00412823 sw x4 , 0x10(x2)
24: 03c00293 la x5, trap_handler # псевдоинструкция la аналогично li загружает число,
28: 00028293 # только в случае la это число является адресом
# указанного места (адреса обработчика перехвата)
# данная псевдоинструкция будет разбита на две
# инструкции: lui и addi
2c: 30529073 csrw mtvec, x5 # устанавливаем вектор прерывания
30: 000102b7 li x5 , 0x00010000 # подготавливаем маску прерывания единственного
# (нулевого) входа
34: 30429073 csrw mie, x5 # загружаем маску в регистр маски
24: 03c00293 la x5, trap_handler # the la pseudo-instruction loads a number similarly to li,
28: 00028293 # but in the case of la the number is the address
# of the specified location (the trap handler address);
# this pseudo-instruction will be split into two
# instructions: lui and addi
2c: 30529073 csrw mtvec, x5 # set the interrupt vector
30: 000102b7 li x5 , 0x00010000 # prepare the interrupt mask for the single
# (zeroth) input
34: 30429073 csrw mie, x5 # load the mask into the mask register
# Вызов функции main
# Call main function
main:
38: 00000063 beq x0, x0, main # бесконечный цикл, аналогичный while (1);
# ОБРАБОТЧИК ПЕРЕХВАТА
# Без стороннего вмешательства процессор никогда не перейдет к инструкциям ниже,
# однако в случае прерывания в программный счетчик будет загружен адрес первой
# нижележащей инструкции.
# Сохраняем используемые регистры на стек
38: 00000063 beq x0, x0, main # infinite loop, equivalent to while (1);
# TRAP HANDLER
# Without external intervention the processor will never reach the instructions below;
# however, upon an interrupt the program counter will be loaded with the address of
# the first instruction below.
# Save used registers to the stack
trap_handler:
3c: 0000a383 lw x7, 0(x1) # загружаем пришедший байт
3c: 0000a383 lw x7, 0(x1) # load the received byte
40: 00712023 sw x7, 0(x2)
44: 30200073 mret

View File

@@ -9,43 +9,43 @@ See https://github.com/MPSU/APS/blob/master/LICENSE file for licensing details.
* ------------------------------------------------------------------------------
*/
_start:
# Инициализируем начальные значения регистров
0: 010000b7 li x1, 0x01000000 # сохраняем базовый адрес переключателей
4: 02000137 li x2, 0x02000000 # сохраняем базовый адрес светодиодов
8: 0000b1b7 li x3, 0x0000aaaa # сохраняем спец-код для режима моргания
# Initialize register values
0: 010000b7 li x1, 0x01000000 # save switches base address
4: 02000137 li x2, 0x02000000 # save LED controller base address
8: 0000b1b7 li x3, 0x0000aaaa # save special code for blink mode
c: aaa18193
10: 00005237 li x4, 0x00005555 # сохраняем спец-код для сброса
10: 00005237 li x4, 0x00005555 # save special code for reset
14: 55520213
18: 00100313 li x6, 0x00000001 # сохраняем единицу
1c: 03400293 la x5, trap_handler # псевдоинструкция la аналогично li загружает число,
20: 00028293 # только в случае la это число является адресом
# указанного места (адреса обработчика перехвата)
# данная псевдоинструкция будет разбита на две
# инструкции: lui и addi
24: 30529073 csrw mtvec, x5 # устанавливаем вектор прерывания
28: 000102b7 li x5 , 0x00010000 # подготавливаем маску прерывания единственного
# (нулевого) входа
2c: 30429073 csrw mie, x5 # загружаем маску в регистр маски
18: 00100313 li x6, 0x00000001 # save one
1c: 03400293 la x5, trap_handler # the la pseudo-instruction loads a number similarly to li,
20: 00028293 # but in the case of la the number is the address
# of the specified location (the trap handler address);
# this pseudo-instruction will be split into two
# instructions: lui and addi
24: 30529073 csrw mtvec, x5 # set the interrupt vector
28: 000102b7 li x5 , 0x00010000 # prepare the interrupt mask for the single
# (zeroth) input
2c: 30429073 csrw mie, x5 # load the mask into the mask register
# Вызов функции main
# Call main function
main:
30: 00000063 beq x0, x0, main # бесконечный цикл, аналогичный while (1);
# ОБРАБОТЧИК ПЕРЕХВАТА
# Без стороннего вмешательства процессор никогда не перейдет к инструкциям ниже,
# однако в случае прерывания в программный счетчик будет загружен адрес первой
# нижележащей инструкции.
# Сохраняем используемые регистры на стек
30: 00000063 beq x0, x0, main # infinite loop, equivalent to while (1);
# TRAP HANDLER
# Without external intervention the processor will never reach the instructions below;
# however, upon an interrupt the program counter will be loaded with the address of
# the first instruction below.
# Save used registers to the stack
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)
# что означает возврат в бесконечный цикл
34: 0000a383 lw x7, 0(x1) # load the value from the switches
38: 00338863 beq x7, x3, blink_mode # if blink special code received, jump to blink_mode
3c: 00438a63 beq x7, x4, reset # if reset special code received, jump to reset
40: 00712023 sw x7, 0(x2) # write the switch value to LEDs
44: 30200073 mret # return control to the program (pc = mepc),
# which means returning to the infinite loop
blink_mode:
48: 00612223 sw x6, 4(x2) # записываем 1 в led_mode
48: 00612223 sw x6, 4(x2) # write 1 to led_mode
4c: 30200073 mret
reset:
50: 02612223 sw x6, 0x24(x2) # записываем 1 в led_reset
54: 30200073 mret
50: 02612223 sw x6, 0x24(x2) # write 1 to led_reset
54: 30200073 mret