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

自制操作系统开发:执行int 13h指令时程序卡顿的问题求助

解决int 13h执行卡顿的问题

我之前在写自制OS的bootloader时也踩过int 13h的坑,结合你的代码和调试信息,大概率是几个关键错误导致的,咱们一步步分析:

最紧急的错误:栈帧初始化笔误

看你的ReadOneSector函数开头:

push bp
mov sp, sp  ; 这里明显写错了!
sub esp, 2

push bp之后,正确的操作应该是mov bp, sp,用来把栈基指针指向当前栈顶,这样后续访问[bp-2]才是正确的局部变量地址。你写成mov sp, sp等于啥也没做,bp还是之前的随机值,导致byte [bp-2]取到的是垃圾数据——这直接让int 13h的al参数(要读取的扇区数)错误,比如变成0,必然导致读盘失败,然后触发jc Label_Go_Reading无限重试,看起来就是“卡顿”。

先改这个:把mov sp, sp改成mov bp, sp。

其他可能导致int 13h失败的原因

即使修复了栈帧,还有几个常见坑需要排查:

1. CHS地址计算逻辑有问题

你的扇区计算代码假设磁盘磁头数是2(用shr al,1和and dh,1),但如果你的磁盘镜像的BPB参数里磁头数不是2,这个计算就会出错。正确的CHS计算应该结合BPB里的磁头数字段(比如BPB_NumHeads),而不是硬编码:

; 假设逻辑扇区号已经在ax中
mov bl, [BPB_SecPerTrk]
div bl          ; ah = 扇区偏移(0~17), al = (磁头号*柱面数)
inc ah          ; 扇区号从1开始
mov cl, ah      ; cl = 扇区号(低6位)
mov bl, [BPB_NumHeads]
mov ah, 0
div bl          ; al = 柱面号, ah = 磁头号
mov ch, al      ; ch = 柱面号低8位
mov dh, ah      ; dh = 磁头号
; 注意:如果柱面号超过255,需要把高2位放到cl的高2位,不过软盘一般不需要

2. 段寄存器es未正确设置

int 13h的ah=2功能要求es:bx指向数据缓冲区,如果你的es寄存器值不对,就会把数据写到错误的内存地址,或者直接读失败。在调用ReadOneSector之前,一定要确保es被设置成目标缓冲区所在的段,比如如果loader要加载到0x7e00,那es应该设为0x0000(因为0x0000*16 + 0x7e00 = 0x7e00)。

3. 栈未初始化

boot程序加载到0x7c00后,默认的栈位置可能不可用,你需要在boot开头手动设置栈:

org 07c00h
mov ax, 0
mov ss, ax
mov sp, 07c00h  ; 栈从0x7c00向下增长,避免覆盖boot代码

如果栈没设置,push/pop操作会破坏内存数据,间接导致int 13h参数错误。

4. 驱动器号dl不正确

你的BS_DrvNum设为0,这是软盘的驱动器号,但如果Bochs里配置的是硬盘镜像,应该用0x80。可以在boot程序开头直接用BIOS传入的dl值(BIOS会把启动驱动器号放到dl里),不要硬编码:

org 07c00h
mov [BS_DrvNum], dl  ; 保存BIOS传入的驱动器号

调试技巧

如果修复后还是有问题,在Bochs里执行到int 13h前,用info reg查看寄存器:

  • ax:ah=2(读扇区功能),al是要读的扇区数(必须≥1)
  • cx:ch是柱面号低8位,cl低6位是扇区号,高2位是柱面号高2位
  • dx:dh是磁头号,dl是驱动器号
  • es:bx:缓冲区的物理地址

看看这些参数是否符合你的磁盘镜像的实际参数,就能快速定位问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 15:27:39