# Interrupt handlers (ivss) An **interrupt handler** services an event at the address installed in `%handler`. A shared handler can inspect `%cause` and select the appropriate behavior: ```asm handler: push %r1 push %r2 csrrd %cause, %r1 ld $4, %r2 bne %r1, %r2, finish ld $42, %r5 # software-interrupt result finish: pop %r2 pop %r1 iret ``` This example handles cause four and leaves a result in `%r5`. Causes two and three identify timer and terminal events; cause one identifies an invalid instruction. The main program must install `handler` before requesting delivery. The automatic entry frame saves the program counter, status, and registers twelve and thirteen. The explicit pushes preserve registers one and two, which this handler uses for dispatch. They are popped in reverse order before the automatic frame is consumed. Any register intentionally changed, such as `%r5` here, becomes part of the handler's contract with the main program. A final [[ivss-interrupt-return|`iret`]] restores the interrupted context; ordinary `ret` is only appropriate for separately called subroutines. Source: [emulator.c](https://github.com/yanevskiv/ivss/blob/main/src/emulator.c).