一看二做三总结
分类: 嵌入式
2011-06-09 22:13:40
Cpu启动时,如果在bios中设置了从软盘启动,则bios会自动把软盘的第一个扇区(512字节)搬移到0x7c00,然后会从0x7c00开始运行,我们需要在这512字节的程序中实现把boot从软盘中搬移到内存中的功能。
此时x86系列的cpu还处在实模式中,可以利用bios提供的中断完成软盘读写,也就是著名的int 13。
1 软盘操作 1.1 软盘结构以1.44M软盘为例,软盘有上、下两个盘面,每个盘面被划分为80个track,每个track被划分为18个Sector,每个Sector大小为512 BYTES。
2×80×18×512=1440×1024=1.44MB
如果是单纯的进行软盘读写操作,知道软盘的这些知识就够了。
1.2 软盘读写
中断号 |
寄存器 |
作用 |
13h |
ah=00h al=驱动器号(0表示A盘) |
复位软驱 |
ah=02h al=要读扇区数 ch=磁道号 cl=起始扇区号 dh=磁头号 dl=驱动器号 es:bx=数据缓冲区 |
从cl/ch/dh/dl指向的扇区开始读取al个扇区的数据到es:bx指向的缓冲区 | |
ah=03h al=要写扇区数 ch=磁道号 cl=起始扇区号 dh=磁头号 dl=驱动器号 es:bx=数据缓冲区 |
从es:bx指向的缓冲区读取al个扇区的数据写入cl/ch/dh/dl指向的al个扇区 |
对于软盘来说, DL=0(0表示A盘)
CL的取值范围是:1—18
CH的取值范围是:0—79
DH 的取值范围是:0—1
如果软盘的CL,CH,DH取值超过了范围,中断调用出错。
使用int13时对应扇区数的计算方法如下:
1.3 软盘编程用软盘存放操作系统时,bios只会把前512个字节(即第一个扇区,引导区)读入内存的0x7c00处执行。程序的长度也被限制在了512字节大小,一个出入保护模式的程序就会超出。
为了突破512字节的限制,需要在这个扇区内放置一段引导程序,用于把后面的程序加载到内存中。这也是第一个扇区被称为引导区的原因。
下面的就是一段简单的加载程序,reset软驱后从LABEL_SECTOR2开始读入17个扇区。加上0号扇区(引导区),一共是18个扇区,也就是第一个磁道。这是因为13号中断不能跨磁道读取,所以这里只读入第一个磁道剩下的17个扇区。
; reset floppy xor ah, ah xor dl, dl int 13h
; read sector 2 to memory mov ah, 03h mov al, 11h mov ch, 00h mov cl, 03h mov dh, 00h mov dl, 00h mov bx, 0100h int 13h |
下面的程序用于保证除引导程序外的所有程序都在引导区之外,完成把磁盘内容拷贝入memory的操作后,就会跳入LABEL_SECTOR2。
jmp LABEL_SECTOR2
; fill boot sector times 510 - ($ - $$) db 1 dw 0xaa55
; Sector 2 LABEL_SECTOR2: |
下面是完整的程序代码
org 07c00h jmp LABEL_BEGIN
LABEL_BEGIN: mov ax, cs mov ds, ax mov ss, ax mov es, ax
; reset floppy xor ah, ah xor dl, dl int 13h
; read sector 2 mov ah, 02h mov al, 01h mov ch, 00h mov cl, 02h mov dh, 00h mov dl, 00h mov bx, LABEL_SECTOR2 int 13h
jmp LABEL_SECTOR2
; fill boot sector uutimes 510 - ($ - $$) db 0 dw 0xaa55
; Sector 2 jmp into loader ; org 0100h LABEL_SECTOR2: mov ax, cs mov ds, ax mov es, ax call DispStr ; 调用显示字符串例程 jmp $ ; 无限循环 DispStr: mov ax, BootMessage mov bp, ax ; ES:BP = 串地址 mov cx, 16 ; CX = 串长度 mov ax, 01301h ; AH = 13, AL = 01h mov bx, 000ch ; 页号为0(BH = 0) 黑底红字(BL = 0Ch,高亮) mov dl, 0 int 10h ; 10h 号中断 ret BootMessage: db "Hello, OS world!"
; fill floppy times (2 * 18 * 80 * 512 - ($ - $$)) db 0 |
软盘,INT 13H和IMG文件
1:软盘
软盘是以扇区为基本单位来进行操作的,每扇区512字节,共2880个扇区,空间大小为1.44M.
这2880个扇区又可以用(磁头、磁道、扇区)这三个参数来描述。我们简单记(磁头、磁道、扇区)为(x,y,z),那么
X的取值范围是:0—1
Y的取值范围是:0--79
Z的取值范围是:1—18
也就是说软盘有2磁头、每磁头有80磁道、每磁道有18扇区,共2880个扇区(2880=2*80*18)。
如果把2880个扇区从0开始编号,一直到2879结束,那么
编号为i的扇区和(X,Y,Z)的换算公式为:i=80*18*x+18*y+z-1
2:INT 13H
INT13H是磁盘的BOIS中断,对于读写扇区操作,中断的完整调用参数如下:
AL=扇区数
AH=中断子功能号 ;2=读扇区,3=写扇区
CL的6,7位,CH = 磁道号 ;每磁头最多可以有2^10=1024个磁道
CL的低6位 = 扇区号 ;每磁道最多可以有2^6=64个扇区
DH = 磁头号 ;最多可以有256个磁头
DL = 驱动器号 ;0=软盘,80H=硬盘
ES:BX=数据缓冲区的地址
其他:
1).
对于软盘来说,实际的INT 13H中DL=0,而CL,CH,DH的取值范围也不可能取到上面的数值,根据1:中的数据,有
CL的取值范围是:1--18
CH的取值范围是:0-79
DH 的取值范围是:0—1
如果软盘的CL,CH,DH取值超过了范围,中断调用出错。
AL的取值也不是任意的,一次调用INT13H进行读写扇区的只可以在一个磁道内的扇区进行。如果超出了一个磁道,必须要更新INT13H的中寄存器,重复调用INT13H。
对于软盘来说 AL必须要小于19-CL。
下面是一个从软盘的(x,y,z)扇区中连续读出n个扇区的内容到缓冲区BUFFER中的代码片段( 代码使用了一些80386的指令和MASM6.0才支持的伪指令):
MOV AX,DS
MOV ES,AX
MOV BX,OFFSET
MOV BP, n
MOV CL,z
MOV CH,y
MOV DL,0
MOV DH,x
.WHILE BP ;bp记录的是还没有进行读操作的扇区数量
;WHILE伪指令,和高级语言的WHILE一样理解就可以了,下面的。IF也一样
;对AL的取值进行计算
MOV AL,19
SUB AL,CL ;最多可以读19-CL个扇区
XOR AH,AH
.IF AX>BP
MOV AX,BP
XOR BP,BP
.ELSE
SUB BP,AX ;更新BP
.ENDIF
MOV AH,2
INT 13H ;读扇区
;更新CL,CH,DH
MOV CL,1
.IF CH==79
INC DH
XOR CH,CH
.ELSE
INC CH
.ENDIF
XOR AH,AH
SHL AL,9 ;AX=AL*512,等于已经处理的字节数
;SHL AL,9和SHL AX,4都是80386+才支持的指令
SHR AX,4 ;AX=AX/16
ADD ES,AX ;更新ES:BX,这里是更新了ES,也可以更新BX。
.endw
2).
INT13H只理论上最多处理 2^24个扇区*512字节/扇区=8G的磁盘空间,这对现在的硬盘来说,是远远不够的,于是后来对INT13H进行了扩展,用AH=42H、AH=43H分别对大硬盘进行操作,这里就不详细讨论了。
3:IMG文件
IMG文件是软盘的镜像文件,文件大小也是1.44M,它和软盘是一种线性的对应关系。
软盘上一个编号为(x,y,z)的512字节的扇区,对应IMG文件中的以2400H*x+4800H*y+(z-1)*512为基址的512个字节(注意,2400H,4800H是16进制数)。
IMG文件的字节和软盘的扇区对应关系也可以如下图所示(注意那些是十进制,那些是16进制)。
对于扩展INT 13中断,参数如下:
中断号 功能 调用寄存器 返回寄存器 备注
INT 13
AH=41H 检测扩展中断功能是否安装 AH = 41h
BX=55AAh
DL = 驱动器号(80h到FFH)
失败:AH=1
CF置位
成功:AH=版本号
CF=0 BX=AA55H
INT 13
AH=42H 磁盘扩展读操作 AH = 42H
DL = 驱动器号
DS:SI=指向LBA地址包的指针 失败:AH=错误号
CF置位
成功:AH=0
CF=0
地址包定义:
偏移 大小 描述
00H 字节 地址包大小
01H 字节 保留(为0)
02H 字 传输包个数
04H 双字 指向数据指针
08H 4字 起始地址
其中LBA=((柱面*磁头/柱面+磁头)*扇区/柱面)+扇区-1
INT 13
AH=43H 磁盘扩展写操作 AH=43H
AL=写标志
DL = 驱动器号
DS:SI=指向LBA地址包的指针 失败:AH=错误号
CF置位
成功:AH=0
CF =0 同上
INT 13
AH=48H 获取磁盘参数 AH=48H
DL=驱动器号
DS:SI=指向保存参数缓冲区的指针
失败:AH=错误号
CF置位
成功:AH=0
CF=0
参数缓冲区定义:
偏移 大小 描述
00H 字 缓冲区大小
02H 字 信息标志位
04H 双字 物理柱面数
08H 双字 物理磁头数
0CH 双字 物理每柱扇区数
10H 4字 扇区总数
18H 字 每扇区字节数