Penulis: Reza Ervani bin Asmanu
1. Pendahuluan
Perbedaan paling radikal antara pengembangan Legacy Bootloader dan UEFI Application terletak pada mekanisme komunikasi antara perangkat lunak (Software) dan perangkat keras (Firmware).
Pada BIOS, komunikasi bersifat Imperatif dan Terpusat melalui Interrupt Vector Table (IVT). Pada UEFI, komunikasi bersifat Deklaratif dan Terdesentralisasi melalui Function Pointer Tables di Heap Memory. Artikel ini membedah implikasi register, stack, dan instruksi mesin dari kedua pendekatan tersebut.
2. BIOS: Arsitektur Berbasis Interupsi (Software Interrupt Architecture)
Dalam mode BIOS Real Mode, CPU menggunakan tabel di alamat fisik 0x0000 hingga 0x03FF (1 KB pertama RAM) yang berisi 256 alamat fungsi (ISR – Interrupt Service Routines).
2.1. Mekanisme Instruksi INT
Instruksi INT n (opcode CD imm8) bukan sekadar lompatan (JUMP). Ia adalah operasi kompleks yang melibatkan manipulasi stack otomatis oleh CPU:
- Push Flags: CPU menyimpan register FLAGS ke stack.
- Disable Interrupts: CPU mematikan Interrupt Flag (IF) (cli).
- Push CS:IP: CPU menyimpan alamat kembali (Return Address) ke stack.
- Vector Lookup: CPU membaca alamat handler dari
IVT[n]. - Jump: CPU melompat ke kode BIOS.
2.2. Rigid Register Mapping (Kekakuan Register)
BIOS tidak memiliki standar ABI (Application Binary Interface) yang seragam antar vendor, namun memiliki konvensi de-facto IBM PC. Register memiliki peran semantik yang kaku:
AH(Accumulator High): Selalu berfungsi sebagai Function Selector (ID Perintah).AL(Accumulator Low): Biasanya untuk sub-fungsi atau jumlah elemen.DL(Data Low): De-facto standar untuk ID Drive (misal0x80untuk HDD).Carry Flag (CF): Indikator status. JikaCF=1, operasi gagal.
2.3. Studi Kasus Forensik: Low-Level Disk Read (BIOS)
Operasi membaca sektor disk menuntut penggunaan register segmen yang rumit.
; --- BIOS DISK READ (INT 13h, AH=02h) ---
; Target: Baca 1 sektor ke alamat memori 0x07C0:0x0000
MOV AX, 0x07C0
MOV ES, AX ; ES (Extra Segment) diisi segmen tujuan
XOR BX, BX ; BX (Offset) diisi 0. Alamat fisik = 0x07C00
MOV AH, 0x02 ; FUNCTION ID: Read Sectors
MOV AL, 0x01 ; Sektor count = 1
MOV CH, 0x00 ; Cylinder = 0
MOV CL, 0x02 ; Sector = 2 (Sector 1 is MBR)
MOV DH, 0x00 ; Head = 0
MOV DL, 0x80 ; Drive = First Hard Disk
INT 0x13 ; TRAP: Transfer kontrol ke BIOS ROM
JC DiskError ; Cek Carry Flag (CF). Jump if Carry Set.
Analisis Register: Register digunakan sebagai wadah nilai mentah. Tidak ada pointer ke struktur data yang kompleks. Semuanya hardcoded dalam register 16-bit.
3. UEFI: Arsitektur Berbasis Protokol (Interface Protocol Architecture)
UEFI membuang konsep Interupsi Software untuk layanan sistem. Sebagai gantinya, ia mengadopsi model C Object Oriented. Layanan tidak disimpan di lokasi memori tetap (seperti IVT 0x0000), melainkan dialokasikan secara dinamis saat boot.
3.1. Microsoft x64 Calling Convention (ABI)
UEFI secara ketat mengikuti standar ABI Microsoft x64. Ini mengubah total cara register digunakan. Register tidak lagi memiliki arti semantik (seperti “AH adalah ID Fungsi”), melainkan memiliki arti Posisional.
Aturan Volatile Register (Caller-Saved):
Register ini dianggap “rusak” setelah pemanggilan fungsi UEFI. Nilainya tidak dijamin sama saat kembali.
RAX,RCX,RDX,R8,R9,R10,R11,XMM0-XMM5.
Aturan Non-Volatile Register (Callee-Saved):
Fungsi UEFI wajib menjaga nilai register ini.
RBX,RBP,RDI,RSI,R12-R15.
3.2. Struktur Pemanggilan (Indirect Call)
Layanan UEFI dipanggil melalui Pointer to Function yang ada di dalam struktur data (biasanya SystemTable).
- Pointer
SystemTablebiasanya diserahkan keRCX(Argumen 1) atau disimpan di variabel global.
3.3. Studi Kasus Forensik: Low-Level Disk Read (UEFI)
Berbeda dengan BIOS yang pakai register CHS (Cylinder-Head-Sector), UEFI menggunakan protokol EFI_BLOCK_IO_PROTOCOL dan struktur data linear.
Mari kita lihat terjemahan Assembly murni dari pemanggilan fungsi BlockIo->ReadBlocks(...):
; --- UEFI DISK READ (BlockIo Protocol) ---
; C Prototype: ReadBlocks(BlockIo, MediaId, LBA, Size, Buffer)
; 1. Persiapan Stack Frame (Wajib untuk Shadow Space)
SUB RSP, 32 ; Alokasi 32 bytes Shadow Space (Microsoft ABI Requirement)
AND RSP, 0xFFFFFFF0 ; Stack Alignment 16-byte (Agar tidak crash di instruksi SSE)
; 2. Persiapan Argumen (Positional Register Mapping)
; Arg 5 (Buffer) - Masuk ke Stack (karena register habis)
MOV RAX, [BufferPtr] ; Ambil alamat buffer tujuan
MOV [RSP + 32], RAX ; Taruh di stack, tepat di atas shadow space
; Arg 4 (Size) -> Register R9
MOV R9, 512 ; Ukuran 512 bytes
; Arg 3 (LBA/Offset) -> Register R8
MOV R8, 1 ; Baca LBA 1 (Sektor ke-2)
; Arg 2 (Media ID) -> Register RDX
MOV RDX, [MediaId] ; ID Media dari struktur BlockIo
; Arg 1 (This Pointer) -> Register RCX
MOV RCX, [BlockIo] ; Pointer ke Object BlockIo itu sendiri (Context)
; 3. Eksekusi Call (Indirect Call)
; Kita harus mencari alamat fungsi ReadBlocks di dalam tabel vtable BlockIo
MOV RAX, [RCX] ; Dereference pointer BlockIo untuk dapat alamat VTable
CALL [RAX + 0x20] ; Panggil fungsi di offset 0x20 (Offset fungsi ReadBlocks)
; 4. Cek Hasil
ADD RSP, 32 ; Bersihkan stack
TEST RAX, RAX ; Cek return value di RAX (EFI_STATUS)
JNZ DiskError ; Jika RAX != 0 (EFI_SUCCESS), maka Error.
4. Analisis Komparatif Mendalam
Berikut adalah tabel matriks perbedaan pada level instruksi mesin (opcode level):
| Titik Analisis | BIOS (16-bit Assembly) | UEFI (64-bit Assembly) |
| Metode Dispatch | INT 0x13 (Software Interrupt Trap) | CALL [RAX+Offset] (Indirect Memory Call) |
| Penyimpanan Argumen | Semantic Registers (AH=Func, CX=Cyl). Register ditentukan oleh fungsi. | Positional Registers (RCX=Arg1, RDX=Arg2). Register ditentukan oleh urutan. |
| Passing Buffer | Segmented Pointer (ES:BX). Terbatas 1MB. Harus hitung (ES<<4)+BX. | Linear Pointer (64-bit Flat). Bisa alamat 0x0000000800000000 (RAM 32GB+). |
| Stack Management | Tidak wajib (kecuali push/pop data sendiri). | Wajib. Harus alokasi Shadow Space (32 byte) dan Alignment (16 byte). |
| Error Reporting | Carry Flag (Hardware Flag). 1 bit informasi. | RAX (EFI_STATUS). 64-bit kode error (bisa membedakan DeviceError, NoMedia, dll). |
| Konteks | Stateless. BIOS tidak tahu siapa yang memanggil. | Stateful. RCX (This Pointer) membawa konteks objek driver tertentu. |
5. Implikasi bagi Pengembang OS (Relevansi Nyata)
- Debugging Complexity:
- Di BIOS, jika disk gagal baca, Anda cukup lihat register
AH. - Di UEFI, jika disk gagal baca, Anda harus memeriksa Stack Trace dan isi struktur
EFI_SYSTEM_TABLEdi memori. Debugging UEFI membutuhkan pemahaman tentang memory dump, bukan hanya register dump.
- Di BIOS, jika disk gagal baca, Anda cukup lihat register
- Stack Safety:
- Di BIOS, Anda bisa sembarangan memanipulasi
SP(Stack Pointer). - Di UEFI, jika Anda lupa
SUB RSP, 32sebelum memanggil fungsi, firmware akan menimpa data stack Anda atau crash karena pelanggaran memori. Ini adalah sumber bug #1 bagi pemula UEFI Assembly.
- Di BIOS, Anda bisa sembarangan memanipulasi
- Portabilitas:
- Kode Assembly BIOS hanya jalan di x86.
- Kode C UEFI (yang dikompilasi ke pola register di atas) bisa di-recompile untuk ARM64 (Raspberry Pi) atau RISC-V dengan mudah, karena abstraksi protokolnya sama, hanya Calling Convention-nya yang berubah.
Bersambung ke Bagian 3: Akses Grafik (VGA Mode 0x13 vs GOP Linear Framebuffer).
