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

来源:互联网 发布:windows编程视频教程 编辑:程序博客网 时间:2024/05/22 00:49
;########################################################################################;#                       #;#    软盘引导扇区源代码       #;#  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_DISKINFOequ9;磁盘总的磁头数在磁盘参数表中的位置FDT_LBA_NUMBER_DISKINFOequ13h;首张根目录表起始逻辑扇区号在磁盘参数表中的位置BYTE_OF_SECTOR_DISKINFOequ0eh;每扇区字节数在磁盘参数表中的位置DATA_LOGICNUM_DISKINFOequ17h;磁盘数据区起始逻辑扇区号在磁盘参数表中的位置LDLOADER_SIZE_OFFSETequ13h;LDLOADER文件的大小在目录项中的位置;======================宏变量定义结束=========================================================================org 0jmp Entry;磁盘参数DiskType db 0;磁盘类型,驱动器号(编号法则为:磁盘的第一个分区为0,第二个为1,依次类推。若为硬盘,则第7位置1;也就是若是硬盘第一个分区则设成0x80,软盘则为0x00)DiskInfoHead db 0;磁盘参数表所在的磁头号DiskInfoCyl db 0;磁盘参数表所在的磁道号DiskInfoSector db 2;磁盘参数表所在的扇区号;将自身移至内存9000h:0000Entry:;使DS:SI→7C00H:0000,ES:DI→9000H:0000xor si,sixor di,dimov ax,7c0hmov ds,axmov ax,9000hmov es,axmov cx,512cldrep movsbjmp 9000h:Start;主体代码Start:;设置段寄存器DS→9000H;ES→磁盘参数表50H;FS→临时数据区9040H;GS→磁盘缓冲区9060H;SS,SP→堆栈段9020H:01ffHmov ax,9000hmov ds,axmov ax,50hmov es,axmov ax,9040hmov fs,axmov ax,9060hmov gs,axmov ax,9020hmov ss,axmov sp,01ffh;将磁盘参数表读入内存0050:0000mov dh,[DiskInfoHead]mov ch,[DiskInfoCyl]mov cl,[DiskInfoSector]push esmov bx,50hmov es,bxmov bx,0call ReadDiskpop esjnc next;读磁盘成功跳转,否则显示错误信息NonSysErr:mov ax,csmov es,axmov ax,ErrorMSGmov bp,axmov cx,SystemName-ErrorMSGcall TypeMSGxor ax,axint 16hjmp 0FFFFh:0000;将根目录表首扇区内容读入内存9060:0000簇列表缓冲区中next:mov eax,[es:FDT_LBA_NUMBER_DISKINFO];根目录表起始逻辑扇区号在磁盘参数表第0fh字节处call SubDiskAddress;计算物理磁头、扇区、磁道号push esmov bx,9060hmov es,bxxor bx,bxcall ReadDiskpop esjc NonSysErr;检查首张根目录表第一个目录项文件名是否为:“LDLoader.sys”mov di,0mov si,SystemNamemov cx,12CMPstr:mov dl,[gs:di]mov dh,[ds:si]cmp dl,dhjne NonSysErrinc diinc siloop CMPstrinc dimov dl,[gs:di];检查该目录项最后一个字符是否是0cmp dl,0jne NonSysErr;检查文件大小是否大于零,目录项偏移13h处是文件的大小mov eax,[gs:LDLOADER_SIZE_OFFSET]cmp eax,0je NonSysErr;下面开始读取LDLoader.sys文件;1、计算文件占用扇区数xor edx,edxxor ebx,ebxmov bx,[es:BYTE_OF_SECTOR_DISKINFO]div ebxcmp edx,0je next1inc eaxnext1:;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,0ffffhsub ax,[es:BYTE_OF_SECTOR_DISKINFO];偏移地址上限inc axmov [fs:108h],axmov eax,[es:DATA_LOGICNUM_DISKINFO]mov [fs:110h],eaxReadLBR:mov eax,[fs:110h]call SubDiskAddresspush esmov es,[fs:104h]mov bx,[fs:106h]call ReadDiskpop esmov ax,[fs:106h]cmp ax ,[fs:108h]jne GoOnmov word [fs:106h],0add word [fs:104h],1000hjmp GoOn2GoOn:mov ax,[es:BYTE_OF_SECTOR_DISKINFO]add [fs:106h],axGoOn2:inc dword [fs:110h]dec dword [fs:100h]cmp dword [fs:100h],0jnz ReadLBRjmp 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,edxxor ecx,ecxmov cx,[es:SECS_OF_CYLINDER_DISKINFO];磁盘参数表第8字节处,存放着磁盘每磁道扇区数的信息。div ecxinc edx;此时EAX中存放的是(RS/NS)的商,EDX中存放的是余数mov [fs:150h],dl;保存物理扇区号;2、计算磁头号及柱面号xor ecx,ecxxor edx,edxmov cl,[es:HEADS_OF_DISK_DISKINFO];磁盘参数表第5字节处,存放着磁盘总的磁头数div ecxmov dh,dl;EDX中存放的是((RS / NS) / NH)的余数,也即物理磁头号,EAX中存放中存放的是商,也即柱面号。mov ch,almov cl,[fs:150h]ret;===============================;读磁盘扇区功能,读入一个扇区;入:;    CH—柱面,CL—扇区,DH—磁头;ES:BX=缓冲区地址;出:CF=0—操作成功,AH=00H,AL=传输的扇区数;    CF=1—操作失败,AH=状态码;===============================ReadDisk:mov ax,0201hmov dl,[DiskType]int 13hret;===============================;显示字符串函数;入口参数:ES:BP,字符串地址;   CX,字符串长度;;;===============================TypeMSG:push cxmov ah,3;调用int 10H 03H功能,获得光标坐标mov bh,0int 10hpop cxmov ax,1301h;调用int 10H 13H功能,显示字符串mov bx,0fhint 10hretErrorMSG db "None system or disk error!",13,10,"Press anykey to restart your computer!"SystemName db "LDLoader.sys"times 510-($-$$) db 0dw 0aa55h

原创粉丝点击