bootsect.S 中文注释 ( linux-0.12 )

本文详细分析并注释了Linux 0.12版本中的bootsect.S文件,深入理解早期Linux启动流程的关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

取自 https://github.com/ultraji/linux-0.12

!
! SYS_SIZE is the number of clicks (16 bytes) to be loaded.
! SYS_SIZE 是要加载的系统模块长度(单位是节,每节有16字节)。
! 0x3000 is 0x30000 bytes = 196kB, more than enough for current
! 即 0x30000 bytes = 192 KB(估算,以1000为单位,则是196KB),对于当前的
! 版本空间已足够了。
! 例如,当该值为 0x8000 时,表示内核最大为512KB。
! versions of linux
!
#include <linux/config.h>
!
! 该头文件里定义了内核用到的一些常数符号和 Linus 自己使用的默认硬盘默认参数块。
! 例如:
! DEF_SYSSIZE = 0X3000 系统模块长度
! DEF_INITSEG = 0x9000 该程序将要移动到的目的段位置
! DEF_SETUPSEG = 0x9020 setup程序代码的段位置
! DEF_SYSSEG = 0x1000 从磁盘加载系统模块到内存的段位置
!
SYSSIZE = DEF_SYSSIZE
!
!   bootsect.s      (C) 1991 Linus Torvalds
!   modified by Drew Eckhardt
!
! bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
! iself out of the way to address 0x90000, and jumps there.
!
! It then loads 'setup' directly after itself (0x90200), and the system
! at 0x10000, using BIOS interrupts. 
!
! NOTE! currently system is at most 8*65536 bytes long. This should be no
! problem, even in the future. I want to keep it simple. This 512 kB
! kernel size should be enough, especially as this doesn't contain the          '
! buffer cache as in minix
!
! The loader has been made as simple as possible, and continuos
! read errors will result in a unbreakable loop. Reboot by hand. It
! loads pretty fast by getting whole sectors at a time whenever possible.

! 以下是前面这些文字的翻译:
!   bootsect.s  (C) 1991 Linus Torvalds 版权所有
!   Drew Eckhardt 修改
!
!  bootsect.s 被BIOS启动子程序加载至 0x7c00 (31KB)处,并将自己移到了地
! 址 0x90000(576KB)处,并跳转至那里。
!
! 它然后使用BIOS 中断将'setup'直接加载到自己的后面(0x90200)(576.5KB),
! 并将 system 加载到地址 0x10000 处。
!
! 注意! 目前的内核系统最大长度限制为(8*65536)(512KB)字节,即使是在将来
! 这也应该没有问题的。我想让它保持简单明了。这样512KB的最大内核长度应该
! 足够了,尤其是这里没有像MINIX中一样包含缓冲区高速缓冲。
!
! 加载程序已经做得够简单了,所以持续的读操作出错将导致死循环。只能手工重启。
! 只要可能,通过一次读取所有的扇区,加载过程可以做的很快的。

.globl begtext, begdata, begbss, endtext, enddata, endbss
.text
begtext:
.data
begdata:
.bss
begbss:
.text

SETUPLEN = 4                ! nr of setup-sectors 
                            ! setup 占用的磁盘扇区数
BOOTSEG  = 0x07c0           ! original address of boot-sector
                            ! bootsect 代码所在的原地址(被BIOS子程序加载至此处)
INITSEG  = DEF_INITSEG          ! we move boot here - out of the way
                                ! bootsect将要移动到的目的段位置,为了避开系统模块占用处
SETUPSEG = DEF_SETUPSEG         ! setup starts here
                                ! setup程序代码从该段位置开始
SYSSEG   = DEF_SYSSEG           ! system loaded at 0x10000 (65536).
                                ! system 模块将被加载到 0x10000
ENDSEG   = SYSSEG + SYSSIZE     ! where to stop loading
                                ! 停止加载的段地址

! ROOT_DEV & SWAP_DEV are now written by "build".
! 根文件系统设备号 ROOT_DEV 和 交换设备号 SWAP_DEV 现在由 tools 目录下的 build 程序写入。
! 设备号具体值的含义如下:
! 设备号=主设备号*256 + 次设备号(也即 dev_no = ( major <<8 ) + minor )
! (主设备号:1-内存,2-磁盘,3-硬盘,4-ttyx,5-tty,6-并行口,7-非命名管道)
! 0x300 - /dev/hd0 - 代表整个第 
<think>好的,我现在需要帮助用户查找关于bootsect.s文件的详细注释。用户对汇编引导扇区代码感兴趣,可能是在学习操作系统启动过程或进行底层开发。首先,我得回忆一下bootsect.s的作用,它是Linux早期启动过程中的一部分,负责加载操作系统的其他部分。 根据用户提到的引用[2],用户正在分析boot目录中的汇编源码,想了解如何加载内核。这说明用户需要具体的代码注释和解释。我需要确保提供的注释准确,并且符合用户的需求。 首先,我需要确认bootsect.s的基本功能:它是引导扇区代码,由BIOS加载到内存0x7C00处,然后将自己移动到0x90000,设置堆栈,加载setup模块和系统模块。接下来,我需要分段解释代码,包括各个寄存器的使用、中断调用以及关键指令的作用。 用户提供的引用中提到了int 0x13的AH=0x02功能用于读取磁盘扇区,这在bootsect.s中会有应用。同时,用户可能对movw指令有疑问,引用[3]提到了相关的博文,但用户现在需要的是bootsect.s的注释,因此需要详细解释代码中的每个步骤。 接下来,我需要检查是否有常见的代码结构,比如移动自身代码、加载setup模块、打印信息等。对于每个关键指令,如mov、jmp、int等,都需要解释其参数和作用。此外,需要指出如何通过BIOS中断读取磁盘,以及如何跳转到setup模块执行。 还要注意代码中的一些细节,比如ORG指令的作用、如何计算扇区数、如何设置段寄存器等。可能用户对这些底层细节不太熟悉,所以需要用简单的中文解释清楚。 最后,生成相关问题时要围绕bootsect.s的功能、汇编指令、启动流程和调试方法,确保问题能够帮助用户进一步深入理解。</think>### `bootsect.s` 文件详细注释与解释 `bootsect.s` 是 Linux 0.11 内核引导阶段的核心汇编代码,负责从磁盘加载操作系统内核到内存,并移交控制权。以下是对其关键代码段的逐行注释: ```assembly ! bootsect.s 引导扇区代码,由 BIOS 自动加载到 0x7C00.globl begtext, begdata, begbss, endtext, enddata, endbss .text begtext: .data begdata: .bss begbss: .text SETUPLEN = 4 ! setup 模块占用的扇区数 BOOTSEG = 0x07C0 ! BIOS 加载引导扇区的原始段地址 INITSEG = 0x9000 ! 将引导扇区移动到此段地址 SETUPSEG = 0x9020 ! setup 模块加载地址 SYSSEG = 0x1000 ! 系统模块加载地址 SYSSIZE = 0x3000 ! 系统模块最大长度(单位:16字节) entry start start: mov ax,#BOOTSEG ! 将原始段地址 0x07C0 存入 AX mov ds,ax ! 设置数据段寄存器 DS mov ax,#INITSEG ! 目标段地址 0x9000 mov es,ax ! 设置附加段寄存器 ES mov cx,#256 ! 移动 256 字(512 字节) sub si,si ! SI = 0 sub di,di ! DI = 0 rep movsw ! 重复执行 movsw,将代码从 0x7C00 移动到 0x90000 jmpi go,INITSEG ! 段间跳转到新地址 0x9000:go [^1] ``` **代码作用**:将自身从 `0x7C00` 移动到 `0x90000`,避免被后续加载的 setup 模块覆盖。 --- ```assembly go: mov ax,cs ! 设置各个段寄存器为新的位置 mov ds,ax ! DS = CS = 0x9000 mov es,ax ! ES = 0x9000 mov ss,ax ! SS = 0x9000 mov sp,#0xFF00 ! 设置堆栈指针 SP(约 64KB 空间) ! 加载 setup 模块到内存 0x90200 处 load_setup: mov dx,#0x0000 ! DH=0(磁头号),DL=0(驱动器号) mov cx,#0x0002 ! CH=0(磁道号低8位),CL=2(起始扇区号) mov bx,#0x0200 ! ES:BX=0x9000:0x0200(目标地址 0x90200) mov ax,#0x0200+SETUPLEN! AH=0x02(读磁盘功能),AL=4(读取4个扇区) int 0x13 ! 调用 BIOS 磁盘中断 [^1] jnc ok_load_setup ! 若未出错(CF=0)则跳转 mov dx,#0x0000 ! 出错则复位磁盘 int 0x13 jmp load_setup ! 重试 ``` **关键点**: 1. 使用 `int 0x13` 的 `AH=0x02` 功能读取磁盘扇区 2. 参数说明:`CL` 寄存器低6位表示扇区号(1-based),`CH` 和 `CL` 高2位组成10位磁道号 3. 错误处理通过检查进位标志 `CF` 实现 --- ```assembly ! 打印加载信息 ok_load_setup: mov ah,#0x03 ! 获取光标位置 xor bh,bh ! 页号=0 int 0x10 mov cx,#24 ! 消息长度 mov bx,#0x0007 ! 显示属性(黑底白字) mov bp,#msg1 ! 消息地址 mov ax,#0x1301 ! AH=0x13(显示字符串),AL=1(更新光标) int 0x10 ! 调用 BIOS 视频中断 ! 加载系统模块到 0x10000 处 load_system: mov dx,#0x0000 ! 驱动器号=0,磁头号=0 mov cx,#0x0006 ! 起始扇区=6,磁道=0 mov bx,#0x0000 ! ES:BX=0x1000:0x0000 mov ax,#0x1000 mov es,ax mov ax,#0x0230+SYSSIZE ! 读取 0x3000*16=192KB int 0x13 jnc ok_load_system ... ! 错误处理(省略) ! 跳转到 setup 模块 ok_load_system: jmpi 0,SETUPSEG ! 跳转到 0x9020:0x0000 执行 setup.s ``` **系统加载逻辑**: 1. 系统模块从磁盘第6个扇区开始加载 2. 目标地址为 `0x10000`(实模式下 64KB 边界) 3. 最终通过 `jmpi` 跳转到 setup 模块继续执行 --- ### 相关技术细节 1. **磁盘寻址**:使用 CHS(柱面-磁头-扇区)模式,最大支持 8GB 磁盘 2. **内存布局**: - `0x7C00-0x7DFF`:BIOS 加载引导扇区原始位置 - `0x90000-0x901FF`:移动后的引导程序 - `0x90200`:setup 模块加载位置 3. **段寄存器计算**:实模式下物理地址 = `段寄存器 << 4 + 偏移量`
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值