本文解析bootsect.s程序。
bootsect.s可以分为4部分:
- 读取bootsect到0x7c00,搬运bootsect到0x90000
- 读取system到0x10000
- 读取setup到0x90200
即从硬盘启动扇区的512字节中复制数据到内存中0x7c00位置,并跳转到该位置执行,
读取bootsect到0x7c00 搬运bootsect到0x90000
SYSSIZE = 0x3000
.globl begtext, begdata, begbss, endtext, enddata, endbss
.text
begtext:
.data
begdata:
.bss
begbss:
.text
SETUPLEN = 4 | nr of setup-sectors
BOOTSEG = 0x07c0 | original address of boot-sector
INITSEG = 0x9000 | we more boot here - out of the way
SETUPSEG = 0x9020 ! setup starts here
SYSSEG = 0x1000 | system loaded at 0x10000(65536)
ENDSEG = SYSSEG + SYSSIZE ! where to stop loading
! ROOT_DEV: 0x000 - same type of floppy as boot.
! 0x301 - first partition on first drive etc
ROOT_DEV = 0x306
从硬盘中第0个扇道0个磁头0磁道的1扇区复制BOOTSEG
entry start
start:
mov ax, #BOOTSEG
mov ds, ax
mov ax, #INITSEG
mov es, ax
mov cx, #256
sub si, si
sub di, di
rep
movw
jmpi go, INITSEG
go: mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
mov sp, #0xFF00
下面开始逐步分析
entry start
start:
mov ax, #BOOTSEG
mov ds, ax
mov ax, #INITSEG
mov es, ax
mov cx, #256
sub si, si
sub di, di
开始执行start部分代码,本段第一次开始执行过程中,寄存器取值变化如图所示
rep
movw
rep:表示重复执行指令movw,执行次数由cx寄存器中的值决定,即256次
原理详解:rep通过cx寄存器中自减到0x0000或自加到0xffffH,因而可以执行相应次数的操作
movw: 表示复制一个字(Word 16位),即每次复制两个字节,从ds:si复制到es:di处;
本段函数表示,将内存地址0x7c00处开始的512个字节(256*2)的数据,原封不动复制到0x90000处。
jmpi go, INITSEG
jmpi 是一个段间跳转指令,表示跳转到 0x9000:go 处执行
jmpi: 表示跳转到INITSEG(0x9000)为基址,go(此处假定地址为0x0008)为变址的地址继续运行
原理详解:jmpi IP:CS,其中 CS 和 IP是 内存寻址的两个坐标,通过计算CS左移4位+IP确定内存地址。文中通过jmpi go,0x9000,CS被改为0x9000,IP被改为go的地址。本回就是拷贝运行中的系统程序(512字节(1个扇区大小))到另一个内存区域,然后继续从前面执行的位置处执行启动代码
go: mov ax, cs
mov ds, ax
mov es, ax
m