Skip to content

Assembly Guide — Interrupts and Exceptions Handling

DodaTech Updated 2026-06-28 5 min read

In this tutorial, you will learn about Assembly Guide. We cover key concepts, practical examples, and best practices to help you master this topic.

x86-64 interrupts are events that transfer control to predefined handlers through the Interrupt Descriptor Table (IDT), handling hardware I/O, system calls, exceptions, and faults.

What You'll Learn

  • Interrupt types: hardware, software, exceptions
  • Interrupt Descriptor Table (IDT)
  • INT instruction for system calls
  • Exception Handling (page faults, division errors)
  • Interrupt handler conventions

Why It Matters

Interrupts are the interface between software and hardware. Understanding them is essential for OS development, drivers, and system programming. Durga Antivirus Pro hooks interrupts for monitoring.

Real-World Use

Operating system kernels, device drivers, Embedded Systems, and security monitoring tools.

flowchart LR
    A["Interrupts"] --> B["Types"]
    B --> C["IDT"]
    C --> D["Handlers"]
    D --> E["System Calls"]
    A:::current --> B
    style A fill:#2563eb,stroke:#2563eb,color:#fff
    style B fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style C fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style D fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style E fill:#f1f5f9,stroke:#94a3b8,color:#64748b

Interrupt Types

; Hardware interrupts (IRQs)
; Generated by hardware devices: keyboard, timer, disk
; Example: IRQ0 = timer, IRQ1 = keyboard

; Software interrupts (INT n)
; Generated by INT instruction
int 0x80        ; Linux syscall (legacy)
int 0x21        ; DOS syscall

; Exceptions
; Generated by CPU on errors:
; #DE (0): Division error
; #BP (3): Breakpoint
; #PF (14): Page fault
; #GP (13): General protection fault

INT Instruction

; Generate software interrupt
; Transfers control to interrupt handler

; In real mode / legacy:
mov ah, 0x09    ; Function number
mov dx, msg     ; String pointer
int 0x21        ; DOS syscall

; Modern approach: SYSCALL instruction
; (not an interrupt, but same concept)

Interrupt Descriptor Table

; IDT: Array of 256 gate descriptors
; Each entry: 16 bytes (in 64-bit mode)
; Contains: handler address, segment selector, flags

; Structure (64-bit IDT entry):
; Bytes 0-1: Low 16 bits of handler offset
; Bytes 2-3: Code segment selector
; Bytes 4-5: Flags (type, DPL, present)
; Bytes 6-7: Middle 16 bits of handler offset
; Bytes 8-15: High 32 bits of handler offset

; IDT is loaded with LIDT instruction
lidt [idt_descriptor]

Simple Interrupt Handler

; Interrupt handler (save/restore registers)
section .text
global handler_timer

handler_timer:
    ; Save registers
    push rax
    push rcx
    push rdx
    push rsi
    push rdi
    push r8
    push r9
    push r10
    push r11

    ; Handler body
    ; ... process interrupt ...

    ; Restore registers
    pop r11
    pop r10
    pop r9
    pop r8
    pop rdi
    pop rsi
    pop rdx
    pop rcx
    pop rax

    ; Return from interrupt
    iretq

Exception Handling

; Division by zero (#DE, vector 0)
; CPU pushes error code (not for #DE)
; Handler must determine cause and respond

    mov rax, 5
    xor rbx, rbx   ; divisor = 0
    div rbx         ; Triggers #DE exception

; Page fault (#PF, vector 14)
; CR2 contains the faulting address
; Error code provides access type info

handler_page_fault:
    ; CR2 has the faulting address
    mov rax, cr2
    ; Error code on stack indicates:
    ; Bit 0: 0=non-present, 1=protection violation
    ; Bit 1: 0=read, 1=write
    ; Bit 2: 0=supervisor, 1=user
    ; ... handling ...
    add rsp, 8      ; Remove error code
    iretq

System Calls with INT 0x80

; Linux system calls (legacy 32-bit interface)
; Still works in 64-bit mode but uses different registers

section .data
msg db "Hello", 0xa
len equ $ - msg

section .text
    ; write(1, msg, len)
    mov eax, 4      ; sys_write
    mov ebx, 1      ; fd = stdout
    mov ecx, msg    ; buffer
    mov edx, len    ; length
    int 0x80

    ; exit(0)
    mov eax, 1      ; sys_exit
    xor ebx, ebx    ; code = 0
    int 0x80

; Note: Prefer SYSCALL on modern 64-bit systems

Common Mistakes

1. Forgetting IRETQ

IRETQ returns from interrupt. RET is for regular functions. Using RET in handlers crashes the system.

2. Not saving registers

Interrupt handlers run in any context. Preserve all registers the handler modifies.

3. Masking interrupts for too long

STI enables, CLI disables interrupts. Keep interrupt-disabled sections short.

4. Stack overflow in handlers

Handler stacks are limited (typically 4KB on x86-64). Don't use deep Recursion.

5. RFLAGS corruption

Interrupts save RFLAGS automatically. But modifying IF inside handlers requires care.

Practice Questions

1. What is an interrupt vector? A number (0-255) identifying which interrupt handler to invoke, used as an index into the IDT.

2. How do interrupts differ from function calls? Interrupts save RFLAGS and can transition privilege levels. They use IRETQ to return. Function calls use RET.

3. What is the IDT? The Interrupt Descriptor Table holds addresses and attributes for all 256 interrupt handlers.

Challenge: Write a simple interrupt handler that counts the number of timer interrupts.

FAQ

{{< faq question="Can user-mode code handle interrupts?" >} No. Interrupt handlers run in kernel mode. User code cannot install or override handlers. {{< /faq >}}

{{< faq question="What is an interrupt gate vs trap gate?" >} Interrupt gates clear IF (disable interrupts). Trap gates don't. Use interrupt gates for hardware IRQs. {{< /faq >}}

{{< faq question="How many interrupts can x86-64 handle?" >} 256 total. 0-31 reserved for exceptions. 32-255 available for software and hardware interrupts. {{< /faq >}}

{{< faq question="What happens during an interrupt?" >} CPU saves RSP, SS, RFLAGS, CS, RIP, and error code on stack. Loads handler address from IDT. Jumps to handler. {{< /faq >}}

{{< faq question="Can interrupts be nested?" >} Yes. Higher-priority interrupts can interrupt lower-priority handlers. Each handler must re-enable interrupts when ready. {{< /faq >}}

Mini Project

Set up a simple interrupt handler (kernel code):

section .data
idt_ptr:
    dw 256*16 - 1       ; Limit
    dq idt              ; Base address

section .bss
align 16
idt: resb 256*16       ; IDT table

section .text
global setup_idt
setup_idt:
    ; Fill IDT entries for handlers
    ; Each entry: 16 bytes
    ; ... setup code ...

    lidt [idt_ptr]
    sti                 ; Enable interrupts
    ret

global timer_handler
timer_handler:
    push rax
    ; Send EOI to PIC
    mov al, 0x20
    out 0x20, al
    pop rax
    iretq

What's Next

Now that you understand interrupts, explore Linux system calls for I/O operations.

Topic Description Link
Assembly Syscalls Linux system calls {{< ref "13-syscalls" >}}
Assembly Strings String operations {{< ref "14-strings" >}}

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro