mirror of
https://github.com/MPSU/APS.git
synced 2025-09-16 17:40:41 +00:00
ЛР10-11. Изменение программы
При работе со стеком прерываний, верхушка стека не поднималась перед сохранением на стек новых данных, из-за чего данные сохранялись по нулевым ячейкам памяти.
This commit is contained in:
@@ -234,7 +234,7 @@ _Рисунок 5. Структурная схема контроллера пр
|
|||||||
```asm
|
```asm
|
||||||
_start:
|
_start:
|
||||||
# Инициализируем начальные значения регистров
|
# Инициализируем начальные значения регистров
|
||||||
00: li x2, 0x00003FFC # устанавливаем указатель на верхушку стека
|
00: li x2, 0x00003FF0 # устанавливаем указатель на верхушку стека
|
||||||
04: # данная псевдоинструкция будет разбита на две
|
04: # данная псевдоинструкция будет разбита на две
|
||||||
# инструкции: lui и addi
|
# инструкции: lui и addi
|
||||||
|
|
||||||
@@ -282,30 +282,33 @@ main:
|
|||||||
# Сохраняем используемые регистры на стек
|
# Сохраняем используемые регистры на стек
|
||||||
trap_handler:
|
trap_handler:
|
||||||
44: csrrw x5, mscratch, x5 # меняем местами mscratch и x5
|
44: csrrw x5, mscratch, x5 # меняем местами mscratch и x5
|
||||||
48: sw x6, 0(x5) # сохраняем x6 на стек mscratch
|
48: addi x5, x5, -16 # поднимаем верхушку стека на 16 байт вверх
|
||||||
4С: sw x7, 4(x5) # сохраняем x7 на стек mscratch
|
# (указатель на стек всегда должен быть выровнен
|
||||||
|
# границе в 16 байт)
|
||||||
|
4С: sw x6, 0(x5) # сохраняем x6 на стек mscratch
|
||||||
|
50: sw x7, 4(x5) # сохраняем x7 на стек mscratch
|
||||||
|
|
||||||
# Проверяем произошло ли прерывание
|
# Проверяем произошло ли прерывание
|
||||||
50: csrr x6, mcause # x6 = mcause
|
54: csrr x6, mcause # x6 = mcause
|
||||||
54: li x7, 0x80000010 # загружаем в x7 код того, что произошло прерывание
|
58: li x7, 0x80000010 # загружаем в x7 код того, что произошло прерывание
|
||||||
58: # данная псевдоинструкция будет разбита на две
|
5С: # данная псевдоинструкция будет разбита на две
|
||||||
# инструкции: lui и addi
|
# инструкции: lui и addi
|
||||||
5C: bne x6, x7, exc_handler # если коды не совпадают, переходим к проверке
|
60: bne x6, x7, exc_handler # если коды не совпадают, переходим к проверке
|
||||||
# на исключение
|
# на исключение
|
||||||
# Обработчик прерывания
|
# Обработчик прерывания
|
||||||
60: lw x7, 0(x3) # загружаем переменную из памяти
|
64: lw x7, 0(x3) # загружаем переменную из памяти
|
||||||
64: addi x7, x7, 3 # прибавляем к значению 3
|
68: addi x7, x7, 3 # прибавляем к значению 3
|
||||||
68: sw x7, 0(x3) # возвращаем переменную в память
|
6С: sw x7, 0(x3) # возвращаем переменную в память
|
||||||
6C: j done # идем возвращать регистры и на выход
|
70: j done # идем возвращать регистры и на выход
|
||||||
|
|
||||||
exc_handler: # Проверяем произошло ли исключение
|
exc_handler: # Проверяем произошло ли исключение
|
||||||
70: li x7, 0x0000002 # загружаем в x7 код того, что произошло исключение
|
74: li x7, 0x0000002 # загружаем в x7 код того, что произошло исключение
|
||||||
74: bne x6, x7, done # если это не оно, то выходим
|
78: bne x6, x7, done # если это не оно, то выходим
|
||||||
|
|
||||||
# Обработчик исключения
|
# Обработчик исключения
|
||||||
78: csrr x6, mepc # Узнаем значение PC (адреса инструкции,
|
7С: csrr x6, mepc # Узнаем значение PC (адреса инструкции,
|
||||||
# вызвавшей исключение)
|
# вызвавшей исключение)
|
||||||
7C: lw x7, 0x0(x6) # Загружаем эту инструкцию в регистр x7.
|
80: lw x7, 0x0(x6) # Загружаем эту инструкцию в регистр x7.
|
||||||
# В текущей микроархитектурной реализации это
|
# В текущей микроархитектурной реализации это
|
||||||
# невозможно, т.к. память инструкций отделена от
|
# невозможно, т.к. память инструкций отделена от
|
||||||
# памяти данных и не участвует в выполнении
|
# памяти данных и не участвует в выполнении
|
||||||
@@ -319,18 +322,19 @@ exc_handler: # Проверяем произошло ли иск
|
|||||||
# Например, если это операция умножения — вызвать
|
# Например, если это операция умножения — вызвать
|
||||||
# подпрограмму умножения.
|
# подпрограмму умножения.
|
||||||
|
|
||||||
80: addi x6, x6, 4 # Увеличиваем значение PC на 4, чтобы после
|
84: addi x6, x6, 4 # Увеличиваем значение PC на 4, чтобы после
|
||||||
# возврата не попасть на инструкцию, вызвавшую
|
# возврата не попасть на инструкцию, вызвавшую
|
||||||
# исключение.
|
# исключение.
|
||||||
84: csrw mepc, x6 # Записываем обновленное значение PC в регистр mepc
|
88: csrw mepc, x6 # Записываем обновленное значение PC в регистр mepc
|
||||||
88: j done # идем восстанавливать регистры со стека и на выход
|
8С: j done # идем восстанавливать регистры со стека и на выход
|
||||||
|
|
||||||
# Возвращаем регистры на места и выходим
|
# Возвращаем регистры на места и выходим
|
||||||
done:
|
done:
|
||||||
8C: lw x6, 0(x5) # возвращаем x6 со стека
|
90: lw x6, 0(x5) # возвращаем x6 со стека
|
||||||
90: lw x7, 4(x5) # возвращаем x7 со стека
|
94: lw x7, 4(x5) # возвращаем x7 со стека
|
||||||
94: csrrw x5, mscratch, x5 # меняем обратно местами x5 и mscratch
|
98: addi x5, x5, 16 # опускаем верхушку стека обратно на 16 байт вниз
|
||||||
98: mret # возвращаем управление программе (pc = mepc)
|
9С: csrrw x5, mscratch, x5 # меняем обратно местами x5 и mscratch
|
||||||
|
A0: mret # возвращаем управление программе (pc = mepc)
|
||||||
# что означает возврат в бесконечный цикл
|
# что означает возврат в бесконечный цикл
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
00004137
|
00004137
|
||||||
FFC10113
|
FF010113
|
||||||
00000193
|
00000193
|
||||||
04400293
|
04400293
|
||||||
00028293
|
00028293
|
||||||
@@ -16,6 +16,7 @@ FFC28293
|
|||||||
00000073
|
00000073
|
||||||
00000063
|
00000063
|
||||||
340292F3
|
340292F3
|
||||||
|
ff028293
|
||||||
0062A023
|
0062A023
|
||||||
0072A223
|
0072A223
|
||||||
34202373
|
34202373
|
||||||
@@ -35,5 +36,6 @@ FFC28293
|
|||||||
0040006F
|
0040006F
|
||||||
0002A303
|
0002A303
|
||||||
0042A383
|
0042A383
|
||||||
|
01028293
|
||||||
340292F3
|
340292F3
|
||||||
30200073
|
30200073
|
Reference in New Issue
Block a user