Phân Tích Mã Nguồn Bộ Khởi Động Hệ Điều Hành 64-bit

Giới thiệu

Để hiểu rõ cơ chế hoạt động của bộ khởi động (boot sector), chúng ta cần nắm vững quy trình khởi động từ BIOS. Khi máy tính được bật nguồn, BIOS sẽ thực hiện kiểm tra phần cứng, sau đó đọc boot sector (512 byte) từ thiết bị khởi động và nạp nó vào địa chỉ bộ nhớ 0x7C00. Nhiệm vụ chính của đoạn mã này là tìm và tải kernel vào bộ nhớ, sau đó chuyển quyền điều khiển cho hệ điều hành.

Cấu trúc chương trình

Chương trình boot sector được chia thành các phần chính sau:

  1. Thiết lập môi trường ban đầu (thanh ghi, stack, xóa màn hình)
  2. Đặt lại đĩa mềm và chuẩn bị thao tác đọc
  3. Duyệt qua thư mục gốc để tìm file kernel
  4. Nếu tìm thấy, tải nội dung file theo cấu trúc FAT12
  5. Nhảy đến điểm nhập của kernel
  6. Nếu không tìm thấy, hiển thị thông báo lỗi và dừng

Chi tiết từng phần

1. Định nghĩa các hằng số và tham số

org 0x7c00

; Tham số hệ thống file FAT12 cho đĩa mềm 1.44MB
STACK_ADDR equ 0x7c00
KERNEL_SEG equ 0x1000
KERNEL_OFF equ 0x00
ROOT_SECTS equ 14
ROOT_START equ 19
FAT1_START equ 1
SECTOR_OFFSET equ 17

Các tham số trên xác định cấu trúc của đĩa mềm 1.44MB theo chuẩn FAT12, bao gồm vị trí của bảng FAT, thư mục gốc và các thông số khác.

2. Khởi tạo môi trường

init_environment:
    mov ax, cs
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov sp, STACK_ADDR

    ; Xóa màn hình bằng BIOS interrupt 10h/06h
    mov ax, 0600h
    mov bx, 0700h
    mov cx, 0
    mov dx, 0184Fh
    int 10h

    ; Đặt con trỏ tại vị trí (0,0)
    mov ax, 0200h
    mov bx, 0000h
    mov dx, 0000h
    int 10h

    ; Hiển thị thông báo khởi động
    mov ax, 1301h
    mov bx, 000Fh
    mov dx, 0000h
    mov cx, msg_len
    push ax
    mov ax, ds
    mov es, ax
    pop ax
    mov bp, boot_msg
    int 10h

Đoạn mã này thiết lập các thanh ghi đoạn, khởi tạo stack, xóa màn hình và hiển thị thông báo khởi động cho người dùng.

3. Đặt lại đĩa mềm

reset_disk:
    xor ah, ah
    xor dl, dl
    int 13h

Việc reset đĩa là cần thiết để đảm bảo đĩa ở trạng thái sẵn sàng cho các thao tác đọc tiếp theo.

4. Tìm kiếm file kernel trong thư mục gốc

search_kernel:
    mov word [remaining_sectors], ROOT_SECTS
    mov word [current_sector], ROOT_START

next_root_sector:
    cmp word [remaining_sectors], 0
    jz not_found

    dec word [remaining_sectors]

    ; Đọc một sector của thư mục gốc vào địa chỉ 0x8000
    mov ax, 00h
    mov es, ax
    mov bx, 8000h
    mov ax, [current_sector]
    mov cl, 1
    call read_sector

    ; So sánh tên file
    mov si, kernel_name
    mov di, 8000h
    cld
    mov dx, 11

compare_loop:
    cmp dx, 0
    jz found_kernel
    dec dx
    mov cx, 11

char_compare:
    cmp cx, 0
    jz next_entry
    dec cx
    lodsb
    cmp al, byte [es:di]
    jz char_equal
    jmp next_entry

char_equal:
    inc di
    jmp char_compare

next_entry:
    and di, 0FFE0h
    add di, 20h
    mov si, kernel_name
    jmp compare_loop

found_kernel:
    ; Xử lý khi tìm thấy file
    mov ax, ROOT_SECTS
    and di, 0FFE0h
    add di, 01Ah
    mov cx, word [es:di]
    push cx
    ; Tiếp tục tải file...
    jmp load_kernel

not_found:
    ; Hiển thị thông báo lỗi
    mov ax, 1301h
    mov bx, 008Ch
    mov dx, 0100h
    mov cx, err_len
    push ax
    mov ax, ds
    mov es, ax
    pop ax
    mov bp, error_msg
    int 10h
    jmp $

Quá trình tìm kiếm duyệt qua từng entry trong thư mục gốc (mỗi entry 32 byte), so sánh từng ký tự của tên file. Thư mục gốc lưu trữ thông tin về tất cả các file bao gồm tên, phần mở rộng, cluster bắt đầu và kích thước.

5. Tải file kernel vào bộ nhớ

load_kernel:
    mov ax, KERNEL_SEG
    mov es, ax
    mov bx, KERNEL_OFF

load_loop:
    push ax
    push bx

    ; Hiển thị dấu chấm để báo tiến trình
    mov ah, 0Eh
    mov al, '.'
    mov bl, 0Fh
    int 10h

    pop bx
    pop ax

    ; Đọc một cluster
    mov cl, 1
    call read_sector

    ; Lấy cluster tiếp theo từ bảng FAT
    call get_fat_entry
    cmp ax, 0FFFh
    jz done_loading

    push ax
    mov dx, ROOT_SECTS
    add ax, dx
    add ax, SECTOR_OFFSET
    add bx, 512
    jmp load_loop

done_loading:
    jmp KERNEL_SEG:KERNEL_OFF

Cơ chế tải file dựa trên chuỗi các cluster: mỗi cluster chứa một sector, bảng FAT lưu trữ cluster tiếp theo của file. Khi gặp giá trị 0FFFh, có nghĩa là đã đến cuối chuỗi cluster.

6. Hàm đọc một sector (LBA sang CHS)

read_sector:
    push bp
    mov bp, sp
    sub esp, 2
    mov byte [bp-2], cl
    push bx

    ; Chuyển đổi LBA sang CHS
    mov bl, 18
    div bl
    inc ah
    mov cl, ah
    mov dh, al
    shr al, 1
    mov ch, al
    pop bx
    mov dl, [drive_number]

retry_read:
    mov ah, 2
    mov al, byte [bp-2]
    int 13h
    jc retry_read
    add esp, 2
    pop bp
    ret

BIOS sử dụng địa chỉ CHS (Cylinder-Head-Sector) thay vì LBA (Logical Block Addressing). Hàm này thực hiện phép chuyển đổi dựa trên tham số của đĩa mềm (18 sector/track, 2 head).

7. Hàm lấy giá trị từ bảng FAT

get_fat_entry:
    push es
    push bx
    push ax

    mov ax, 00h
    mov es, ax
    pop ax
    mov byte [is_odd], 0

    ; Tính toán vị trí trong bảng FAT
    mov bx, 3
    mul bx
    mov bx, 2
    div bx
    mov bx, 8000h
    add ax, FAT1_START
    mov cl, 1
    mul cx
    pop dx
    add bx, dx
    mov ax, [es:bx]

    ; Xử lý trường hợp cluster chẵn/lẻ
    cmp byte [is_odd], 1
    jnz even_cluster
    shr ax, 4

even_cluster:
    and ax, 0FFFh
    pop bx
    pop es
    ret

FAT12 sử dụng 12 bit (1.5 byte) cho mỗi entry. Với cluster chẵn, lấy 12 bit thấp; với cluster lẻ, lấy 12 bit cao bằng cách dịch phải 4 bit.

8. Định nghĩa biến và chuỗi

remaining_sectors dw ROOT_SECTS
current_sector dw 0
is_odd db 0

boot_msg db "Start Boot"
msg_len equ $ - boot_msg
error_msg db "ERROR:No KERNEL Found"
err_len equ $ - error_msg
kernel_name db "KERNEL  BIN",0

9. Boot signature

times 510 - ($ - $$) db 0
dw 0xAA55

Hai byte cuối cùng của boot sector phải là 0xAA55 để BIOS nhận diện đây là sector khởi động hợp lệ.

Tổng kết

Việc nắm vững nguyên lý hoạt động của boot sector là nền tảng quan trọng cho việc phát triển hệ điều hành. Dù công nghệ phần cứng ngày càng phát triển (UEFI, NVMe), nhưng các khái niệm cốt lõi như khởi tạo, tìm kiếm file, và chuyển giao quyền điều khiển vẫn giữ nguyên giá trị.

Tài liệu tham khảo:

  • FAT12 Filesystem Specification (Microsoft)
  • BIOS Interrupt Reference
  • Assembly Language Programming

Thẻ: assembly bios boot-sector fat12 operating-system

Đăng vào ngày 1 tháng 6 lúc 13:44