ЛР14. Уточнение методички

This commit is contained in:
Andrei Solodovnikov
2024-05-22 15:10:39 +03:00
parent af51ef612f
commit bf865179ea
3 changed files with 157 additions and 116 deletions

View File

@@ -41,7 +41,11 @@ _main_call:
# нулевой элемент которого является именем исполняемого файла,
# Но для простоты реализации оба аргумента всего лишь обнулены.
# Это сделано для детерминированного поведения программы в случае,
# если будет пытаться использовать эти аргументы.
# если программист будет пытаться использовать эти аргументы.
# Вызов main.
# Для того чтобы программа скомпоновалась, где-то должна быть описана
# функция именно с таким именем.
call main
# Зацикливание после выхода из функции main
_endless_loop:
@@ -64,12 +68,12 @@ _int_handler:
# Данная операция меняет местами регистры sp и mscratch.
# В итоге указатель на стек прерываний оказывается в регистре sp, а вершина
# программного стека оказывается в регистре mscratch.
csrrw sp,mscratch,sp
csrrw sp, mscratch,sp
# Далее мы поднимаемся по стеку прерываний и сохраняем все регистры.
addi sp,sp,-80 # Указатель на стек должен быть выровнен до 16 байт, поэтому
# поднимаемся вверх не на 76, а на 80.
sw ra,4(sp)
addi sp, sp, -80 # Указатель на стек должен быть выровнен до 16 байт, поэтому
# поднимаемся вверх не на 76, а на 80.
sw ra, 4(sp)
# Мы хотим убедиться, что очередное прерывание не наложит стек прерываний на
# программный стек, поэтому записываем в освободившийся регистр низ
# программного стека, и проверяем что приподнятый указатель на верхушку
@@ -80,34 +84,36 @@ _int_handler:
la ra, _stack_ptr
blt sp, ra, _endless_loop
sw t0,12(sp) # Мы перепрыгнули через смещение 8, поскольку там должен
# лежать регистр sp, который ранее сохранили в mscratch.
# Мы запишем его на стек чуть позже.
sw t1,16(sp)
sw t2,20(sp)
sw a0,24(sp)
sw a1,28(sp)
sw a2,32(sp)
sw a3,36(sp)
sw a4,40(sp)
sw a5,44(sp)
sw a6,48(sp)
sw a7,52(sp)
sw t3,56(sp)
sw t4,60(sp)
sw t5,64(sp)
sw t6,68(sp)
sw t0, 12(sp) # Мы перепрыгнули через смещение 8, поскольку там должен
# лежать регистр sp, который ранее сохранили в mscratch.
# Мы запишем его на стек чуть позже.
sw t1, 16(sp)
sw t2, 20(sp)
sw a0, 24(sp)
sw a1, 28(sp)
sw a2, 32(sp)
sw a3, 36(sp)
sw a4, 40(sp)
sw a5, 44(sp)
sw a6, 48(sp)
sw a7, 52(sp)
sw t3, 56(sp)
sw t4, 60(sp)
sw t5, 64(sp)
sw t6, 68(sp)
# Кроме того, мы сохраняем состояние регистров прерываний на случай, если
# произойдет еще одно прерывание.
csrr t0,mscratch
csrr t1,mepc
csrr a0,mcause
sw t0,8(sp)
sw t1,72(sp)
sw a0,76(sp)
csrr t0, mscratch
csrr t1, mepc
csrr a0, mcause
sw t0, 8(sp)
sw t1, 72(sp)
sw a0, 76(sp)
# Вызов высокоуровневого обработчика прерываний
# Вызов высокоуровневого обработчика прерываний.
# Для того чтобы программа скомпоновалась, где-то должна быть описана
# функция именно с таким именем.
call int_handler
# Восстановление контекста. В первую очередь мы хотим восстановить CS-регистры,
@@ -117,29 +123,29 @@ _int_handler:
# сохраним его в регистр a0, и будем восстанавливаться из него.
mv a0,sp
lw t1,72(a0)
addi sp,sp,80
csrw mscratch,sp
csrw mepc,t1
lw ra,4(a0)
lw sp,8(a0)
lw t0,12(a0)
lw t1,16(a0)
lw t2,20(a0)
lw a1,28(a0) # Мы пропустили a0, потому что сейчас он используется в
# качестве указателя на верхушку стека и не может быть
# восстановлен.
lw a2,32(a0)
lw a3,36(a0)
lw a4,40(a0)
lw a5,44(a0)
lw a6,48(a0)
lw a7,52(a0)
lw t3,56(a0)
lw t4,60(a0)
lw t5,64(a0)
lw t6,68(a0)
lw a0,40(a0)
lw t1, 72(a0)
addi sp, sp, 80
csrw mscratch, sp
csrw mepc, t1
lw ra, 4(a0)
lw sp, 8(a0)
lw t0, 12(a0)
lw t1, 16(a0)
lw t2, 20(a0)
lw a1, 28(a0) # Мы пропустили a0, потому что сейчас он используется в
# качестве указателя на верхушку стека и не может быть
# восстановлен.
lw a2, 32(a0)
lw a3, 36(a0)
lw a4, 40(a0)
lw a5, 44(a0)
lw a6, 48(a0)
lw a7, 52(a0)
lw t3, 56(a0)
lw t4, 60(a0)
lw t5, 64(a0)
lw t6, 68(a0)
lw a0, 40(a0)
# Выход из обработчика прерывания
mret