30天自制操作系统:第三天

2024-05-31 17:48

本文主要是介绍30天自制操作系统:第三天,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

对第二天代码进行了修改,只打印hello ,uos没一点意思。

读取磁盘上10个柱面的1-18个扇区,(目前ssd已经没有柱面这个概念了)。读出来的数据放入内存0x8200起始的地方。

启动区放在0x8000内存扇区中。为什么要放在0x8000以后的内存中的呢? 只是因为这块内存没有用而已。

为什么要将启动程序(img的0扇区)放在0x7c00处? 这是ibm规定的。

向一个空软盘保存文件时:

​ 1.文件名会写在0x002600以后的地方。

​ 2.文件内容会写在0x004200以后的地方。

所以若想启动位于0x004200的程序,就得让引导程序运行完成后跳转到0x8000+0x4200=0xc200处。

作者这一块写的很混乱啊,咱们整理一下为啥是0xc200地址,看下图:

在这里插入图片描述

bios会把磁盘0位置的内容拷贝到内存0x7c00这个位置然后跳过去执行,
也就是把A拷贝到了内存,然后执行A
A会把磁盘后面的内容从内存0x8200开始拷贝
这样的话磁盘0x4200位置就会对应到内存0xC200
一个扇区512字节,十六进制表示就是0x200

程序的执行情况:

1.bios读取磁盘0扇区到0x7c00处。

2.bios跳转到0x7c00处开始执行,该处为ipl10.nas程序,该程序功能为加载磁盘[1-最后]扇区到内存的0x8200处。并跳转到0xc200处执行。

3.0xc200处为asmhead.nas程序,该程序功能为,调用显卡bios,设置画面模式,调用操作系统代码。

4.操作系统代码目前就一个功能就是让cpu睡眠,开始进入c程序。

下面根据功能修改代码:

1.修改ipl.nas

ipl10.nas:

; haribote-ipl
; TAB=4CYLS	EQU		10				; 声明CYLS=10ORG		0x7c00			; 指明程序装载地址; 标准FAT12格式软盘专用的代码 Stand FAT12 format floppy codeJMP		entryDB		0x90DB		"HARIBOTE"		; 启动扇区名称(8字节)DW		512				; 每个扇区(sector)大小(必须512字节)DB		1				; 簇(cluster)大小(必须为1个扇区)DW		1				; FAT起始位置(一般为第一个扇区)DB		2				; FAT个数(必须为2)DW		224				; 根目录大小(一般为224项)DW		2880			; 该磁盘大小(必须为2880扇区1440*1024/512)DB		0xf0			; 磁盘类型(必须为0xf0)DW		9				; FAT的长度(必??9扇区)DW		18				; 一个磁道(track)有几个扇区(必须为18)DW		2				; 磁头数(必??2)DD		0				; 不使用分区,必须是0DD		2880			; 重写一次磁盘大小DB		0,0,0x29		; 意义不明(固定)DD		0xffffffff		; (可能是)卷标号码DB		"HARIBOTEOS "	; 磁盘的名称(必须为11字?,不足填空格)DB		"FAT12   "		; 磁盘格式名称(必??8字?,不足填空格)RESB	18				; 先空出18字节; 程序主体entry:MOV		AX,0			; 初始化寄存器MOV		SS,AXMOV		SP,0x7c00MOV		DS,AX; 读取磁盘MOV		AX,0x0820MOV		ES,AXMOV		CH,0			; 柱面0MOV		DH,0			; 磁头0MOV		CL,2			; 扇区2readloop:MOV		SI,0			; 记录失败次数寄存器retry:MOV		AH,0x02			; AH=0x02 : 读入磁盘MOV		AL,1			; 1个扇区MOV		BX,0MOV		DL,0x00			; A驱动器INT		0x13			; 调用磁盘BIOSJNC		next			; 没出错则跳转到nextADD		SI,1			; 往SI加1CMP		SI,5			; 比较SI与5JAE		error			; SI >= 5 跳转到errorMOV		AH,0x00MOV		DL,0x00			; A驱动器INT		0x13			; 重置驱动器JMP		retry
next:MOV		AX,ES			; 把内存地址后移0x200(512/16十六进制转换)ADD		AX,0x0020MOV		ES,AX			; ADD ES,0x020因为没有ADD ES,只能通过AX进行ADD		CL,1			; 往CL里面加1CMP		CL,18			; 比较CL与18JBE		readloop		; CL <= 18 跳转到readloopMOV		CL,1ADD		DH,1CMP		DH,2JB		readloop		; DH < 2 跳转到readloopMOV		DH,0ADD		CH,1CMP		CH,CYLSJB		readloop		; CH < CYLS 跳转到readloop; 读取完毕,跳转到haribote.sys执行!MOV		[0x0ff0],CH		; 记下IPL读到哪里了JMP		0xc200error:MOV		SI,msgputloop:MOV		AL,[SI]ADD		SI,1			; 给SI加1CMP		AL,0JE		finMOV		AH,0x0e			; 显示一个文字MOV		BX,15			; 指定字符颜色INT		0x10			; 调用显卡BIOSJMP		putloopfin:HLT						; 让CPU停止,等待指令JMP		fin				; 无限循环msg:DB		0x0a, 0x0a		; 换行两次DB		"load error"DB		0x0a			; 换行DB		0RESB	0x7dfe-$		; 填写0x00直到0x001feDB		0x55, 0xaa

我们在使用段寄存器时,以ES:BX这种方式表示地址,写成"MOV AL, [ES:BX]"她代表ES×16+BX内存地址。

2.修改asmhead.nas

; haribote-os boot asm
; TAB=4;一些定义
BOTPAK	EQU		0x00280000		; bootpack�̃��[�h��
DSKCAC	EQU		0x00100000		; �f�B�X�N�L���b�V���̏ꏊ
DSKCAC0	EQU		0x00008000		; �f�B�X�N�L���b�V���̏ꏊ�i���A�����[�h�j; 有关BOOT_INFO
CYLS	EQU		0x0ff0			; 设定启动区
LEDS	EQU		0x0ff1
VMODE	EQU		0x0ff2			; 该位置保存颜色数目的信息,颜色的位数。
SCRNX	EQU		0x0ff4			; 该位置保存 分辨率的x
SCRNY	EQU		0x0ff6			; 该位置保存 分辨率的y
VRAM	EQU		0x0ff8			; 图像缓冲区的开始地址。ORG		0xc200			; 这个程序需要装载到内存的什么地方呢。; 画面设定MOV		AL,0x13			; VGA显卡,320*320*8位彩色,调色板模式。MOV		AH,0x00INT		0x10			;调用显卡bios的函数,切换显示模式。MOV		BYTE [VMODE],8	; 将画面模式信息保存到这些内存地址中。MOV		WORD [SCRNX],320MOV		WORD [SCRNY],200MOV		DWORD [VRAM],0x000a0000		
;VRAM指的时显卡内存,也就是用来显示画面的内存。这一块内存地址都对应着画面上的像素。
;VRAM在0xa0000~0xaffff之间的64kb。 VRAM分布在内存分布图中的好几个不同的地方。; 用bios取得键盘上各种led灯的状态。MOV		AH,0x02INT		0x16 			; keyboard BIOSMOV		[LEDS],AL;=====================================后边的留以后再看,这块时调用bootpack.c程序的======================
; 防止PIC接受所有中断
;	AT兼容机的规范、PIC初始化
;	然后之前在CLI不做任何事就挂起
;	PIC在同意后初始化MOV		AL,0xffOUT		0x21,ALNOP						; ; 不断执行OUT指令OUT		0xa1,ALCLI						;进一步中断CPU; ; 让CPU支持1M以上内存、设置A20GATECALL	waitkbdoutMOV		AL,0xd1OUT		0x64,ALCALL	waitkbdoutMOV		AL,0xdf			; enable A20OUT		0x60,ALCALL	waitkbdout; 保护模式转换[INSTRSET "i486p"]				; 说明使用486指令LGDT	[GDTR0]			;设置临时GDTMOV		EAX,CR0AND		EAX,0x7fffffff	; 使用bit31(禁用分页)OR		EAX,0x00000001	; bit0到1转换(保护模式过渡)MOV		CR0,EAXJMP		pipelineflush
pipelineflush:MOV		AX,1*8			;  写32bit的段MOV		DS,AXMOV		ES,AXMOV		FS,AXMOV		GS,AXMOV		SS,AX;bootpack传递MOV		ESI,bootpack	; 源MOV		EDI,BOTPAK		; 目标MOV		ECX,512*1024/4CALL	memcpy; 传输磁盘数据; 从引导区开始MOV		ESI,0x7c00		; 源MOV		EDI,DSKCAC		; 目标MOV		ECX,512/4CALL	memcpy; 剩余的全部MOV		ESI,DSKCAC0+512	; 源MOV		EDI,DSKCAC+512	; 目标MOV		ECX,0MOV		CL,BYTE [CYLS]IMUL	ECX,512*18*2/4	; 除以4得到字节数SUB		ECX,512/4		; IPL偏移量CALL	memcpy; 由于还需要asmhead才能完成
; 完成其余的bootpack任务; bootpack启动MOV		EBX,BOTPAKMOV		ECX,[EBX+16]ADD		ECX,3			; ECX += 3;SHR		ECX,2			; ECX /= 4;JZ		skip			; 传输完成MOV		ESI,[EBX+20]	; 源ADD		ESI,EBXMOV		EDI,[EBX+12]	; 目标CALL	memcpy
skip:MOV		ESP,[EBX+12]	; 堆栈的初始化JMP		DWORD 2*8:0x0000001bwaitkbdout:IN		 AL,0x64AND		 AL,0x02JNZ		waitkbdout		; AND结果不为0跳转到waitkbdoutRETmemcpy:MOV		EAX,[ESI]ADD		ESI,4MOV		[EDI],EAXADD		EDI,4SUB		ECX,1JNZ		memcpy			; 运算结果不为0跳转到memcpyRET
; memcpy地址前缀大小ALIGNB	16
GDT0:RESB	8				; 初始值DW		0xffff,0x0000,0x9200,0x00cf	; 写32bit位段寄存器DW		0xffff,0x0000,0x9a28,0x0047	; 可执行的文件的32bit寄存器(bootpack用)DW		0
GDTR0:DW		8*3-1DD		GDT0ALIGNB	16
bootpack:

3.加入bootpack.c操作系统代码

这个操作系统实现了一个最简单的功能:让cpu睡眠

void io_hlt(void);void HariMain(void)
{fin:io_hlt(); /* 执行naskfunc.nas里边的_io_hlt()函数。 */goto fin;}

4.加入naskfunc.nas

加入这个文件是因为c程序不能调用HLT指令,所以使用c程序调用汇编程序,在汇编程序中用HLT让cpu睡眠。

; naskfunc
; TAB=4[FORMAT "WCOFF"]				; 制作目标文件的模式	
[BITS 32]						; 制作32位模式用的机器语言; 制作目标文件的信息。
[FILE "naskfunc.nas"]			; 源文件名信息GLOBAL	_io_hlt			; 程序中包含的函数名;实际的函数[SECTION .text]		;目标中间中写了这些之后再写程序_io_hlt:	; void io_hlt(void); 这个函数只执行了一个HLT命令,让cpu睡眠。HLTRET

5.运行结果

在这里插入图片描述
本文代码下载地址:https://download.csdn.net/download/u011164819/12981508

这篇关于30天自制操作系统:第三天的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1018622

相关文章

30常用 Maven 命令

Maven 是一个强大的项目管理和构建工具,它广泛用于 Java 项目的依赖管理、构建流程和插件集成。Maven 的命令行工具提供了大量的命令来帮助开发人员管理项目的生命周期、依赖和插件。以下是 常用 Maven 命令的使用场景及其详细解释。 1. mvn clean 使用场景:清理项目的生成目录,通常用于删除项目中自动生成的文件(如 target/ 目录)。共性规律:清理操作

2024网安周今日开幕,亚信安全亮相30城

2024年国家网络安全宣传周今天在广州拉开帷幕。今年网安周继续以“网络安全为人民,网络安全靠人民”为主题。2024年国家网络安全宣传周涵盖了1场开幕式、1场高峰论坛、5个重要活动、15场分论坛/座谈会/闭门会、6个主题日活动和网络安全“六进”活动。亚信安全出席2024年国家网络安全宣传周开幕式和主论坛,并将通过线下宣讲、创意科普、成果展示等多种形式,让广大民众看得懂、记得住安全知识,同时还

Linux操作系统 初识

在认识操作系统之前,我们首先来了解一下计算机的发展: 计算机的发展 世界上第一台计算机名叫埃尼阿克,诞生在1945年2月14日,用于军事用途。 后来因为计算机的优势和潜力巨大,计算机开始飞速发展,并产生了一个当时一直有效的定律:摩尔定律--当价格不变时,集成电路上可容纳的元器件的数目,约每隔18-24个月便会增加一倍,性能也将提升一倍。 那么相应的,计算机就会变得越来越快,越来越小型化。

Java基础回顾系列-第三天-Lambda表达式

Java基础回顾系列-第三天-Lambda表达式 Lambda表达式方法引用引用静态方法引用实例化对象的方法引用特定类型的方法引用构造方法 内建函数式接口Function基础接口DoubleToIntFunction 类型转换接口Consumer消费型函数式接口Supplier供给型函数式接口Predicate断言型函数式接口 Stream API 该篇博文需重点了解:内建函数式

c++习题30-求10000以内N的阶乘

目录 一,题目  二,思路 三,代码    一,题目  描述 求10000以内n的阶乘。 输入描述 只有一行输入,整数n(0≤n≤10000)。 输出描述 一行,即n!的值。 用例输入 1  4 用例输出 1  24   二,思路 n    n!           0    1 1    1*1=1 2    1*2=2 3    2*3=6 4

嵌入式面试经典30问:二

1. 嵌入式系统中,如何选择合适的微控制器或微处理器? 在嵌入式系统中选择合适的微控制器(MCU)或微处理器(MPU)时,需要考虑多个因素以确保所选组件能够满足项目的具体需求。以下是一些关键步骤和考虑因素: 1.1 确定项目需求 性能要求:根据项目的复杂度、处理速度和数据吞吐量等要求,确定所需的处理器性能。功耗:评估系统的功耗需求,选择低功耗的MCU或MPU以延长电池寿命或减少能源消耗。成本

1、简述linux操作系统启动流程

1、简述linux操作系统启动流程 启动第一步--加载BIOS 当你打开计算机电源,计算机会首先加载BIOS信息,BIOS信息是如此的重要,以至于计算机必须在最开始就找到它。这是因为BIOS中包含了CPU的相关信息、设备启动顺序信息、硬盘信息、内存信息、时钟信息、PnP特性等等。开机时将ROM中的指令映射到RAM的低地址空间,CPU读取到这些指令,硬件的健康状况进行检查,按照BIOS中设置的启

操作系统是怎么为不同的程序分配所需的内存空间的

操作系统为不同的程序分配内存空间的过程涉及多个关键步骤,确保每个程序都有其所需的内存资源,同时避免程序之间的冲突。以下是操作系统如何为程序分配内存空间的详细过程: 1. 内存管理的基础概念 虚拟内存:现代操作系统使用虚拟内存机制来为程序提供隔离的内存空间。每个程序运行在其独立的虚拟地址空间中,这使得程序间的内存互不干扰。物理内存:实际的 RAM(随机存取存储器),由操作系统和硬件共同管理。虚拟

【全网最全】2024年数学建模国赛A题30页完整建模文档+17页成品论文+保奖matla代码+可视化图表等(后续会更新)

您的点赞收藏是我继续更新的最大动力! 一定要点击如下的卡片,那是获取资料的入口! 【全网最全】2024年数学建模国赛A题30页完整建模文档+17页成品论文+保奖matla代码+可视化图表等(后续会更新)「首先来看看目前已有的资料,还会不断更新哦~一次购买,后续不会再被收费哦,保证是全网最全资源,随着后续内容更新,价格会上涨,越早购买,价格越低,让大家再也不需要到处买断片资料啦~💰💸👋」�