INT 15h – System Services (Layanan Sistem)

Deskripsi Umum

INT 15h adalah salah satu interupsi BIOS yang paling kompleks dan serbaguna. Interupsi ini menyediakan berbagai layanan sistem tingkat rendah yang mencakup manajemen memori extended, kontrol power management, konfigurasi sistem, dan berbagai fungsi lanjutan lainnya.

Karakteristik

  • Tipe: BIOS Service Interrupt
  • Kategori: System Services
  • Kompleksitas: Tinggi (banyak subfungsi)
  • Penggunaan: Boot loader, kernel initialization, system configuration

Sejarah

INT 15h berkembang seiring evolusi PC:

  • PC/XT: Fungsi dasar cassette tape (sudah obsolete)
  • AT (286): Extended memory services
  • 386+: Protected mode services, APM
  • Modern: E820 memory map, PCI BIOS

Daftar Lengkap Fungsi INT 15h

Kategori 1: Memory Services

Fungsi (AX/AH)NamaEraDeskripsi Singkat
AH=87hMove Extended Memory BlockAT+Memindahkan data antara conventional dan extended memory
AH=88hGet Extended Memory SizeAT+Mendapatkan ukuran extended memory (KB di atas 1MB)
AH=89hEnter Protected ModeAT+Switch ke Protected Mode (286)
AX=E801hGet Memory Size (Extended)386+Mendapat ukuran memory >64MB
AX=E820hGet Memory Map486+PALING PENTING – Memory map detail untuk OS modern
AX=E881hGet Memory Size (Alternative)Pentium+Alternatif E801h

Kategori 2: APM (Advanced Power Management)

Fungsi (AX)NamaDeskripsi
AX=5300hAPM Installation CheckCek ketersediaan APM
AX=5301hAPM Real Mode ConnectKoneksi APM di Real Mode
AX=5302hAPM Protected Mode ConnectKoneksi APM di Protected Mode
AX=5303hAPM DisconnectPutus koneksi APM
AX=5304hAPM Interface ConnectKoneksi interface APM
AX=5305hAPM CPU IdleSet CPU ke idle state
AX=5306hAPM CPU BusyKeluar dari idle state
AX=5307hSet Power StateSet device power state (suspend, off, dll)
AX=5308hEnable/Disable Power ManagementKontrol power management
AX=5309hRestore DefaultRestore setting default APM
AX=530AhGet Power StatusStatus battery dan AC
AX=530BhGet EventMendapat APM event
AX=530ChGet Power StateStatus power device
AX=530DhEnable Device Power ManagementEnable PM untuk device tertentu
AX=530EhGet APM VersionVersi APM driver
AX=530FhEngage/Disengage Power ManagementEngage/disengage PM

Kategori 3: System Configuration

Fungsi (AH)NamaDeskripsi
AH=C0hGet System ConfigurationPENTING – Parameter konfigurasi sistem
AH=C1hGet Extended BIOS Data AreaSegment EBDA
AH=C2hPointing Device (Mouse)Fungsi PS/2 mouse
AH=C3hWatchdog TimerSet/reset watchdog timer
AH=C4hProgrammable Option SelectPOS information (MCA)
AH=C9hGet CPU InfoInformasi CPU (586+)

Kategori 4: Timing & Delays

Fungsi (AH)NamaDeskripsi
AH=83hEvent WaitSet interval atau wait event
AH=86hWaitDelay dalam microseconds
AH=90hDevice BusyDevice busy loop
AH=91hInterrupt CompleteSinyal interrupt selesai

Kategori 5: Miscellaneous

Fungsi (AH)NamaDeskripsi
AH=84hJoystick SupportBaca joystick
AH=85hSysRq KeySysRq key handler
AH=4FhKeyboard InterceptHook keyboard
AH=D8hEISA System FunctionsFungsi EISA bus

Penjelasan Detail Fungsi Penting


AH=88h – Get Extended Memory Size

Deskripsi

Mendapatkan jumlah extended memory (memori di atas 1MB) dalam satuan kilobyte. Fungsi ini hanya dapat mendeteksi maksimum 64MB.

Input Parameters

AH = 88h

Output/Return Values

AX = Jumlah extended memory dalam KB (continuous dari 1MB)
     (0 jika tidak ada extended memory)
CF = Clear jika sukses
CF = Set jika error
     AH = error code (80h = invalid command, 86h = function not supported)

Contoh Penggunaan

; Mendapatkan ukuran extended memory
mov ah, 88h
int 15h
jc .no_extended_memory

; AX sekarang berisi KB extended memory
; Contoh: AX = 15360 berarti 15MB extended memory (total 16MB RAM)

mov [extended_mem_kb], ax
jmp .continue

.no_extended_memory:
    ; Handle: tidak ada extended memory
    xor ax, ax
    mov [extended_mem_kb], ax

.continue:
    ; Lanjutkan...

Limitasi

  • Maksimum: 64MB (65535 KB)
  • Untuk sistem >64MB, gunakan AX=E801h atau AX=E820h
  • Tidak mendeteksi memory holes

Nilai Return Umum

Sistem    | AX Value | Total RAM
----------|----------|----------
2 MB | 1024 | 1 MB extended
4 MB | 3072 | 3 MB extended
8 MB | 7168 | 7 MB extended
16 MB | 15360 | 15 MB extended
64 MB | 64512 | ~63 MB extended
128 MB | 65535 | MAX (terpotong!)

Catatan Penting

⚠️ DEPRECATED untuk sistem modern – Gunakan E820h untuk OS baru


AH=86h – Wait (Microsecond Delay)

Deskripsi

Memberikan delay dalam satuan microseconds. Fungsi ini menggunakan system timer untuk memberikan delay yang akurat tanpa busy-waiting CPU.

Input Parameters

AH = 86h
CX:DX = Jumlah microseconds untuk wait (32-bit value)
        CX = High word
        DX = Low word

Output/Return Values

CF = Clear jika sukses (wait selesai)
CF = Set jika error
     AH = error code:
          80h = Invalid command
          83h = Wait already in progress (wait sebelumnya belum selesai)
          86h = Function not supported

Contoh Penggunaan

Contoh 1: Delay 1 detik (1,000,000 microseconds)

; Delay 1 detik = 1,000,000 microseconds = 0x000F4240
mov ah, 86h
mov cx, 0x000F        ; High word
mov dx, 0x4240        ; Low word
int 15h
jc .wait_error

; Delay selesai, lanjutkan eksekusi
jmp .continue

.wait_error:
    ; Handle error
    ; AH berisi error code
    
.continue:
    ; Kode selanjutnya...

Contoh 2: Delay 500 milliseconds (500,000 microseconds)

; 500ms = 500,000 = 0x0007A120
mov ah, 86h
mov cx, 0x0007
mov dx, 0xA120
int 15h

Contoh 3: Delay 100 microseconds

; 100 microseconds = 0x00000064
mov ah, 86h
xor cx, cx           ; CX = 0
mov dx, 100          ; DX = 100
int 15h

Tabel Konversi Waktu

Waktu      | Microseconds | CX Value | DX Value
-----------|--------------|----------|----------
1 μs       | 1            | 0x0000   | 0x0001
100 μs     | 100          | 0x0000   | 0x0064
1 ms       | 1,000        | 0x0000   | 0x03E8
10 ms      | 10,000       | 0x0000   | 0x2710
100 ms     | 100,000      | 0x0001   | 0x86A0
500 ms     | 500,000      | 0x0007   | 0xA120
1 sec      | 1,000,000    | 0x000F   | 0x4240
2 sec      | 2,000,000    | 0x001E   | 0x8480
5 sec      | 5,000,000    | 0x004C   | 0x4B40
10 sec     | 10,000,000   | 0x0098   | 0x9680

Implementasi Internal

BIOS biasanya menggunakan:

  1. System Timer (IRQ 0) yang tick setiap ~55ms
  2. Real-Time Clock (RTC) untuk timing lebih presisi
  3. Menghitung jumlah ticks yang diperlukan

Akurasi

  • Minimum delay: ~1000 microseconds (1ms) pada kebanyakan sistem
  • Akurasi: ±15-55 microseconds (tergantung timer resolution)
  • Delay di bawah 1ms mungkin tidak akurat

Catatan Penting

⚠️ Selama wait, CPU tidak melakukan apa-apa (tidak dapat diinterrupt dengan mudah)

⚠️ Hindari wait yang sangat panjang (>beberapa detik) karena dapat membuat sistem terlihat hang

Best practice untuk delay panjang: Gunakan loop dengan delay pendek

; Delay 10 detik dengan loop 10x1 detik
mov cx, 10           ; Loop 10 kali
.delay_loop:
    push cx
    
    ; Delay 1 detik
    mov ah, 86h
    mov cx, 0x000F
    mov dx, 0x4240
    int 15h
    
    pop cx
    loop .delay_loop


AH=87h – Move Extended Memory Block

Deskripsi

Memindahkan blok data antara conventional memory (di bawah 1MB) dan extended memory (di atas 1MB), atau antar region di extended memory. Fungsi ini sangat penting untuk bootloader yang perlu memuat kernel ke extended memory.

Input Parameters

AH = 87h
CX = Jumlah words (16-bit) untuk dipindahkan
      (Jadi untuk memindahkan N bytes: CX = N/2)
ES:SI = Pointer ke Global Descriptor Table (GDT)

Output/Return Values

CF = Clear jika sukses
CF = Set jika error
     AH = Error code:
          00h = No error
          01h = RAM parity error
          02h = Exception interrupt error
          03h = Gate A20 error

Global Descriptor Table (GDT) Structure

GDT harus berisi 6 descriptor (48 bytes total):

Offset | Size | Deskripsi
-------|------|------------------------------------------
00h    | 16   | Descriptor NULL (harus diisi 0)
10h    | 16   | Descriptor GDT sendiri (tidak digunakan di Real Mode)
20h    | 16   | Descriptor Source segment
30h    | 16   | Descriptor Destination segment
40h    | 16   | Descriptor BIOS CS (diisi BIOS)
50h    | 16   | Descriptor BIOS SS (diisi BIOS)

Format Descriptor (8 bytes)

Byte  | Bits   | Field
------|--------|----------------------------------
0-1   | 15-0   | Segment Limit (Low)
2-4   | 23-0   | Base Address (Low 24 bits)
5     | 7-0    | Access Rights
6     | 7-4    | Segment Limit (High 4 bits)
      | 3-0    | Flags
7     | 7-0    | Base Address (High 8 bits)

Contoh Penggunaan: Copy dari Conventional ke Extended Memory

; Memindahkan 32KB dari 0x10000 ke 0x100000 (1MB)

; Setup GDT
gdt:
    ; NULL descriptor (offset 0x00)
    dq 0x0000000000000000
    
    ; GDT descriptor (offset 0x10)
    dq 0x0000000000000000
    
    ; Source descriptor (offset 0x20)
    ; Base = 0x00010000, Limit = 0xFFFF
    dw 0xFFFF                    ; Limit low
    dw 0x0000                    ; Base low
    db 0x01                      ; Base mid
    db 0x93                      ; Access (P=1, DPL=0, S=1, Type=3)
    db 0x00                      ; Limit high + flags
    db 0x00                      ; Base high
    
    ; Destination descriptor (offset 0x30)
    ; Base = 0x00100000, Limit = 0xFFFF
    dw 0xFFFF                    ; Limit low
    dw 0x0000                    ; Base low
    db 0x10                      ; Base mid
    db 0x93                      ; Access
    db 0x00                      ; Limit high + flags
    db 0x00                      ; Base high
    
    ; BIOS CS (offset 0x40) - akan diisi BIOS
    dq 0x0000000000000000
    
    ; BIOS SS (offset 0x50) - akan diisi BIOS
    dq 0x0000000000000000

; Lakukan copy
mov ax, seg gdt
mov es, ax
mov si, gdt                      ; ES:SI -> GDT
mov ah, 87h
mov cx, 16384                    ; 32KB = 32768 bytes = 16384 words
int 15h
jc .copy_error

; Copy berhasil
jmp .continue

.copy_error:
    ; AH berisi error code
    cmp ah, 01h
    je .parity_error
    cmp ah, 02h
    je .exception_error
    cmp ah, 03h
    je .a20_error
    jmp .unknown_error
    
.parity_error:
    ; Handle RAM parity error
    ; ...
    
.exception_error:
    ; Handle exception
    ; ...
    
.a20_error:
    ; Handle A20 gate error
    ; Mungkin perlu enable A20 gate
    ; ...
    
.unknown_error:
    ; Handle unknown error
    ; ...
    
.continue:

Contoh Penggunaan: Helper Macro untuk Mudahkan Setup

; Macro untuk membuat descriptor
%macro DESCRIPTOR 3
    ; %1 = Base address (32-bit)
    ; %2 = Limit (20-bit)
    ; %3 = Access rights byte
    
    dw (%2 & 0xFFFF)                    ; Limit low
    dw (%1 & 0xFFFF)                    ; Base low
    db ((%1 >> 16) & 0xFF)              ; Base mid
    db %3                                ; Access
    db ((%2 >> 16) & 0x0F)              ; Limit high
    db ((%1 >> 24) & 0xFF)              ; Base high
%endmacro

; Penggunaan:
gdt_copy:
    dq 0                                 ; NULL
    dq 0                                 ; GDT
    DESCRIPTOR 0x00010000, 0xFFFF, 0x93  ; Source
    DESCRIPTOR 0x00100000, 0xFFFF, 0x93  ; Dest
    dq 0                                 ; BIOS CS
    dq 0                                 ; BIOS SS

Access Rights Byte (byte ke-5 descriptor)

Bit 7:   P (Present) = 1 (segment present)
Bit 6-5: DPL (Privilege Level) = 00 (ring 0)
Bit 4:   S (Descriptor Type) = 1 (code/data)
Bit 3-0: Type = 0011 (data, read/write, accessed)

Nilai umum: 0x93 = 10010011b

Batasan dan Catatan

⚠️ A20 Gate harus aktif – Jika A20 gate tidak aktif, akses ke memory >1MB akan wrap around

⚠️ Maksimum transfer: 64KB per call (CX = 0xFFFF words = 0x1FFFE bytes)

⚠️ Alignment: Untuk performa optimal, gunakan address yang aligned ke boundary 2-byte

Untuk transfer besar: Gunakan loop dengan multiple calls

; Transfer 128KB (perlu 2 calls @ 64KB)
; Transfer pertama
mov cx, 32768        ; 64KB = 32768 words
; ... setup GDT untuk offset 0 ...
int 15h

; Transfer kedua
; ... update GDT base address +64KB ...
int 15h

Alternatif untuk Protected Mode

Setelah masuk Protected Mode, fungsi ini tidak diperlukan karena:

  • Bisa akses extended memory langsung
  • Paging menyediakan mekanisme lebih fleksibel
  • Tidak perlu BIOS interrupt

AX=E801h – Get Memory Size (Extended Method)

Deskripsi

Mendapatkan ukuran memory sistem yang lebih detail dibanding AH=88h. Fungsi ini dapat mendeteksi memory hingga 4GB dan memberikan breakdown antara memory 1-16MB dan memory di atas 16MB.

Input Parameters

AX = E801h

Output/Return Values

CF = Clear jika sukses
CF = Set jika tidak didukung

Jika sukses:
AX = Extended memory antara 1MB dan 16MB, dalam KB (max 0x3C00 = 15MB)
BX = Extended memory di atas 16MB, dalam 64KB blocks
CX = Configured memory 1MB to 16MB, dalam KB
DX = Configured memory di atas 16MB, dalam 64KB blocks

Notes:
- Beberapa BIOS mengembalikan hasil di AX/BX saja
- Beberapa BIOS mengembalikan hasil di CX/DX saja  
- Beberapa BIOS mengembalikan hasil di keduanya (redundant)
- Untuk kompatibilitas: gunakan CX/DX jika tidak nol, otherwise gunakan AX/BX

Contoh Penggunaan

; Mendapatkan total memory menggunakan E801h
mov ax, 0xE801
int 15h
jc .e801_failed

; Cek mana yang valid: CX/DX atau AX/BX
test cx, cx
jnz .use_cx_dx

; Gunakan AX/BX
mov cx, ax
mov dx, bx

.use_cx_dx:
; CX = KB antara 1MB-16MB
; DX = 64KB blocks di atas 16MB

; Hitung total memory dalam KB
; Total = 1024 (conventional) + CX + (DX * 64)

movzx eax, cx        ; EAX = KB antara 1-16MB
movzx ebx, dx        ; EBX = blocks di atas 16MB
shl ebx, 6           ; EBX = EBX * 64 (convert ke KB)
add eax, ebx         ; EAX = total extended KB
add eax, 1024        ; Tambah 1MB conventional

; EAX sekarang berisi total KB memory
mov [total_memory_kb], eax

; Konversi ke MB untuk display
shr eax, 10          ; EAX = MB
mov [total_memory_mb], eax

jmp .continue

.e801_failed:
    ; Fallback ke metode lain (E820h atau AH=88h)
    ; ...

.continue:

Contoh Kalkulasi

Contoh 1: Sistem 64MB

CX = 0x3C00 (15360 KB = 15 MB antara 1-16MB)
DX = 0x0300 (768 blocks * 64KB = 48MB di atas 16MB)

Total = 1MB + 15MB + 48MB = 64MB

Contoh 2: Sistem 256MB

CX = 0x3C00 (15 MB)
DX = 0x0F00 (3840 blocks * 64KB = 240MB)

Total = 1MB + 15MB + 240MB = 256MB

Contoh 3: Sistem 8MB (memory di bawah 16MB saja)

CX = 0x1C00 (7168 KB = 7 MB)
DX = 0x0000 (tidak ada memory di atas 16MB)

Total = 1MB + 7MB = 8MB

Fungsi Helper untuk Kalkulasi

; Function: calculate_total_memory_e801
; Input: CX = KB (1-16MB), DX = 64KB blocks (>16MB)
; Output: EAX = Total memory dalam KB
calculate_total_memory_e801:
    push ebx
    
    ; Extended memory 1-16MB
    movzx eax, cx
    
    ; Extended memory >16MB
    movzx ebx, dx
    shl ebx, 6           ; Multiply by 64
    
    ; Total extended
    add eax, ebx
    
    ; Tambah conventional (1MB)
    add eax, 1024
    
    pop ebx
    ret

Tabel Hasil Umum

Total RAM | CX (KB)  | DX (blocks) | Perhitungan
----------|----------|-------------|---------------------------
2 MB      | 0x0400   | 0x0000      | 1 + 1 + 0 = 2MB
4 MB      | 0x0C00   | 0x0000      | 1 + 3 + 0 = 4MB
8 MB      | 0x1C00   | 0x0000      | 1 + 7 + 0 = 8MB
16 MB     | 0x3C00   | 0x0000      | 1 + 15 + 0 = 16MB
32 MB     | 0x3C00   | 0x0100      | 1 + 15 + 16 = 32MB
64 MB     | 0x3C00   | 0x0300      | 1 + 15 + 48 = 64MB
128 MB    | 0x3C00   | 0x0700      | 1 + 15 + 112 = 128MB
256 MB    | 0x3C00   | 0x0F00      | 1 + 15 + 240 = 256MB
512 MB    | 0x3C00   | 0x1F00      | 1 + 15 + 496 = 512MB
1 GB      | 0x3C00   | 0x3F00      | 1 + 15 + 1008 = 1GB
2 GB      | 0x3C00   | 0x7F00      | 1 + 15 + 2032 = 2GB
4 GB      | 0x3C00   | 0xFFFF      | 1 + 15 + ~4GB (max)

Perbandingan dengan Metode Lain

MetodeMax MemoryDetailRecommended
AH=88h64MBSingle value❌ Obsolete
AX=E801h4GBTwo values⚠️ OK untuk simple
AX=E820hUnlimitedFull mapBEST

Limitasi

⚠️ Tidak mendeteksi memory holes – Tidak tahu tentang reserved regions

⚠️ Tidak detail – Hanya tahu total, bukan layout

⚠️ Maximum 4GB – Untuk memory >4GB, harus gunakan E820h

Fallback Strategy

; Coba E820 dulu (paling detail)
; Jika gagal, coba E801
; Jika gagal, coba 88h

; Try E820
mov eax, 0xE820
; ... call ...
jnc .got_memory

; Try E801
mov ax, 0xE801
int 15h
jnc .got_memory_e801

; Try 88h
mov ah, 88h
int 15h
jnc .got_memory_88h

; No memory detection available!
jmp .error

.got_memory:
    ; Process E820 map
    ; ...
    jmp .done

.got_memory_e801:
    ; Process E801 values
    ; ...
    jmp .done

.got_memory_88h:
    ; Process 88h value (AX = KB)
    ; ...
    jmp .done

.done:


AX=E820h – Get Memory Map (CRITICAL untuk OS Modern)

Deskripsi

Ini adalah fungsi PALING PENTING untuk bootloader dan kernel modern!

E820h memberikan memory map lengkap sistem, termasuk:

  • Region yang tersedia (usable RAM)
  • Region yang reserved (ROM, MMIO, ACPI)
  • Memory holes
  • ACPI tables
  • Ukuran dan tipe setiap region

Input Parameters

EAX = 0xE820
EBX = Continuation value (0 untuk entry pertama, value dari call sebelumnya untuk next)
ECX = Buffer size (minimum 20 bytes, recommended 24 bytes untuk ACPI 3.0+)
EDX = Signature 'SMAP' (0x534D4150)
ES:DI = Pointer ke buffer untuk menerima entry

Output/Return Values

CF = Clear jika sukses
CF = Set jika end of list atau error

Jika sukses (CF=0):
EAX = Signature 'SMAP' (0x534D4150)
EBX = Continuation value untuk next entry
      (0 jika ini adalah entry terakhir)
ECX = Actual size of entry returned (20 atau 24 bytes)
ES:DI = Entry data written to buffer

Memory Map Entry Structure

Basic Structure (20 bytes)

struct E820Entry {
    uint64_t base;       // Base address (8 bytes)
    uint64_t length;     // Length of region (8 bytes)
    uint32_t type;       // Type of region (4 bytes)
} __attribute__((packed));

Extended Structure (24 bytes) – ACPI 3.0+

struct E820EntryExtended {
    uint64_t base;       // Base address (8 bytes)
    uint64_t length;     // Length of region (8 bytes)
    uint32_t type;       // Type of region (4 bytes)
    uint32_t acpi_ext;   // Extended attributes (4 bytes)
} __attribute__((packed));

Memory Region Types

TypeNamaDeskripsiUsage
1Usable (Available)RAM yang bisa digunakan OSUse this
2ReservedHardware reserved, jangan digunakan❌ Do not use
3ACPI ReclaimableACPI tables, bisa direclaim setelah parsing⚠️ Reclaim after ACPI init
4ACPI NVSACPI Non-Volatile Storage❌ Do not use
5Bad MemoryMemory rusak❌ Never use
12PRAM (Persistent RAM)Persistent memory⚠️ Special handling

ACPI Extended Attributes (bit flags)

Bit 0: Ignore entry jika bit ini clear
Bit 1: Non-volatile (persistent across reboots)
Bits 2-31: Reserved

Contoh Penggunaan Lengkap

; Buffer untuk menyimpan memory map entries
section .bss
memory_map:
    resb 24 * 128       ; Space untuk 128 entries @ 24 bytes
memory_map_count:
    resw 1

section .text
; Function: detect_memory_e820
; Returns: Number of entries dalam memory_map_count
detect_memory_e820:
    push es
    push di
    push ebp
    mov ebp, esp
    
    ; Setup ES:DI untuk buffer
    mov ax, ds
    mov es, ax
    mov di, memory_map
    
    xor ebx, ebx            ; EBX = 0 untuk entry pertama
    xor bp, bp              ; BP = entry counter
    
.loop:
    mov eax, 0xE820         ; Function code
    mov ecx, 24             ; Buffer size (support ACPI 3.0)
    mov edx, 0x534D4150     ; 'SMAP' signature
    int 15h
    
    ; Check error
    jc .failed              ; Carry set = error/end
    
    ; Verify signature
    cmp eax, 0x534D4150
    jne .failed
    
    ; Check if entry is valid (length > 0)
    mov eax, [es:di + 8]    ; Low dword of length
    or eax, [es:di + 12]    ; High dword of length
    jz .skip_entry          ; Skip if length = 0
    
    ; Entry valid, increment counter
    inc bp
    add di, 24              ; Move to next entry
    
.skip_entry:
    ; Check if more entries
    test ebx, ebx
    jz .done                ; EBX = 0 means last entry
    
    ; Check if buffer full
    cmp bp, 128
    jge .done
    
    jmp .loop
    
.done:
    mov [memory_map_count], bp
    clc                     ; Success
    jmp .exit
    
.failed:
    xor bp, bp              ; No entries
    mov [memory_map_count], bp
    stc                     ; Error
    
.exit:
    mov esp, ebp
    pop ebp
    pop di
    pop es
    ret

Contoh Output Memory Map (Real System)

Entry | Base Address      | Length           | Type | Description
------|-------------------|------------------|------|------------------
0     | 0x0000000000000000| 0x000000000009FC00| 1    | Low RAM (639KB)
1     | 0x000000000009FC00| 0x0000000000000400| 2    | Reserved (1KB)
2     | 0x00000000000E0000| 0x0000000000020000| 2    | Reserved (BIOS)
3     | 0x0000000000100000| 0x000000003FEF0000| 1    | Usable (1022MB)
4     | 0x000000003FFF0000| 0x0000000000010000| 3    | ACPI Reclaimable
5     | 0x00000000FFFE0000| 0x0000000000020000| 2    | Reserved (BIOS)

Fungsi Helper: Mencari Largest Usable Region

; Function: find_largest_usable_region
; Returns: EAX:EDX = base address, ECX:EBX = length
find_largest_usable_region:
    push esi
    push edi
    push ebp
    
    xor ecx, ecx            ; Largest length (low)
    xor ebx, ebx            ; Largest length (high)
    xor eax, eax            ; Largest base (low)
    xor edx, edx            ; Largest base (high)
    
    mov si, memory_map
    movzx ebp, word [memory_map_count]
    test ebp, ebp
    jz .done
    
.loop:
    ; Check if type = 1 (usable)
    cmp dword [si + 16], 1
    jne .next
    
    ; Compare length
    mov edi, [si + 12]      ; Length high
    cmp edi, ebx
    jb .next                ; Smaller
    ja .update              ; Larger
    
    mov edi, [si + 8]       ; Length low
    cmp edi, ecx
    jbe .next               ; Smaller or equal
    
.update:
    ; This region is larger
    mov eax, [si + 0]       ; Base low
    mov edx, [si + 4]       ; Base high
    mov ecx, [si + 8]       ; Length low
    mov ebx, [si + 12]      ; Length high
    
.next:
    add si, 24
    dec ebp
    jnz .loop
    
.done:
    pop ebp
    pop edi
    pop esi
    ret

Fungsi Helper: Calculate Total Usable Memory

; Function: calculate_total_usable_memory
; Returns: EDX:EAX = Total usable bytes
calculate_total_usable_memory:
    push esi
    push ebp
    
    xor eax, eax            ; Total low
    xor edx, edx            ; Total high
    
    mov si, memory_map
    movzx ebp, word [memory_map_count]
    test ebp, ebp
    jz .done
    
.loop:
    ; Check if type = 1 (usable)
    cmp dword [si + 16], 1
    jne .next
    
    ; Add length to total
    add eax, [si + 8]       ; Add length low
    adc edx, [si + 12]      ; Add length high with carry
    
.next:
    add si, 24
    dec ebp
    jnz .loop
    
.done:
    pop ebp
    pop esi
    ret

Contoh Display Memory Map

; Function: print_memory_map
print_memory_map:
    push esi
    push ebp
    
    mov si, memory_map
    movzx ebp, word [memory_map_count]
    
    ; Print header
    mov si, msg_header
    call print_string
    
    mov si, memory_map
    xor cx, cx              ; Entry number
    
.loop:
    ; Print entry number
    mov ax, cx
    call print_hex_word
    
    mov al, ':'
    call print_char
    mov al, ' '
    call print_char
    
    ; Print base address (64-bit)
    mov eax, [si + 4]       ; High dword
    call print_hex_dword
    mov eax, [si + 0]       ; Low dword
    call print_hex_dword
    
    mov al, ' '
    call print_char
    
    ; Print length (64-bit)
    mov eax, [si + 12]      ; High dword
    call print_hex_dword
    mov eax, [si + 8]       ; Low dword
    call print_hex_dword
    
    mov al, ' '
    call print_char
    
    ; Print type
    mov eax, [si + 16]
    call print_hex_dword
    
    ; Print type description
    mov eax, [si + 16]
    cmp eax, 1
    je .type_usable
    cmp eax, 2
    je .type_reserved
    cmp eax, 3
    je .type_acpi_reclaim
    cmp eax, 4
    je .type_acpi_nvs
    cmp eax, 5
    je .type_bad
    jmp .type_unknown
    
.type_usable:
    mov si, msg_usable
    jmp .print_type
.type_reserved:
    mov si, msg_reserved
    jmp .print_type
.type_acpi_reclaim:
    mov si, msg_acpi_reclaim
    jmp .print_type
.type_acpi_nvs:
    mov si, msg_acpi_nvs
    jmp .print_type
.type_bad:
    mov si, msg_bad
    jmp .print_type
.type_unknown:
    mov si, msg_unknown
    
.print_type:
    mov al, ' '
    call print_char
    call print_string
    call print_newline
    
    ; Next entry
    add si, 24
    inc cx
    dec ebp
    jnz .loop
    
    pop ebp
    pop esi
    ret

msg_header:        db 'Memory Map:', 13, 10, 0
msg_usable:        db '(Usable)', 0
msg_reserved:      db '(Reserved)', 0
msg_acpi_reclaim:  db '(ACPI Reclaim)', 0
msg_acpi_nvs:      db '(ACPI NVS)', 0
msg_bad:           db '(Bad Memory)', 0
msg_unknown:       db '(Unknown)', 0

Typical Memory Map Layout

0x00000000 - 0x0009FFFF : Usable (640KB - Low Memory)
0x000A0000 - 0x000BFFFF : Reserved (VGA memory)
0x000C0000 - 0x000FFFFF : Reserved (BIOS ROM)
0x00100000 - 0x???????? : Usable (Extended Memory - varies)
0x???????? - 0x???????? : ACPI Reclaimable
0xFFFE0000 - 0xFFFFFFFF : Reserved (BIOS)

Best Practices

ALWAYS use E820h untuk OS modern – ini adalah standard de-facto

Check ECX return – Beberapa BIOS return 20, beberapa 24 bytes

Validate entries – Skip entries dengan length = 0

Handle extended attributes – Untuk ACPI 3.0+ systems

Save map early – Collect sebelum masuk Protected Mode

⚠️ Sort entries – Beberapa BIOS tidak return entries dalam urutan ascending

⚠️ Merge contiguous regions – Optimize memory management

Error Handling

; Fallback jika E820h gagal
call detect_memory_e820
jnc .e820_success

; E820 failed, try E801
mov ax, 0xE801
int 15h
jnc .e801_success

; E801 failed, try 88h
mov ah, 88h
int 15h
jnc .88h_success

; All methods failed!
; Assume minimal memory atau halt
jmp error_no_memory

.e820_success:
    ; Use E820 map (best)
    ; ...
    jmp continue

.e801_success:
    ; Convert E801 to simple map
    ; ...
    jmp continue

.88h_success:
    ; Convert 88h to simple map
    ; ...
    jmp continue

continue:
    ; Proceed with detected memory


AH=C0h – Get System Configuration

Deskripsi

Mendapatkan pointer ke system configuration table yang berisi informasi hardware dan capabilities sistem. Table ini sangat berguna untuk mendeteksi fitur-fitur yang tersedia.

Input Parameters

AH = C0h

Output/Return Values

CF = Clear jika sukses
CF = Set jika tidak didukung

Jika sukses:
ES:BX = Pointer ke ROM system configuration table
AH = 00h (success)

Jika gagal:
AH = 80h (Invalid command)
AH = 86h (Function not supported)

System Configuration Table Structure

struct SystemConfigTable {
    uint16_t length;         // Length of table (bytes) - typically 8 or 9
    uint8_t  model;          // Model byte
    uint8_t  submodel;       // Submodel byte
    uint8_t  bios_revision;  // BIOS revision level
    uint8_t  feature1;       // Feature byte 1
    uint8_t  feature2;       // Feature byte 2
    uint8_t  feature3;       // Feature byte 3
    uint8_t  feature4;       // Feature byte 4
    uint8_t  feature5;       // Feature byte 5
} __attribute__((packed));

Feature Byte 1 (offset 5)

Bit 7: DMA channel 3 used by hard disk BIOS
Bit 6: Second interrupt controller (slave 8259) installed
Bit 5: Real-Time Clock installed
Bit 4: Keyboard intercept (INT 15h/AH=4Fh) called by INT 09h
Bit 3: Wait for external event supported (INT 15h/AH=83h, 86h)
Bit 2: Extended BIOS data area allocated
Bit 1: Micro Channel implemented
Bit 0: Reserved

Feature Byte 2 (offset 6)

Bit 7: Reserved
Bit 6: Reserved  
Bit 5: Reserved
Bit 4: POST supports system information from CMOS
Bit 3: Reserved
Bit 2: Reserved
Bit 1: Reserved
Bit 0: Reserved

Model Byte Values (Common Systems)

0xFC - AT (PC/AT)
0xF8 - PS/2 Model 80
0xF9 - Convertible
0xFA - PS/2 Model 30
0xFB - PS/2 Model 25 or 30
0xFE - XT
0xFF - PC

Contoh Penggunaan

; Get system configuration
mov ah, 0xC0
int 15h
jc .not_supported

; ES:BX now points to configuration table
; Read table length
mov cx, [es:bx]         ; CX = table length

; Read model
mov al, [es:bx+2]       ; AL = model byte
mov [system_model], al

; Read submodel
mov al, [es:bx+3]       ; AL = submodel
mov [system_submodel], al

; Read BIOS revision
mov al, [es:bx+4]       ; AL = BIOS revision
mov [bios_revision], al

; Check feature byte 1
mov al, [es:bx+5]
test al, 0x20           ; Bit 5: RTC installed?
jz .no_rtc
    ; RTC is installed
    mov byte [has_rtc], 1
    
.no_rtc:
    test al, 0x40       ; Bit 6: Slave PIC?
    jz .no_slave_pic
    ; Slave PIC installed
    mov byte [has_slave_pic], 1

.no_slave_pic:
    test al, 0x10       ; Bit 4: Keyboard intercept?
    jz .no_kbd_intercept
    ; Keyboard intercept supported
    mov byte [has_kbd_intercept], 1

.no_kbd_intercept:
    jmp .continue

.not_supported:
    ; Function not supported
    ; Assume default configuration
    ; ...

.continue:

Fungsi Helper: Print System Info

print_system_config:
    push es
    push bx
    
    mov ah, 0xC0
    int 15h
    jc .error
    
    ; Print model
    mov si, msg_model
    call print_string
    mov al, [es:bx+2]
    call print_hex_byte
    call print_newline
    
    ; Print submodel
    mov si, msg_submodel
    call print_string
    mov al, [es:bx+3]
    call print_hex_byte
    call print_newline
    
    ; Print BIOS revision
    mov si, msg_revision
    call print_string
    mov al, [es:bx+4]
    call print_hex_byte
    call print_newline
    
    ; Print features
    mov si, msg_features
    call print_string
    
    mov al, [es:bx+5]       ; Feature byte 1
    
    test al, 0x20
    jz .no_rtc_print
    mov si, msg_rtc
    call print_string
.no_rtc_print:
    
    test al, 0x40
    jz .no_pic_print
    mov si, msg_pic
    call print_string
.no_pic_print:
    
    test al, 0x04
    jz .no_ebda_print
    mov si, msg_ebda
    call print_string
.no_ebda_print:
    
    call print_newline
    jmp .done
    
.error:
    mov si, msg_not_supported
    call print_string
    
.done:
    pop bx
    pop es
    ret

msg_model:          db 'Model: ', 0
msg_submodel:       db 'Submodel: ', 0
msg_revision:       db 'BIOS Revision: ', 0
msg_features:       db 'Features: ', 0
msg_rtc:            db 'RTC ', 0
msg_pic:            db 'PIC ', 0
msg_ebda:           db 'EBDA ', 0
msg_not_supported:  db 'System config not supported', 13, 10, 0

Contoh Detection Flow

; Comprehensive system detection
detect_system_features:
    ; 1. Get system configuration
    mov ah, 0xC0
    int 15h
    jc .no_config
    
    ; Save feature flags
    mov al, [es:bx+5]
    mov [feature_flags], al
    
    ; 2. Check for slave PIC
    test al, 0x40
    jz .single_pic
    
    ; Dual PIC system (IRQ 0-15)
    mov byte [max_irq], 15
    jmp .pic_done
    
.single_pic:
    ; Single PIC (IRQ 0-7)
    mov byte [max_irq], 7
    
.pic_done:
    ; 3. Check for RTC
    test byte [feature_flags], 0x20
    jz .no_rtc
    mov byte [has_rtc], 1
    
.no_rtc:
    ; 4. Check for EBDA
    test byte [feature_flags], 0x04
    jz .no_ebda
    
    ; Get EBDA segment
    mov ah, 0xC1
    int 15h
    jc .no_ebda
    mov [ebda_segment], es
    
.no_ebda:
    clc
    ret

.no_config:
    ; Assume defaults for old systems
    mov byte [max_irq], 7
    mov byte [has_rtc], 0
    mov word [ebda_segment], 0
    stc
    ret


AH=C1h – Get Extended BIOS Data Area (EBDA)

Deskripsi

Mendapatkan segment address dari Extended BIOS Data Area (EBDA). EBDA adalah area memori yang digunakan BIOS untuk menyimpan data runtime tambahan.

Input Parameters

AH = C1h

Output/Return Values

CF = Clear jika sukses
ES = EBDA segment address

CF = Set jika error atau tidak didukung

EBDA Information

Location

  • Typical address: 0x9FC00 – 0x9FFFF (di bawah 640KB boundary)
  • Size: Bervariasi, typically 1KB – 4KB
  • Detection alternative: Segment address juga tersimpan di 0x0040:0x000E

Contents

EBDA biasanya berisi:

  1. PS/2 mouse data
  2. Additional disk parameter tables
  3. PCI BIOS data structures
  4. ACPI tables (pointer)
  5. Extended keyboard buffer
  6. Manufacturing test data

Contoh Penggunaan

; Method 1: Using INT 15h, AH=C1h
get_ebda_int15:
    mov ah, 0xC1
    int 15h
    jc .not_supported
    
    ; ES = EBDA segment
    mov [ebda_segment], es
    clc
    ret

.not_supported:
    xor ax, ax
    mov [ebda_segment], ax
    stc
    ret

; Method 2: Reading from BDA (More compatible)
get_ebda_from_bda:
    push es
    
    ; BDA segment
    mov ax, 0x0040
    mov es, ax
    
    ; EBDA segment stored at 0x0040:0x000E
    mov ax, [es:0x000E]
    mov [ebda_segment], ax
    
    pop es
    ret

; Method 3: Calculate from memory size
get_ebda_from_memsize:
    ; Get base memory size (INT 12h)
    int 12h                 ; AX = KB
    
    ; Convert to segment (KB * 1024 / 16)
    mov cl, 6
    shl ax, cl              ; AX = segment
    
    mov [ebda_segment], ax
    ret

Validating EBDA

; Validate EBDA segment
validate_ebda:
    mov ax, [ebda_segment]
    
    ; Check if valid (should be below A000h and above 8000h typically)
    cmp ax, 0xA000
    jae .invalid
    
    cmp ax, 0x8000
    jb .invalid
    
    ; Valid
    clc
    ret

.invalid:
    stc
    ret

Reading EBDA Data

; Example: Find PS/2 mouse data in EBDA
find_ps2_mouse_data:
    push es
    
    mov ax, [ebda_segment]
    test ax, ax
    jz .not_found
    
    mov es, ax
    
    ; First word of EBDA usually contains EBDA size in KB
    mov cx, [es:0]
    
    ; PS/2 mouse data typically at offset varies
    ; Need to scan or know specific offset
    ; This is system-specific
    
    ; ...
    
    pop es
    clc
    ret

.not_found:
    pop es
    stc
    ret

EBDA Size Detection

; Get EBDA size
get_ebda_size:
    push es
    
    mov ax, [ebda_segment]
    test ax, ax
    jz .no_ebda
    
    mov es, ax
    
    ; First word = size in KB
    movzx ax, byte [es:0]   ; Some BIOS use byte, some use word
    
    ; Convert to bytes
    mov bx, 1024
    mul bx                  ; DX:AX = size in bytes
    
    pop es
    ret

.no_ebda:
    xor ax, ax
    xor dx, dx
    pop es
    ret

Complete EBDA Detection

; Comprehensive EBDA detection
detect_ebda:
    push es
    
    ; Try method 1: INT 15h, C1h
    mov ah, 0xC1
    int 15h
    jnc .got_ebda
    
    ; Try method 2: From BDA
    mov ax, 0x0040
    mov es, ax
    mov ax, [es:0x000E]
    test ax, ax
    jnz .got_ebda_from_bda
    
    ; Try method 3: Calculate from memory
    int 12h                 ; Get memory size
    mov cl, 6
    shl ax, cl
    
.got_ebda_from_bda:
    mov es, ax

.got_ebda:
    ; Validate
    mov ax, es
    cmp ax, 0x8000
    jb .invalid
    cmp ax, 0xA000
    jae .invalid
    
    ; Store
    mov [ebda_segment], ax
    
    ; Get size
    movzx ax, byte [es:0]
    mov [ebda_size_kb], ax
    
    pop es
    clc
    ret

.invalid:
    xor ax, ax
    mov [ebda_segment], ax
    mov [ebda_size_kb], ax
    pop es
    stc
    ret

Important Notes

⚠️ EBDA location varies – Always detect, never assume fixed address

⚠️ Size varies – From 1KB to several KB depending on BIOS

⚠️ OS should relocate – Before using memory, OS should move/reclaim EBDA if needed

Use for: Detecting additional hardware info, PS/2 mouse, etc.


APM (Advanced Power Management) – AX=53xxh Series

Deskripsi Umum

APM adalah interface untuk manajemen daya sistem sebelum era ACPI. Masih digunakan pada sistem lama dan sebagai fallback pada beberapa sistem modern.

APM Version History

  • APM 1.0: Basic power management
  • APM 1.1: Improved CPU idle
  • APM 1.2: Additional power states

Catatan

⚠️ Deprecated – Sistem modern menggunakan ACPI, tapi APM masih berguna untuk:

  • Legacy systems
  • Embedded systems
  • Fallback mechanism