开发操作系统实践(五)——新的引导扇区代码
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
相关文章推荐
- 开发操作系统实践(三)——LinDos引导扇区内容及运行环境搭建
- 把自己的操作系统写入U盘(FAT32)引导扇区
- 高效HTML5代码开发最佳实践
- iOS应用开发最佳实践:编写高质量的Objective-C代码
- iOS应用开发最佳实践:编写高质量的Objective-C代码
- 敏捷开发松结对编程系列之十:代码审查最佳实践
- Web前端开发最佳实践(13):前端页面卡顿?可能是DOM操作惹的祸,你需要优化代码
- 敏捷开发“松结对编程”实践之五:代码检查篇(大型研发团队,学习型团队,139团队,师徒制度,代码审查)
- 微软一站式代码示例库开发实践系列课程
- python自动化测试开发利器ulipad最佳实践(可写python测试代码也可编写selenium、Appium等) 推荐
- Jfinal开发代码碎片_导出报表_配置druid数据源_使用guava_获取当前操作系统_JDK版本_jfinal-utils_jfinal验证码
- Web前端开发最佳实践(3):前端代码和资源的压缩与合并
- WCF分布式安全开发实践(0):文章和代码结构规划介绍
- 敏捷开发中高质量Java代码开发实践 [
- iOS开发>学无止境 - 后台定位上传的代码实践
- Windows和Linux操作系统下Eclipse开发C/C++程序的代码提示
- 敏捷开发“松结对编程”实践之四:日常工作篇(大型研发团队,学习型团队,139团队,师徒制度,检查点,代码审查,每日立会)
- 敏捷开发“松结对编程”实践之五:代码检查篇(大型研发团队,学习型团队,139团队,师徒制度,代码审查)
- 敏捷开发中高质量 Java 代码开发实践
- 敏捷开发“松结对编程”实践之五:代码检查篇(大型研发团队,学习型团队,139团队,师徒制度,代码审查)