You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

x86 BIOS启动加载器中LBA转CHS函数在LBA>65时失效问题排查

问题:x86 BIOS启动加载器LBA转CHS函数的溢出问题

我正在开发一款x86 BIOS启动加载器,第一阶段启动加载器(MBR)需要从磁盘读取2880个或更多扇区,随后跳转到位于磁盘第二个扇区的第二阶段启动加载器。第二阶段将通过FAT16加载内核文件,该部分我会后续实现。

目前LBA转CHS函数仅对小于65的LBA值有效,此范围足以加载用C语言编写的第二阶段。我已定义BPB_SecPerTrk为18,BPB_NumHeads为2。

以下是LBA转CHS转换函数的汇编代码:

; convert LBA to CHS
; input: si = LBA
; output: ch = cylinder, dh = head, cl = sector
lba_to_chs:
    push bx                         ; save bx
    mov ax, si                      ; load LBA address into ax

    ; Calculate sectors (CL)
    xor dx, dx                      ; clear dx
    div word [BPB_SecPerTrk]        ; ax = LBA / SPT, dx = LBA % SPT
    mov cl, dl                      ; cl = (LBA % SPT) + 1 (sector)
    inc cl                          ; increment cl by 1

    ; Calculate head (DH)
    xor dx, dx                      ; clear dx
    div word [BPB_NumHeads]         ; ax = LBA / (SPT * NumHeads), dx = (LBA / SPT) % NumHeads
    mov dh, dl                      ; dh = (LBA / SPT) % NumHeads (head)

    ; Calculate cylinder (CH)
    mov ch, al                      ; ch = ax (cylinder number, lower 8 bits)
    mov al, ah                      ; al = ah (upper 8 bits of cylinder number)
    shl al, 6                       ; shift upper 2 bits of cylinder to higher bits
    or ch, al                       ; combine them with lower 8 bits of ch

    pop bx                          ; restore bx
    ret

以及磁盘初始化函数代码:

disk_init_lba:
    pusha
    ; check if lba extension is supperted
    mov ah, 0x41                    ; check extensions
    mov bx, 0x55AA                  ; magic number
    mov dl, 0x80                    ; disk number
    int 0x13                        ; call BIOS
    stc                             ; DEBUG: implicitly disable reading disk using int 0x13 extensions
    jc .lba_ext_not_sup             ; if carry flag flag is set, jump to error handler
    jmp .read_lba_ext               ; if not, jump to read disk using LBA
.read_lba_ext:
    mov si, DAPACK                  ; load DAP address to si
    mov ah, 0x42                    ; extended read function
    mov dl, 0x80                    ; disk number
    int 0x13                        ; call BIOS
    jc .fail                        ; if carry flag is set, jump to error handler
    jmp .ok                         ; if not, jump to success handler
.lba_ext_not_sup:
    call print_disk_lba_sup_fail    ; print failure message
    jmp .read_lba_via_chs           ; jump to read disk using CHS
.read_lba_via_chs:
    clc                             ; clear carry flag if for some reason it was set
    xor si, si                      ; LBA = 0
    xor di, di                      ; set di to 0
    mov bx, START_STAGE1            ; buffer for sector
    jmp .loop                       ; jump to loop
.loop:
    inc si                          ; increment LBA
    add bx, 0x200                   ; next sector buffer
    call lba_to_chs                 ; convert LBA to CHS
    mov ah, 0x02                    ; read disk BIOS function
    mov al, 0x01                    ; number of sectors to read
    mov dl, 0x80                    ; disk number 0
    int 0x13                        ; call BIOS
    jc .retry                       ; if carry flag is set, jump to error handler
    ; FIXME: reading LBAs above 65
    ; TODO: read up to 1.44 MB (2879 sectors)
    cmp si, 65                      ; check if we read enough sectors to fill 1.44 MB
    jle .loop                       ; if true read next sector
    jmp .ok                         ; if not, jump to success handler
.retry:
    inc di                          ; increment di
    cmp di, 3                       ; check if we tried 3 times
    jne .loop                       ; if not, retry
    jmp .fail                       ; if yes, jump to error handler
.fail:
    call print_disk_read_fail       ; print failure message
    jmp .exit                       ; jump to exit
.ok:
    call print_disk_read_ok         ; print success message
    jmp .exit                       ; jump to exit
.exit:
    popa
    ret

我怀疑问题源于代码中的值溢出。


内容的提问来源于stack exchange,提问作者mtrzc0

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 17:20:59