加载中...

learning_OS——day3

  • BIOS:基本输入输出系统,电脑启动时的“第一道程序”,负责初始化硬件,检测系统状态等。

BIOS中断的相关指令:

  • INT 10H:控制屏幕输出
  • INT 13H:磁盘读写

汇编程序1:加载操作系统的第一道程序——BIOS程序。加载软盘启动区至内存指定区域,并在新的操作系统中输出"Hello, World"

; hello-os
; TAB=4

		ORG		0x7c00			; 指定程序加载到内存地址0x7c00

; 以下是FAT12格式磁盘的引导扇区信息

		JMP		entry
		DB		0x90
		DB		"HELLOIPL"		; 引导扇区的标识符(8字节)
		DW		512				; 每扇区的字节数(通常为512)
		DB		1				; 每簇的扇区数(通常为1)
		DW		1				; 保留扇区数(通常为1)
		DB		2				; FAT表的数量(通常为2)
		DW		224				; 根目录的条目数(通常为224)
		DW		2880			; 总扇区数(通常为2880,1.44MB软盘)
		DB		0xf0			; 媒体描述符(0xf0表示软盘)
		DW		9				; 每个FAT表占用的扇区数(通常为9)
		DW		18				; 每个磁道的扇区数(通常为18)
		DW		2				; 磁头数(通常为2)
		DD		0				; 隐藏扇区数(通常为0)
		DD		2880			; 总扇区数(32位值,通常为2880)
		DB		0,0,0x29		; 扩展引导标志
		DD		0xffffffff		; 卷序列号
		DB		"HELLO-OS   "	; 卷标(11字节)
		DB		"FAT12   "		; 文件系统类型(8字节)
		RESB	18				; 保留18字节

; 程序入口

entry:
		MOV		AX,0			; 初始化寄存器
		MOV		SS,AX
		MOV		SP,0x7c00
		MOV		DS,AX
		MOV		ES,AX

		MOV		SI,msg
putloop:
		MOV		AL,[SI]
		ADD		SI,1			; SI加1
		CMP		AL,0
		JE		fin
		MOV		AH,0x0e			; BIOS打印字符功能
		MOV		BX,15			; 设置字符颜色
		INT		0x10			; 调用BIOS中断
		JMP		putloop
fin:
		HLT						; 停止CPU
		JMP		fin				; 无限循环

msg:
		DB		0x0a, 0x0a		; 换行两次
		DB		"hello, world"	; 输出的字符串
		DB		0x0a			; 换行
		DB		0

		RESB	0x7dfe-$		; 填充到0x7dfe地址

		DB		0x55, 0xaa		; 引导扇区结束标志

(以下程序省略了汇编程序1的大部分结构,只保留了重点)
汇编程序2:在汇编程序1的基础上,将软盘的第二个扇区读入内存

entry:
		MOV		AX,0			; 初始化寄存器
		MOV		SS,AX
		MOV		SP,0x7c00		; 设置堆栈指针
		MOV		DS,AX

(新添加部分)
		MOV		AX,0x0820
		MOV		ES,AX
		MOV		CH,0			; 磁道号0
		MOV		DH,0			; 磁头号0
		MOV		CL,2			; 扇区号2

		MOV		AH,0x02			; AH=0x02:读磁盘
		MOV		AL,1			; 读取1个扇区
		MOV		BX,0
		MOV		DL,0x00			; 驱动器号
		INT		0x13			; 调用磁盘BIOS
		JC		error			; 如果出错,跳转到error

汇编程序3:在汇编程序2的基础上,添加读软盘的试错功能(可能会读取失败)。连续读错5次以上则停止读取并报错。

; 初始化寄存器

entry:
		MOV		AX,0			; AX清零
		MOV		SS,AX			; 设置栈段寄存器为0
		MOV		SP,0x7c00		; 设置栈指针为加载地址0x7c00
		MOV		DS,AX			; 设置数据段寄存器为0

; 加载第二扇区

		MOV		AX,0x0820		; 设置第二扇区加载内存的起始地址为0x0820:0000
		MOV		ES,AX			; ES:BX构成第二扇区载入的内存地址区间
		MOV		CH,0			; 柱面号为0
		MOV		DH,0			; 磁头号为0
		MOV		CL,2			; 扇区号为2

		MOV		SI,0			; 重试计数器清零
retry:
		MOV		AH,0x02			; AH=0x02:读取磁盘扇区
		MOV		AL,1			; 读取1个扇区
		MOV		BX,0			; BX清零,偏移地址为0
		MOV		DL,0x00			; 驱动器号为0(软盘)
		INT		0x13			; 调用磁盘BIOS中断
		JNC		fin				; 如果没有错误,跳转到fin
		ADD		SI,1			; 重试计数器加1
		CMP		SI,5			; 判断是否重试超过5次
		JAE		error			; 如果重试次数>=5,跳转到error
		MOV		AH,0x00			; AH=0x00:复位磁盘系统
		MOV		DL,0x00			; 驱动器号为0
		INT		0x13			; 调用磁盘BIOS中断
		JMP		retry			; 重新尝试读取

汇编程序4:在汇编程序3的基础上,读取完整18个扇区。
执行完毕后,磁盘上的 C0-H0-S2 到 C0-H0-S18(第2~18个扇区)会装载到内存的 0x8200~0xa3ff 处。

retry:(读取当前扇区)
		MOV		AH,0x02			; AH=0x02:读取磁盘
		MOV		AL,1			; 读取1个扇区
		MOV		BX,0
		MOV		DL,0x00			; 驱动器号
		INT		0x13			; 调用磁盘BIOS
		JNC		next			; 如果没有错误,跳转到next
		ADD		SI,1			; 重试计数+1
		CMP		SI,5			; 如果重试次数>=5
		JAE		error			; 跳转到error
		MOV		AH,0x00
		MOV		DL,0x00			; 驱动器号
		INT		0x13			; 重置驱动器
		JMP		retry
next:(更换下一个扇区)
		MOV		AX,ES			; 地址偏移+0x200
		ADD		AX,0x0020       ; 一个扇区512字节,这里16*ES变化量刚好为512
		MOV		ES,AX			; 更新ES寄存器
		ADD		CL,1			; 扇区号+1
		CMP		CL,18			; 如果扇区号<=18
		JBE		readloop		; 跳转到readloop

汇编程序5:在汇编程序4的基础上,读取完整10个柱面。
读取顺序:先读完18个扇区,再更换磁头读取另一面的18个扇区;两个面均读完后才更新柱面。
执行该程序后,10个柱面的内容已读取到内存地址范围0x08200 ~0x34fff。

retry:(读取当前扇区)
		MOV		AH,0x02			; AH=0x02:读取磁盘
		MOV		AL,1			; 读取1个扇区
		MOV		BX,0
		MOV		DL,0x00			; 驱动器号
		INT		0x13			; 调用磁盘BIOS
		JNC		next			; 如果没有错误,跳转到next
		ADD		SI,1			; 重试计数器加1
		CMP		SI,5			; 如果重试次数>=5
		JAE		error			; 跳转到error
		MOV		AH,0x00
		MOV		DL,0x00			; 驱动器号
		INT		0x13			; 重置驱动器
		JMP		retry
next:(更换扇区,磁头与柱面)
		MOV		AX,ES			; 内存地址加0x200(512字节)
		ADD		AX,0x0020
		MOV		ES,AX			; 更新ES
		ADD		CL,1			; 扇区号加1
		CMP		CL,18			; 如果扇区号<=18
		JBE		readloop		; 跳转到readloop
		MOV		CL,1			; 18个扇区全部读完,扇区号重置为1,并更新磁头
		ADD		DH,1			; 磁头号加1
		CMP		DH,2
		JB		readloop		; 如果磁头号<2,跳转到readloop
		MOV		DH,0			; 2个磁头全部读完,磁头号重置为0,并更新柱面
		ADD		CH,1			; 柱面号加1
		CMP		CH,CYLS 		; CYLS = 10
		JB		readloop		; 如果柱面号<CYLS,跳转到readloop

汇编程序6:BIOS的初始化——画面模式设定(存储在内存中,以备后用)与得到键盘状态

; haribote-os
; TAB=4

; BOOT_INFO的定义
CYLS	EQU		0x0ff0			; 设置启动扇区数
LEDS	EQU		0x0ff1			; LED状态
VMODE	EQU		0x0ff2			; 显示模式,8位颜色
SCRNX	EQU		0x0ff4			; 屏幕分辨率X
SCRNY	EQU		0x0ff6			; 屏幕分辨率Y
VRAM	EQU		0x0ff8			; 图形缓冲区的起始地址

		ORG		0xc200			; 从这个地址开始加载程序

		MOV		AL,0x13			; 设置VGA图形模式为320x200x8位颜色
		MOV		AH,0x00
		INT		0x10
		MOV		BYTE [VMODE],8	; 设置当前模式为8位颜色
		MOV		WORD [SCRNX],320	; 设置屏幕宽度为320
		MOV		WORD [SCRNY],200	; 设置屏幕高度为200
		MOV		DWORD [VRAM],0x000a0000	; 设置图形缓冲区起始地址为0x000a0000

; 从键盘读取LED状态并保存到内存

		MOV		AH,0x02
		INT		0x16 			; 调用键盘BIOS
		MOV		[LEDS],AL		; 保存LED状态到内存

fin:
		HLT					; 停止CPU
		JMP		fin			; 无限循环

上述汇编程序中BIOS参与的事情:

  • 画面模式的设定
  • 磁盘的读写
  • 得到键盘状态

由于BIOS是16位机器语言模式的,而现在要逐渐转入32位机器语言模式,二者互不兼容。这也就意味着进入32位系统后就不能再使用BIOS的功能了,故在进入操作系统之前必须要提前做好BIOS要做的事情。

posted @ 2025-07-16 12:55  jxs123  阅读(22)  评论(0)    收藏  举报