最近在研究赵炯老师的《Linux 内核 0.11 详细注释》,将自己的粗浅理解做个简单的注记,以供有相同兴趣爱好的朋友查阅。
一、程序功能
当 PC 的电源打开后,80x86 结构的CPU 将自动进入实模式,并从地址 0xFFFF0 开始自动执行程序代码,这个地址通常是 ROM-BIOS 中的地址。PC 机的 BIOS程序将执行某些系统的检测,并在物理地址 0 处开始初始化中断向量。此后,它将可启动设备的第一个扇区(磁盘引导扇区,512 字节)读入内存地址 0x7C00 处,并跳转到这个地方。启动设备通常是软驱或是硬盘。
二、代码注记
! SYS_SIZE是要加载的字节数(16字节)。
! 0x3000是0x30000字节= 196kB,对于当前Linux版本来说绰绰有余
!
SYSSIZE = 0x3000
bootsect 由BIOS程序加载到在内存地址0x7c00,当它执行时又将Bootsect移动到物理地址0x90000,并跳转到那里执行。并将启动设备Setup程序写入物理地址 0x90200 处,而内核的其它部分(system 模块)则被读入到从地址 !0x10000 开始处,因为该版本的system 模块的长度不会超过 0x80000(即 512KB),所以它不会覆盖在 0x90000 处开始的bootsect 和 setup模块。
.globl begtext, begdata, begbss, endtext, enddata, endbss
.text
begtext:
.data
begdata:
.bss
begbss:
.text
SETUPLEN = 4 ! setup程序占用的扇区数量
BOOTSEG = 0x07c0 ! bootsect程序原始段地址
INITSEG = 0x9000 ! bootsect移动到这里
SETUPSEG = 0x9020 ! setup 加载段地址
SYSSEG = 0x1000 !系统加载到0x10000处
ENDSEG = SYSSEG + SYSSIZE !加载结束段地址=0x4000
ROOT_DEV = 0x306 ! 指定根文件系统设备是第 2 个硬盘的第 1 个分区
entry _start
_start:
mov ax,#BOOTSEG
mov ds,ax !设置DS寄存器为0x07c0
mov ax,#INITSEG
mov es,ax !设置ES寄存器为0x9000
mov cx,#256 !设置CX寄存器为256
sub si,si
sub di,di !将si源址变址寄存器 、di目的变址寄存器清0,
rep
movw !rep movw 从DS:SI中复制CX个字(word)到ES:DI。
jmpi go,INITSEG !跳转至0x9000:go的位置执行,
go: