操作系统开发日记-day4

; 今日添加的内容

		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			; A驱动器
		INT		0x13			; 磁盘BIOS调用
		JC		error

JC指令的功能:
所谓JC,就是jump if carry,的缩写,意思是如果仅为标志位1的话,就跳转。

关于INT 0x13这个指令,我们知道是要调用BIOS的0x13号函数,但还不明白它到底是干什么用的。

我们可以找到如下的内容:

  • 磁盘读、写,扇区校验,以及寻道
  • AH=0x02(读盘)
  • AH=0x03
  • AH=0x04
  • AH=0x0c
  • AL=处理对象的扇区数;(智能同时处理连续的扇区)
  • CH=柱面号&0xff
  • CL=扇区号(0-5位)|(柱面号&0x300)>>2;
  • DH=磁头号
  • DL=驱动器号;
  • ES:BX=缓冲地址;(校验即寻道时不使用)
  • 返回值
  • FLACS.CF0:没有错误,AH0
  • FLACS.CF==1:有错误,错误号码存入AH内

返回值里的FLACS.CF的意思是,调用了BIOS中的这一个函数之后,如果没有错误,进位标志就是0,如果有错误,进位标志就是1。

在CPU中有一些只有1位的寄存器。像这种1位寄存器我们称之为标志。标志在英文中未flag,还有其他的几个1位寄存器。CH、CL、DH、DL分别是柱面号、扇区号、磁头号、驱动器号。

软盘的结构图:
在这里插入图片描述

在这里插入图片描述
到目前为止开发的程序还没有考虑段寄存器,不过实际上我们要指定内存的什么地址,都必须同时指定段寄存器,一般如果省略的话就会把DS数据段寄存器当做默认的段寄存器。

在这里插入图片描述
双击!cons_nt.bat,在cmd中输入make run
在这里插入图片描述
在这里插入图片描述
没有什么错误信息显示,如果有错误信息的话会显示错误信息。

由于软盘的不可靠,有时候会发生不能读数据的状况,这时候重新再读一次就行了。所以即使那么一、两次错误,就让它重新再读几次就可以了,在上面的程序的基础上加上如下的优化,就可以实现出错时循环读取。
在这里插入图片描述
JNC指令的功能:和JC的作用相反,也就是进位标志如果是0的话就跳转。JAE也是条件跳转,意思是大于或等于时跳转。

在重新读盘之前,做了AH=0x00,DL=0x00,INT 0x13的处理,作用是复位软盘的状态,再读一次。

读18个扇区
在这里插入图片描述
用循环的方式读取扇区,也就是用循环的方式将上面的功能重复。最后显示的画面虽然与之前没有不同,但是这个时候我们已经把磁盘上的512*17个字节读到内存上0x8200~0xa3ff了。

接下来读取10个柱面。这里另外加一个指令EQU,它是equal的缩写,CYLS EQU 10的意思相当于CYLS=10.

CYLS EQU 10;读到什么程度
ORG 0x7c00;这个程序会被读取到哪里

额外话题:向一个空软盘保存文件时
(1)文件名会写在0x002600以后的地方
(2)文件的内容会写在0x004200以后的地方

现在所写的程序都是从启动区开始的,把磁盘上的内容装载到内存0x8000号地址,所以磁盘0x4200处的内容就应该位于内存0x8000+0x4200=0xc200号地址。

在另外一个文件haribote.nas中写入ORG 0xc200,然后在ipl.nas处理的最后加上JMP 0xc200指令,就可以从ipl.nas的最后跳转到这个内存地址继续执行代码内容。

在这里插入图片描述
接着,我们在haribote.nas中写入下面的指令,让最终命令行窗口出现一个全黑的窗口

; haribote-os
; TAB=4

		ORG		0xc200			; 这个程序会被读取到哪里

		MOV		AL,0x13			; VGA图形,320x200x8bit颜色
		MOV		AH,0x00
		INT		0x10
fin:
		HLT
		JMP		fin

设定AH=0x00后,调用显卡的BIOS的0x10号函数,就可以切换显示模式了。这里选择0x13画面模式,8位彩色模式可以使用256种颜色。

在这里插入图片描述
make run之后成功出现了一个黑窗口,说明程序运行正常,变成了图形模式,光标消失。
在这里插入图片描述
32位模式前期准备
修改harbote.nas

;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      ;图像缓冲区的开始地址,VRAM指显卡内存

    ORG     0xc200      ;程序要装载的地方

    MOV     AL,0x13     ;VGA显卡,32x00x8位颜色
    MOV     AH,0x00     ;设置AH=0x00,调用显卡BIOS函数,就可以切换显示模式了,AL中设置模式
    INT     0x10        

    MOV     BYTE [VMODE],8    ; 记录画面模式
    MOV     WORD [SCRNX],320
    MOV     WORD [SCRNY],200
    MOV     DWORD [VRAM],0x000a0000 ;这种画面模式下"VRAM是0xa00000xaffff64KB

; 用BIOS取得键盘上各种LED指示灯的状态

    MOV     AH,0x02
    INT     0x16            ; keyboard BIOS
    MOV     [LEDS],AL
fin:
    HLT
    JMP fin

所谓32位模式,是指CPU的模式。CPU有16位和32位两种模式。如果以16位模式启动的话,用AX和CX等16寄存器会非常方便,反过来,像EAX和ECX等32位的寄存器,使用就非常不方便了。而且,在16位和32位下,机器语言的命令代码不一样。同样的机器语言,解释的方法也不一样,所以16位模式的机器语言在32位模式下不能运行,反之亦然。

不过有一点,在32位模式下,就不能调用BIOS的函数了,因为BIOS是16位机器语言写的。如果我们有什么事要BIOS来做,那就放到开头做,一旦进入32位模式,就不能调用BIOS函数了。(也有从32位返回16位的方法,不过有点复杂)

我们已经从BIOS获得了画面模式,接下来就是要从BIOS获得键盘状态,所谓的键盘状态,就是NumLock是ON还是OFF等这些状态。

猜你喜欢

转载自blog.csdn.net/weixin_45394002/article/details/113823572