interrupts

the x86 interrupt calls i actually reach for. the full firehose is ralf brown's list, and this is just my slice of it.

jump to int 21h · int 10h · int 16h · int 13h · linux 32-bit · linux 64-bit

int 21h (dos api)

ah picks the function.

  • 01h reads a char from stdin with echo → al
  • 02h prints the char in dl
  • 08h reads a char without echo → al
  • 09h prints the $-terminated string at ds:dx
  • 0ah reads a buffered line into ds:dx
  • 3ch creates or truncates a file (ds:dx name, cx attrs) → ax handle
  • 3dh opens a file (al mode) → ax handle
  • 3eh closes the handle in bx
  • 3fh reads cx bytes from handle bx into ds:dx
  • 40h writes cx bytes from ds:dx to handle bx
  • 42h seeks handle bx (al origin, cx:dx offset)
  • 4ch exits with the code in al
; print a string, then exit clean
mov ah, 09h
mov dx, msg          ; ds:dx -> "$"-terminated string
int 21h
mov ax, 4c00h        ; ah=4ch (exit), al=0 (code)
int 21h
msg db "hello$"

int 10h (bios video)

  • ah=00h sets the video mode (al = mode)
  • ah=0eh is teletype output, it prints the char in al and moves the cursor forward
  • ah=02h sets the cursor position (dh row, dl col, bh page)
  • ah=13h writes a string (es:bp ptr, cx len)
; teletype one char, real mode (bootloader-style)
mov ah, 0eh
mov al, 'x'
int 10h

int 16h (bios keyboard)

  • ah=00h waits for a key → al ascii, ah scancode
  • ah=01h checks whether a key is available, with the result in zf
; block until a key; ascii lands in al
xor ah, ah           ; ah=00h
int 16h

int 13h (bios disk)

  • ah=00h resets the drive in dl
  • ah=02h reads al sectors (ch/cl cyl/sector, dh head, dl drive) → es:bx
  • ah=03h writes al sectors (same args)
  • ah=08h gets the drive params
; load the sector after the mbr to 0000:7e00
xor bx, bx
mov es, bx           ; es=0
mov bx, 7e00h        ; es:bx = buffer
mov ah, 02h
mov al, 1            ; one sector
mov ch, 0            ; cylinder 0
mov cl, 2            ; sector 2 (1-based)
mov dh, 0            ; head 0
mov dl, 80h          ; first hard disk
int 13h

linux 32-bit (int 0x80)

eax is the number, and the args go in ebx, ecx, edx, esi, edi.

  • 1 is exit(ebx code)
  • 3 is read(ebx fd, ecx buf, edx len)
  • 4 is write(ebx fd, ecx buf, edx len)
  • 5 is open(ebx path, ecx flags, edx mode)
  • 6 is close(ebx fd)
  • 11 is execve(ebx path, ecx argv, edx envp)
; write(1, msg, 3); exit(0)
mov eax, 4
mov ebx, 1           ; stdout
mov ecx, msg
mov edx, 3
int 0x80
mov eax, 1
xor ebx, ebx
int 0x80

linux 64-bit (syscall)

rax is the number, and the args go in rdi, rsi, rdx, r10, r8, r9.

  • 0 is read(rdi fd, rsi buf, rdx len)
  • 1 is write(rdi fd, rsi buf, rdx len)
  • 2 is open(rdi path, rsi flags, rdx mode)
  • 3 is close(rdi fd)
  • 59 is execve(rdi path, rsi argv, rdx envp)
  • 60 is exit(rdi code)
; write(1, msg, 3); exit(0)
mov rax, 1
mov rdi, 1           ; stdout
lea rsi, [rel msg]
mov rdx, 3
syscall
mov rax, 60
xor rdi, rdi
syscall