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

第三天(续)

第三小节

注明一下,源代码中有很多原作者留的日文注释,我没去一条一条删去,不管就行了

harib00c:

readloop:
		MOV		SI,0			; 记录失败次数的寄存器
retry:
		MOV		AH,0x02			; AH=0x02 : 僨傿僗僋撉傒崬傒
		MOV		AL,1			; 1个扇区
		MOV		BX,0
		MOV		DL,0x00			; A僪儔僀僽
		INT		0x13			; 僨傿僗僋BIOS屇傃弌偟
		JNC		next			; 僄儔乕偑偍偒側偗傟偽next傊
		ADD		SI,1			; SI加一
		CMP		SI,5			; 比较SI和5
		JAE		error			; SI >= 5 跳error
		MOV		AH,0x00
		MOV		DL,0x00			; A僪儔僀僽
		INT		0x13			; 僪儔僀僽偺儕僙僢僩
		JMP		retry
next:
		MOV		AX,ES			; 内存后移0x200
		ADD		AX,0x0020
		MOV		ES,AX			; ADD ES,0x020 偲偄偆柦椷偑側偄偺偱偙偆偟偰偄傞
		ADD		CL,1			; CL偵1傪懌偡
		CMP		CL,18			; CL偲18傪斾妑
		JBE		readloop		; CL <= 18 偩偭偨傜readloop傊

之所以不在INT 0x13中用MOV AL,0x17指定18个扇区,是因为BIOS在读盘时,指定处理的扇区数时有限制,作者这里也没有说清楚,但在Bochs 2.4.5中不能一次指定72个扇区以上。

7220       if ((drive > 1) || (head > 1) || (sector == 0) ||
7221           (num_sectors == 0) || (num_sectors > 72)) {
7222         BX_INFO("int13_diskette: read/write/verify: parameter out of range\n");
7223         SET_AH(1);
7224         set_diskette_ret_status(1);
7225         SET_AL(0); // no sectors read
7226         SET_CF(); // error occurred
7227         return;
7228       }

具体可以看下这个:https://*.com/questions/62483420/int-13h-effective-sector-size

Bochs

bochs是X86硬件平台的开源模拟器,完全可以通过软件来给我们提供各种所需的硬件资源。

和bochs类似的虚拟机软件还有我们常用的VMware、Virtuabox,但区别也是明显的。

bochs是完全依靠软件来模拟整个环境的:从启动到重启包括PC的外设键盘、鼠标、磁盘以及网卡等,全部都是由软件来模拟的,而其余软件则不然(部分依赖于硬件)。

现在0x8200~0xa3ff中装载了磁盘的512×17=8704个字节(一个扇区512字节)


第四小节

harib00d

CYLS	EQU		10				; 相当于C语言的#define CYLS = 10,EQU是equal的缩写,相当于"="
·····
next:
		MOV		AX,ES			; 傾僪儗僗傪0x200恑傔傞
		ADD		AX,0x0020
		MOV		ES,AX			; ADD ES,0x020 偲偄偆柦椷偑側偄偺偱偙偆偟偰偄傞
		ADD		CL,1			; CL偵1傪懌偡
		CMP		CL,18			; CL偲18傪斾妑
		JBE		readloop		; CL <= 18 偩偭偨傜readloop傊
		MOV		CL,1
		ADD		DH,1
		CMP		DH,2
		JB		readloop		; DH < 2 偩偭偨傜readloop傊
		MOV		DH,0
		ADD		CH,1
		CMP		CH,CYLS
		JB		readloop		; CH < CYLS 偩偭偨傜readloop傊

扇区:C0-H0-S1:柱面0,磁头0,扇区1,柱面cylinder,磁头head,扇区sector

10×2×18×512=184320byte=180KB 十个柱面


第五、六小节

非常好的一张图片,说明了软盘的存储结构30天自制操作系统——第三天

软盘保存文件,文件名会写在0x002600处,文件的内容会写在0x004200之后的地方

用make install命令将haribote.nas用nask编译输出为sys文件

我遇到如下报错,但是不影响sys文件的生成
30天自制操作系统——第三天

磁盘上0x004200号地址的程序,因为装载到内存中是从0x8000号地址开始的,因此磁盘0x4200处的内容在内存0x8000+0x4200=0xc200处

注意此时引导区的文件差不多就写完了为ipl.nas


第七小节

http://oswiki.osask.jp/?(AT)BIOS

还是上面那个日文网页

有个问题,为啥是内存的0x0ff0,搜了一下也没有解释,求指教

; haribote.nas文件
; 因为(磁盘上10个柱面的数据)读完了执行haribote.sys!

        MOV        [0x0ff0],CH        ; 将 读取柱面的数量(此时是10)写到内存的0x0FF0,为什么是0x0FF0?
        JMP        0xc200

make run结果:黑屏


第八小节

; haribote-os
; TAB=4

; 有关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僌儔僼傿僢僋僗丄320x200x8bit僇儔乕
		MOV		AH,0x00
		INT		0x10
		MOV		BYTE [VMODE],8	; 记录画面模式,指令中制定了BYTE,则用8个位来存储8这个数值,内存地址为VMODE,即0x0ff2
		MOV		WORD [SCRNX],320; 一个字来存储
		MOV		WORD [SCRNY],200
		MOV		DWORD [VRAM],0x000a0000 ; 双字

; 

		MOV		AH,0x02
		INT		0x16 			; keyboard BIOS
		MOV		[LEDS],AL

按键锁定和换档状态获取

INT=0x16

AH= 0x02状态下的AL返回值:

bit0:右移

bit1:左移

bit2:控制

bit3:Alt

bit4:滚动锁定

bit5:数字锁

bit6:大写锁定

bit7:插入模式

(翻译还是Google翻译的准

好家伙,github上有汉化了的,让我看日文看了这么久(—_—) https://github.com/yourtion/30dayMakeOS

不过给出的文件都是一天的最终版,没有一天里逐步改进的过程


第九小节

添加了亿点点细节

主要加的功能是把.c变为.sys文件

具体内容(如何调用C语言写的程序)作者说后面再讲


第十节

WCOFF模式搜不到,但COFF是指通用对象文件格式

; naskfunc.nas文件
; naskfunc
; TAB=4

[FORMAT "WCOFF"]				; 制作目标文件的模式	
[BITS 32]						; 制作32位模式用的机器语言


; 制作目标文件的信息

[FILE "naskfunc.nas"]			; 源文件名信息

		GLOBAL	_io_hlt			; 程序中包含的函数名


; 以下是实际的函数

[SECTION .text]		; 目标文件中写了这些后再写程序

_io_hlt:	; void io_hlt(void);
		HLT
		RET
//bootpack.c文件
/* 告诉C编译器,有一个函数在别的文件里 */

void io_hlt(void);

/* 是函数声明却不用{},而用;,这表示的意思是:
	函数在别的文件中,你自己找一下 */

void HariMain(void)
{

fin:
	io_hlt(); /* 执行naskfunc.nas中的_io_hlt函数 */
	goto fin;

}

c++中一个文件怎么调用另外一个文件里的函数:

前提为,另一个文件中的函数,不能是静态函数,即不能有static修饰。
调用方法,在调用前进行声明,然后直接调用即可。

声明方法:
1 直接在调用前,写函数声明:
如调用函数为int func(int a),那么在调用前只需要
int func(int a);
这样声明后,即可使用func。

2 将声明写在头文件中。
如在名为func.h的头文件中加入
int func(int a);
然后在调用的源文件中,引用
#include “func.h”

即可调用func

此处属于第一种,但是还未使用io_hlt函数

修饰。

调用方法,在调用前进行声明,然后直接调用即可。

声明方法:
1 直接在调用前,写函数声明:
如调用函数为int func(int a),那么在调用前只需要
int func(int a);
这样声明后,即可使用func。

2 将声明写在头文件中。
如在名为func.h的头文件中加入
int func(int a);
然后在调用的源文件中,引用
#include “func.h”

即可调用func

此处属于第一种,但是还未使用io_hlt函数

话说作者第三天是不是打了鸡血。。。


欢迎一起学习和讨论

欢迎关注个人其他账号:

B站账号:哔哩哔哩 无名-易

Gitee账号:gitee账号

GitHub账号:GitHub

上一篇:5801: 七夕祭(贪心)


下一篇:监控服务zabbix----浅谈