您的位置:首页 > 编程语言

开发操作系统实践(五)——新的引导扇区代码

2012-12-06 20:53 246 查看
;########################################################################################
;#                 							      #
;#    软盘引导扇区源代码							       #
;#  1、将引导代码移送至内存9000H:0000处,并转去继续执行			                  #
;#  2、设置段寄存器DS→9000H;ES→磁盘参数表50H;FS→临时数据区9040H;			       #
;#		   GS→磁盘缓冲区9060H;SS,SP→堆栈段9020H:01ffH			      #
;#  3、将磁盘参数表读入内存0050H:0000处,磁盘参数表的位置由格式化程序或系统传送程序设置	       #
;#  4、根据根目录表所在的逻辑扇区号,计算它的物理磁头号、磁道号、逻辑扇区号		       #
;#  5、将根目录表所在的第一个扇区的内容读入内存9060H:0000				      #
;#  6、要想引导系统,必须将引导文件放在根目录表的第一个目录项中。			       #
;#		所以这一步分析根目录表的第一项文件名是否是系统引导文件“LDLoader.sys”	      #
;#  7、计算系统引导文件LDLoader.sys占用的扇区数,目录项偏移20B处是文件的大小		       #
;#  8、将LDLoader.sys文件读入系统内存0070:0000。这里又有一个先决条件,			       #
;#		即LDloader.sys文件放在磁盘用户数据区开头的连续扇区中。		       #
;#  9、JMP 0070H:0000,完成系统引导,转去执行LDLoader.sys。		                  #
;#					最后修改时间:2012年10月26日	                  #
;########################################################################################

;======================宏变量定义区===========================================================================
SECS_OF_CYLINDER_DISKINFO 	         equ 	0ch		;每磁道扇区数在磁盘参数表中的位置
HEADS_OF_DISK_DISKINFO		equ	9		;磁盘总的磁头数在磁盘参数表中的位置
FDT_LBA_NUMBER_DISKINFO		equ	13h		;首张根目录表起始逻辑扇区号在磁盘参数表中的位置
BYTE_OF_SECTOR_DISKINFO		equ	0eh		;每扇区字节数在磁盘参数表中的位置
DATA_LOGICNUM_DISKINFO		equ	17h		;磁盘数据区起始逻辑扇区号在磁盘参数表中的位置
LDLOADER_SIZE_OFFSET		equ	13h		;LDLOADER文件的大小在目录项中的位置
;======================宏变量定义结束=========================================================================

org 0
jmp Entry
;磁盘参数
DiskType db 0		;磁盘类型,驱动器号(编号法则为:磁盘的第一个分区为0,第二个为1,依次类推。若为硬盘,则第7位置1
;也就是若是硬盘第一个分区则设成0x80,软盘则为0x00)
DiskInfoHead db 0	;磁盘参数表所在的磁头号
DiskInfoCyl db 0	;磁盘参数表所在的磁道号
DiskInfoSector db 2	;磁盘参数表所在的扇区号
;将自身移至内存9000h:0000
Entry:
;使DS:SI→7C00H:0000,ES:DI→9000H:0000
xor si,si
xor di,di
mov ax,7c0h
mov ds,ax
mov ax,9000h
mov es,ax
mov cx,512
cld
rep movsb
jmp 9000h:Start
;主体代码
Start:
;设置段寄存器DS→9000H;ES→磁盘参数表50H;FS→临时数据区9040H;GS→磁盘缓冲区9060H;SS,SP→堆栈段9020H:01ffH
mov ax,9000h
mov ds,ax
mov ax,50h
mov es,ax
mov ax,9040h
mov fs,ax
mov ax,9060h
mov gs,ax
mov ax,9020h
mov ss,ax
mov sp,01ffh
;将磁盘参数表读入内存0050:0000
mov dh,[DiskInfoHead]
mov ch,[DiskInfoCyl]
mov cl,[DiskInfoSector]
push es
mov bx,50h
mov es,bx
mov bx,0
call ReadDisk
pop es
jnc next						;读磁盘成功跳转,否则显示错误信息
NonSysErr:
mov ax,cs
mov es,ax
mov ax,ErrorMSG
mov bp,ax
mov cx,SystemName-ErrorMSG
call TypeMSG
xor ax,ax
int 16h
jmp 0FFFFh:0000
;将根目录表首扇区内容读入内存9060:0000簇列表缓冲区中
next:
mov eax,[es:FDT_LBA_NUMBER_DISKINFO]		;根目录表起始逻辑扇区号在磁盘参数表第0fh字节处
call SubDiskAddress				;计算物理磁头、扇区、磁道号
push es
mov bx,9060h
mov es,bx
xor bx,bx
call ReadDisk
pop es
jc NonSysErr
;检查首张根目录表第一个目录项文件名是否为:“LDLoader.sys”
mov di,0
mov si,SystemName
mov cx,12
CMPstr:
mov dl,[gs:di]
mov dh,[ds:si]
cmp dl,dh
jne NonSysErr
inc di
inc si
loop CMPstr
inc di
mov dl,[gs:di]	;检查该目录项最后一个字符是否是0
cmp dl,0
jne NonSysErr
;检查文件大小是否大于零,目录项偏移13h处是文件的大小
mov eax,[gs:LDLOADER_SIZE_OFFSET]
cmp eax,0
je NonSysErr
;下面开始读取LDLoader.sys文件
;1、计算文件占用扇区数
xor edx,edx
xor ebx,ebx
mov bx,[es:BYTE_OF_SECTOR_DISKINFO]
div ebx
cmp edx,0
je next1
inc eax
next1:
;2、将LDLoader.sys文件占用的扇区数保存在内存9040h:0100h中
mov [fs:100h],eax
;3、开始读文件LDLoader.sys,读至内存0070:0000开始的内存中
mov word [fs:104h],70h				;存放文件的段地址
mov word [fs:106h],0					;偏移地址
mov ax,0ffffh
sub ax,[es:BYTE_OF_SECTOR_DISKINFO]		;偏移地址上限
inc ax
mov [fs:108h],ax
mov eax,[es:DATA_LOGICNUM_DISKINFO]
mov [fs:110h],eax
ReadLBR:
mov eax,[fs:110h]
call SubDiskAddress
push es
mov es,[fs:104h]
mov bx,[fs:106h]
call ReadDisk
pop es
mov ax,[fs:106h]
cmp ax ,[fs:108h]
jne GoOn
mov word [fs:106h],0
add word [fs:104h],1000h
jmp GoOn2
GoOn:
mov ax,[es:BYTE_OF_SECTOR_DISKINFO]
add [fs:106h],ax
GoOn2:
inc dword [fs:110h]
dec dword [fs:100h]
cmp dword [fs:100h],0
jnz ReadLBR
jmp 0070h:0000

;=============================================================================================
;根据逻辑扇区号计算对应磁盘的磁头号、磁道号、扇区号
;逻辑扇区号与物理扇区换算关系:逻辑扇区按照扇区号、磁头号、柱面号(或磁道号)增长的顺序连续分配
;假设:LH---LinDos逻辑扇区0的磁头号
;      LC---LinDos逻辑扇区0的柱面号
;      LS---LinDos逻辑扇区0的扇区号
;      NS---每磁道扇区数
;      NH---磁盘总的磁头数
;若已知某扇区柱面号C,磁头号H,扇区号S,则其对应的逻辑扇区号RS公式为:
;	RS=NH*NS*(C-LC)+NS*(H-LH)+(S-DS)
;若已知某扇区的逻辑扇区号RS,则其对应的柱面号C,磁头号H,扇区号S公式为:
;	S=(RS MOD NS)+LS
;	H=((RS DIV NS) MOD NH)+LH
;	C=((RS DIV NS)DIV NH)+LC
;入口参数:	EAX:逻辑扇区号
;出口参数:	CH—柱面,CL—扇区,DH—磁头
;=============================================================================================
SubDiskAddress:
;1、计算物理扇区号
xor edx,edx
xor ecx,ecx
mov cx,[es:SECS_OF_CYLINDER_DISKINFO]		;磁盘参数表第8字节处,存放着磁盘每磁道扇区数的信息。
div ecx
inc edx						;此时EAX中存放的是(RS/NS)的商,EDX中存放的是余数
mov [fs:150h],dl				;保存物理扇区号
;2、计算磁头号及柱面号
xor ecx,ecx
xor edx,edx
mov cl,[es:HEADS_OF_DISK_DISKINFO]		;磁盘参数表第5字节处,存放着磁盘总的磁头数
div ecx
mov dh,dl						;EDX中存放的是((RS / NS) / NH)的余数,也即物理磁头号,EAX中存放中存放的是商,也即柱面号。
mov ch,al
mov cl,[fs:150h]
ret

;===============================
;读磁盘扇区功能,读入一个扇区
;入:
;    	CH—柱面,CL—扇区,DH—磁头
;	ES:BX=缓冲区地址
;出:	CF=0—操作成功,AH=00H,AL=传输的扇区数
;    	CF=1—操作失败,AH=状态码
;===============================

ReadDisk:
mov ax,0201h
mov dl,[DiskType]
int 13h
ret

;===============================
;显示字符串函数
;入口参数:ES:BP,字符串地址
;	   CX,字符串长度
;
;
;===============================

TypeMSG:
push cx
mov ah,3		;调用int 10H 03H功能,获得光标坐标
mov bh,0
int 10h
pop cx
mov ax,1301h	;调用int 10H 13H功能,显示字符串
mov bx,0fh
int 10h
ret

ErrorMSG db "None system or disk error!",13,10,"Press anykey to restart your computer!"
SystemName db "LDLoader.sys"

times 510-($-$$) db 0

dw 0aa55h
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐