_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