1. P52,47~56
start :
mov ax, #BOOTSEG
mov ds, ax
mov ax, #INITSEG
mov es, ax
mov cx, #256
sub si, si
sub di, di
rep ! 重复执行它的下一条语句movw,直到cx中的数值为0。这里是循环执行256次
movw ! 以字节为单位,从源地址往目的地址搬移数据,si、di自增
jmpi go,INITSEG ! jmpi--段间跳转指令,CS = INITSEG,IP = go,即跳转到INITSEG:go处执行
标志寄存器EFlags
方向标志DF(Direction Flag),用于决定执行完一次串操作之后,变址寄存器ESI/EDI是加还是减
- DF=0,自加
- DF=1,自减
串操作
- 取串(LODS),存串(STOS)、移串(MOVS)
- 可以按照字节(B)、字(W)、双字(D)进行数据处理,
2. P53,62
扇区
一个扇区是512byte,setup 程序大约为 4 个扇区
段地址+偏移地址
- x86处理器地址总线是20位,而内部数据总线、寄存器都是16位的。
- 如何用16位寄存器表示20位?物理地址=段地址 << 4 + 偏移地址
- eg
ss = 0x9000,sp=0xff00,那么sp指向的地址是0x90000 + 0xff00 = 0x9ff00
3. P53,67
INT 0x13 磁盘服务程序
-
功能号0x00, 复位驱动器
AH = 0X00,DL = 需要复位的驱动器号。
-
功能号0x02, 读磁盘扇区到内存
AH = 0x02,AL = 需要读出的扇区数量;
CH = 磁道(柱面)号的低 8 位; CL = 开始扇区(0-5 位),磁道号高 2 位(6-7);
DH = 磁头号; DL = 驱动器号(如果是硬盘则位 7 要置位);
es:bx 指向数据缓冲区; 如果读取失败则 CF 标志置位返回信息
传输成功:CF=0,AH=00H,AL=传输的扇区数
传输失败:CF=1,AH=状态代码(见下表)
01H — 非法命令 | 02H — 地址目标未发现 | 03H — 磁盘写保护(软盘) | 05H — 复位失败(硬盘) |
---|---|---|---|
06H — 软盘取出(软盘) | 07H — 错误的参数表(硬盘) | 08H — DMA越界(软盘) | 09H — DMA超过64K界限 |
0AH — 错误的扇区标志(硬盘) | 0BH — 错误的磁道标志(硬盘) | 0CH — 介质类型未发现(软盘) | 0DH — 格式化时非法扇区号(硬盘) |
0EH — 控制数据地址目标被发现(硬盘) | 0FH — DMA仲裁越界(硬盘) | 10H — 不正确的CRC或ECC编码 | 11H — ECC校正数据错(硬盘) |
20H — 控制器失败 | 40H — 查找失败 | 80H — 磁盘超时(未响应) | AAH — 驱动器未准备好(硬盘) |
BBH — 未定义的错误(硬盘) | CCH — 写错误(硬盘) | E0H — 状态寄存器错(硬盘) | FFH — 检测操作失败(硬盘) |
-
功能号0x08,读取磁盘驱动器参数
AH = 0x08,DL = 驱动器号(如果是硬盘则要置位 7 为 1)
返回信息如果出错则 CF 置位,并且 AH = 状态码。
AH = 0, AL = 0
BL = 驱动器类型(AT/PS2)
CH = 最大磁道号的低 8 位,CL = 每磁道最大扇区数(位 0-5),最大磁道号高 2 位(位 6-7)
DH = 最大磁头数,DL = 驱动器数量
es:di 软驱磁盘参数表
4. P54,92~102
INT 0x10
由 BIOS 对屏幕及显示器所提供的服务程序
! Print some inane message
mov ah, #0x03 ! read cursor pos,AH=0x03,读取光标,为了获取光标当前的行列
xor bh, bh !bh = 页号
int 0x10
mov cx, #24
mov bx, #0x0007 ! page 0, attribute 7 (normal)
mov bp, #msg1
mov ax, #0x1301 ! write string, move cursor
int 0x10
读取光标是必要的,为了获取光标位置(DH、DL)
-
AH=3,读光标位置
BH = 页号
CH = 光标开始行
CL = 光标结束行
DH = 行
DL = 列 -
AH=13,表示显示字符串
ES:BP = 串地址
CX = 串长度
DH, DL = 起始行列
BH = 页号
BL = 07H,正常的黑底白字
P55,151~155
read_it:
mov ax, es
test ax, #0x0fff
die: jne die ! es must be at 64kB boundary
xor bx, bx ! bx is starting address within segment
test指令
- test的解释( Intel技术手册)
TEMP ← SRC1 AND SRC2 ;
SF ← MSB(TEMP) ;
IF TEMP = 0
THEN ZF ← 1 ;
ELSE ZF ← 0 ;
FI:
PF ← BitwiseXNOR(TEMP[0:7]);
CF ← 0 ;
OF ← 0 ;
- 对代码的解释
- test是进行位与操作,相与等于0,说明ax=es=0x1000,ZF=1
- JNE/JNZ都是ZF标志位为0时跳转,如果es在64kb处,则顺序执行;否则,死锁
子程序151~218
实现功能
该子程序将系统模块加载到内存地址 0x10000 处,并确定没有跨越 64KB 的内存边界。我们试图尽快 地进行加载,只要可能,就每次加载整条磁道的数据
执行流程
-
read_it
- 检测读入的数据是否在内存地址64kB处
- 是,则执行rp_read;否,则死锁
-
rp_read
- 首先判断是否已经读完
- 是,返回调用处;否,执行ok1_read
-
ok1_read
- 取当前磁道的扇区数,计算是否超过64kB
- 是,计算能读取的最大值;否,执行ok2_read
-
ok2_read
- 执行读取操作(跳转到了read_track)
- 传输的扇区数存储在AL中,判断是否已经读完当前磁道的所有扇区
- 是,顺序执行,如果当前磁道是0,则磁道号+1,执行ok4_read;如果磁道号是1,则直接跳转到ok4_read;否,执行ok3_read
-
ok3_read
- 计算当前已读扇区数量,将读取位置存储在bx中
- 跳转到rp_read,继续读取
-
ok4_read
- 保存磁道号,清空ax
- 如果未读完,进入ok3_read;否则,调整基址跳转到rp_read
-
read_track
- 对通用 寄存器压栈保护
- 设置要读取的驱动器号、磁道号、扇区,然后调用INT 0x13软件中断
- 调用正确,返回调用处;否则,执行bad_rt,驱动器复位,然后重新跳转执行read_track
-
kill_motor
关闭软驱的马达,这样我们进入内核后它处于已知状态,以后也就无须担心它了
子程序执行流图
8086寄存器
数据寄存器
- AX (Accumulator):累加寄存器,也称之为累加器;
- BX (Base):基地址寄存器;
- CX (Count):计数器寄存器;
- DX (Data):数据寄存器;
指针寄存器
- SP (Stack Pointer):堆栈指针寄存器;
- BP (Base Pointer):基指针寄存器;
变址寄存器
- SI (Source Index):源变址寄存器
- DI (Destination Index):目的变址寄存器;
控制寄存器
- IP (Instruction Pointer):指令指针寄存器;
- FLAG:标志寄存器;
段寄存器:
- CS (Code Segment):代码段寄存器;
- DS (Data Segment):数据段寄存器;
- SS (Stack Segment):堆栈段寄存器;
- ES (Extra Segment):附加段寄存器
网友评论