⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 learnosboot.asm

📁 一个关于系统启动代码的各种版本的打包机和
💻 ASM
字号:
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
;Boot.asm
;START:2006/4/11
;AUTHOR:Tresss
;SYSTEM:WinXP+nasm
;HomePage: http://www.writeos.com
;E-Mail:potianjing@gmail.com
;Character:BootLoader.
;Completed:2006.4.24
;nasm boot.asm
;
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑

  [bits	16]
  [org	0x7C00]
  jmp short Main
  NOP
;----------------Fat12分区数据区---------------------
  OEM	DB	'TresssOS'
  ByteOfSec DW	0x200
  SecOfClus DB	0x01
  NumOfReci DW	0x0001
  NumOfFats DB	0x02
  NumOfDirs DW	0x00E0		;十进制224
  NumOfSec DW	0x0B40		;2880
  MediaBPB DB	0xF0
  SecOfFats DW	0x0009
  SecOfTrk DW	0x0012		;18
  NumOfHeader DW	0x0002
  NumOfHide DD	0x00000000
  TotalOfSec DD	0x00000000
  NumOfDrv DB	0x00
  Reserved DB	0x00
  SigOfBoot DB	0x29
  IDOfVol DD	0x00000000
  LabOfVol DB	'Tresss 0.01'
  TypeOfFile DB	'Fat12  '
;-------------------分区数据结束--------------------
  Main:
  Xor ax,ax
  Mov ds,ax
  mov ss,ax
  mov es,ax
  mov sp,0x7BF0
  mov si,Msg
  Call ShowMessage
  xor ah,ah
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
;准备读取根目录区数据
;内存的前500H被BIOS占用,所以此处加载到内存500H之后
;计算出线形扇区位置后
;调用ReadSectors来读取数据.
;磁头,磁道,扇区的换算过程由ReadSectors来解决
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
  mov al,[MemStart]
  mov es,ax
  mov al,[SecOfFats]
  mov bl,[NumOfFats]
  mul bl			;算出Fat区占用的扇区数
  add al,[NumOfReci]
  add al,[NumOfHide]		;AL为目录区起始扇区按现标准值,此时应该al=19
  mov [FatFSec],al		;保存Fat之前的扇区总数
  mov cx,ax			;将起始扇区记录到CL,供ReadSectors调用
  mov al,[NumOfDirs]
  mov bl,[SizeOfDir]
  mul bl			;ax为目录区大小;
  mov [SizeDRoot],ax		;记录目录区大小;
  mov bx,[ByteOfSec]
  div bx			;AL为目录区占用几个扇区;此时应为14
  mov [RootDSec],al		;保存目录区占几个扇区到缓存区
  xor si,si			;读取到0x50:00处
  call ReadSectors
;------------------读取根目录完成--------------------

;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
;从500H处开始查找要加载的文件FileImport
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
FindFile:
  xor al,al
  cmp [es:si],al		;0x50:00处,根目录数据的起始位置.
  jz notok			;无效数据(0H)退出
  mov cl,11
  push si
  mov di,FileImport
CmpLoop:
  mov ah,[ds:di]
  mov al,[es:si]
  cmp ah,al
  jnz CmpNext			;不相等则比较下一个文件名
  inc si
  inc di
  loop CmpLoop			;比较下一个字符
  pop si
  jmp LoadFile			;找到文件,加载
CmpNext:
  pop si
  xor ah,ah
  mov al,[SizeOfDir]
  add si,ax			;指向下一个目录名.
  mov ax,[SizeDRoot]
  cmp si,ax			;比较是否已经查找到目录的最后
  jb FindFile			;循环比较下一个文件名.
;----------------查找文件结束--------------------------


;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
;错误处理,此处应加入错误提示信息
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
notok:				;错误处理,此处应显示一行信息.
xor ax,ax
mov es,ax
  mov si,FileImport
  Call ShowMessage
  xor ax,ax
  int 16h
;-------------------错误处理结束----------------------

;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
;加载Fat区数据至内存500H+SizeDRoot处
;SizeDRoot由上面加载目录区时算出并保存.
;es:si指向文件目录信息
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
LoadFile:
;---------------先加载Fat区数据----------------------
  push si
  mov ax,[SizeDRoot]		;已加载目录区,此处跳过
  mov si,ax
  mov al,[SecOfFats]		;FAT占用扇区数,即读取的个数
  mov cl,[NumOfReci]		;保留扇区数
  add cl,[NumOfHide]		;确定起始位置
  Call ReadSectors
  pop si			;si为内核文件名在目录区的偏移
;----------------Fat加载完毕-------------------------
  mov ax,Word [es:si+1ah]
  push ax			;起始簇
  xor ax,ax
  mov si,ax			;内存起始位置
  pop ax
  push ax 
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
;加载内核文件
;加载到内存FileSeg:00处,此处FileSeg=9000h
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
Loading:
  push es			;保存原基地址
  mov bx,FileSeg
  mov es,bx 
  Call ReadCluster		;读取当前簇内容
  pop es
  xor ah,ah
  mov al,[SecOfClus]
  mov bl,[ByteOfSec]
  mul bl			;ax为每一簇的大小
  add si,ax			;内存缓存区后移一簇大小
  pop ax			;取出簇号
  push si			;保存缓存区位置
  mov si,ax
  shr si,01h			;取(簇号/2)因为链表信息位于(簇号/2+簇号)
  pushf				;作用:保存cf状态
  add si,ax			;si值为(簇号/2+簇号),即此簇在Fat区的相对偏移
  mov ax,[SizeDRoot]		;目录区占用内存大小
  add si,ax			;此时es:si为内存中当前簇信息
  mov ax,[es:si]
  popf				;取出cf判断.
  jc GetHigh			;cf=1,即为奇数时取高十二位
  and ax,0fffh			;否则取低十二位
  jmp iseof
GetHigh:
  mov cl,4
  shr ax,cl
iseof:
  cmp ax,0ff8h			;是否结束.
  jae runknl			;链表结束后跳转到runknl
  pop si
  push ax
  jmp Loading			;没有结束则跳转继续读取当前簇


runknl:
  mov ax,FileSeg ;此处为显示读取的内容
  mov ds,ax
  xor ax,ax
  mov si,ax
  Call ShowMessage
;  jmp dword FileSeg:00 ;若执行内核.则只需将此句代替上面五句

;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
;ReadCluster
;读取一个簇的数据到内存
;入口:al 要读取的扇区数,cl 起始扇区位置
;入口:es:si为要读取到的内存地址,函数自动转换为es:bx
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
ReadCluster:
  sub ax,2h
  mov bl,[FatFSec]
  add al,bl
  mov bl,[RootDSec]
  add al,bl
  mov cl,al			;起始扇区
  mov al,[SecOfClus]		;要读取的扇区数
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
;ReadSectors
;读取硬盘扇区数据到内存
;入口:al 要读取的扇区数,cl 起始扇区位置
;入口:es:si为要读取到的内存地址,函数自动转换为es:bx
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
ReadSectors:
  pusha
  push ax
  mov ax,cx
  mov bl,[SecOfTrk]
  div bl			;al为线性磁道数;
  inc ah
  mov cl,ah			;Cl为实际要读取的扇区位置.
  xor ah,ah
  mov bl,[NumOfHeader]
  div bl
  mov ch,al			;要读取的磁道数
  mov dh,ah			;余数为磁头号
  xor dl,dl
  pop ax			;要读取的扇区数
  mov bx,si			;读取到es:bx
  mov ah,02
  int 13h

  popa
  ret

;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
;显示字符串
;参数	:DS:SI	为要显示的字符串.以00H结尾
;返回值	:无
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑  
  ShowMessage:
    mov ah,0x0e
    mov bh,0x00		;页码
    mov bl,0x0c		;前景色
  .nextchar:
    lodsb
    or al,al		;显示的字符
    jz .brs
    int 0x10
    jmp .nextchar
    .brs
    ret

  Msg		db	"Welcome To www.writeos.com......"
  Mturn		db	13,10,2,3,">",0
  MemStart	db	0x50				;最前的自由内存区500H
  FileImport	db	"learnos txt",0
  SizeOfDir	db	32				;目录区,一个目录信息占多大
  FatFSec	db	0				;记录目录区之前有多少扇区
  RootDSec	db	0				;记录目录区占多少扇区
  SizeDRoot	db	0				;记录目录区占多当字节
  FileSeg	equ	0x800				;加载文件偏移

  
  times 510-($-$$) db 0
  dw 0xaa55

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -