【写一个操作系统】3—汇编语言学习及Makefile入门

今天的主要任务是通过对helloos.nas核心代码汇的理解进行编语言的学习,还有就是Makefile的学习。

汇编代码

主要是对上次的汇编文件helloos.nas核心部分的学习,核心部分的原代码如下:

DB		0xb8, 0x00, 0x00, 0x8e, 0xd0, 0xbc, 0x00, 0x7c
		DB		0x8e, 0xd8, 0x8e, 0xc0, 0xbe, 0x74, 0x7c, 0x8a
		DB		0x04, 0x83, 0xc6, 0x01, 0x3c, 0x00, 0x74, 0x09
		DB		0xb4, 0x0e, 0xbb, 0x0f, 0x00, 0xcd, 0x10, 0xeb
		DB		0xee, 0xf4, 0xeb, 0xfd

看起来晦涩难懂,所以就改写为下面的样子,方便学习:

; hello-os
; TAB=4

		ORG		0x7c00			; 指明程序装载地址

; 以下的记述用于标准FAT12格式的软盘

		JMP		entry
		DB		0x90
		DB		"HELLOIPL"		; 启动区的名称可以是任意字符串(8字节)
		DW		512				;规定 每个扇区的大小(必须为512字节)
		DB		1				; 规定簇的大小,以扇区为单位(必须为1个扇区)
		DW		1				; 规定FAT的起始位置(一般是从第一个位置开始)
		DB		2				; FAT的个数(必须为2)
		DW		224				; 根目录的大小(一般设置224项)
		DW		2880			; 规定磁盘大小(必须2880个扇区大小)
		DB		0xf0			; 规定磁盘的种类
		DW		9				; 规定FAT的长度(必须是9个扇区)
		DW		18				; 规定一个磁道的扇区个数(必须18个)
		DW		2				; 规定磁头数(必须2个)
		DD		0				; 不使用分区,必须为0
		DD		2880			; 重新确定磁盘大小为2880个扇区
		DB		0,0,0x29		; 教程也不知道这是什么
		DD		0xffffffff		; たぶんボリュームシリアル番号
		DB		"HELLO-OS   "	; 磁盘的名称
		DB		"FAT12   "		; 磁盘的格式
		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加一
		CMP		AL,0
		JE		fin
		MOV		AH,0x0e			; 显示一个字符
		MOV		BX,15			; 指定字符颜色
		INT		0x10			; 调用显卡BIOS
		JMP		putloop
fin:
		HLT						; 让CPU处于待机状态
		JMP		fin				; 跳转到fin,即无限循环

msg:
		DB		0x0a, 0x0a		; 换行俩次
		DB		"hello, world"
		DB		0x0a			; 换行
		DB		0

接下来对代码进行由上而下的讲解
OGR指令

OGR来源于origin,意为起点、源头。
OGR指令会告诉汇编语言编译器,把程序装载到内存中的哪个地址,如示:ORG 0x7c00 ; 指明程序装载地址,这就告诉汇编语言编译器将此程序装载到内存中的0x7c00地址。
注意:0x7c00是专用的启动区装载地址

JMP指令

JMP指令来源于jump,意为跳转。
JMP指令就像C语言中的goto语句,JMP entryentry是标号,跳转语句会跳转至标号标记的地方执行程序。标号的值就是对应程序的地址。

MOV指令

MOV指令来源于move,意为移动。
MOV指令是最常用的指令,在这相当于赋值指令:MOV A,B 意为将B的值赋给A。

CPU寄存器

CPU中有一种存储电路,名字叫寄存器,在机器语言中就相当于变量,寄存器的名称就是变量名,寄存器中的内容就是变量内容

这些都是16位寄存器,每个寄存器可以储存16个二进制数:

寄存器代码寄存器位数寄存器名称
AX16位(accumulator)累加寄存器
CX16位(counter)计数寄存器
DX16位(data)数据寄存器
BX16位(base)基址寄存器
SP16位(stack pointer)栈指针寄存器
BP16位(base pointer)基址指针寄存器
SI16位(source index)源变址寄存器
DI16位(destination index)目的变址寄存器

AX、CX、DX、BX寄存器名称中的X(extend)代表扩展,之所以是扩展,因为之前的CPU中寄存器都是8位的,扩展了一倍所以加了个X。
实际上针对AX、CX、DX、BX这四个寄存器CPU还有8个寄存器

寄存器代码寄存器位数寄存器名称
AL8位(accumulator low)累加寄存器低位
CL8位(counter low)计数寄存器低位
DL8位(data low)数据寄存器低位
BL8位(base low)基址寄存器低位
AH8位(accumulator high)累加寄存器高位
CH8位(counter high)计数寄存器高位
DH8位(data high)数据寄存器高位
BH8位(base high)基址寄存器高位

可以看出这都是AX、CX、DX、BX这四个寄存器的衍生,L代表相应寄存器的低8位,H代表相应寄存器的高8位,实际上这些寄存器的储存地址和AX、CX、DX、BX是相同的,只不过是把AX、CX、DX、BX这四个寄存器的地址细分了一下。

MOV指令新含义:MOV AL,[SI]

上面介绍的MOV指令就是一个简单的赋值语句,在这MOV语句中出现了 [],这代表的意义就不同了,MOV指令的数据传送源和传送目的地不仅可以是寄存器或者数字,也可以是内存地址,[]中的值代表内存地址
这里还涉及到保留字的知识:BYTE、WORD、DWORD这三个保留字规定了数据的大小,BYTE代表8位、WORD代表16位、DWORD代表32位。
例:MOV WORD[678],123这句代码的意思就是:将123这个数据存放在内存的678号地址中,占用的空间大小为16位。
MOV AX,WORD[456] 这段代码的意思是:将内存的456地址起的16位的数据存入AX寄存器中。

ADD指令

ADD是加法指令,ADD SI,1就是给SI加一。

CMP、JE指令

CMP		AL,0
JE		fin

CMP指令是比较指令,JE是跳转指令,CMP A,B就是比较A、B是否相同,如果相同就跳转执行JE的指令,如果不相同就继续执行下面的程序
上面这段代码的意思就是:比较AL寄存器中的值和0,如果相等就跳转执行fin部分的程序,如果不同就继续执行下面程序。

INT指令与BIOS

首先说一下什么是BIOS:BIOS是电脑出场时组装在ROM中程序,BIOS为“basic input output system”的缩写,意为基本输入输出系统,在BIOS中写入了常用的各种函数集,而INT的作用就是调用这些函数的。BIOS为“basic input output system”的缩写,意为基本输入输出系统。

HLT指令

HLT来源于:halt,意为停止。HLT指令就是令CPU进入待机,只要外部发生变化CPU就会醒过来,继续执行程序,这样可以减少CPU功耗。

制作启动区程序

因为在之前的程序中helloos.nas不仅仅包含了启动区的内容,还包含了一些启动区之外的东西。因为之前是利用汇编语言编译器一次性制作整个磁盘映像的,这在之后的开发中是不方便的,所以我们决定单独制作启动区的程序

  • 首先再之前的helloos.nas文件中去掉启动区之外的代码,改名为ipl.nas,这就做好了只有启动区的汇编文件
  • 接下来更改一下asm.batasm.bat的作用是生成映像文件,本来是生成helloos.img镜像文件的,现在要生成ipl.binipl.lst文件。(ipl.lst是列表文件,可以用来简单确认每个指令是怎样翻译成机器语言的)

asm.bat
..\z_tools\nask.exe ipl.nas ipl.bin ipl.lst

  • 然后就是以启动区的二进制文件ipl.bin为基础生成helloos.img镜像文件。通过添加一个批处理文件`makeimg.bat:来实现,原理是:利用磁盘映像管理工具,先读入一个空白的磁盘映像文件,在文件开头写入ipl.bin,最后将结果输出为helloos.img映像文件

makeimg.bat:
..\z_tools\edimg.exe imgin:../z_tools/fdimg0at.tek wbinimg src:ipl.bin len:512 from:0 to:0 imgout:helloos.img

  • 最后,启动区文件就做好了,这下程序的运行就是:打开命令窗口,在窗口中按顺序输入asm、makeimg、run这三个命令,程序就可以运行了。
    运行结果如下:
    在这里插入图片描述

Makefile

我第一次对Makefile的理解就是,Makefile是我程序执行的管家,只要把所有的命令(批处理文件)放在Makefile中,在Makefile中规定命令执行的条件和步骤(相当于教管家如何做事),在随后的程序运行过程中指挥Makefile就可以了(只给管家下命令)。我认为Makefile是一般批处理文件的上层文件,Makefile也可以看作是一个批处理文件。

Makefile的写法比较简单,生成一个不带拓展名的Makefile文件,利用文本编辑器向Makefile中写入各种命令和操作。(Makefile中的注释为#)

# 文件生成规则

ipl.bin : ipl.nas Makefile
	../z_tools/nask.exe ipl.nas ipl.bin ipl.lst

helloos.img : ipl.bin Makefile
	../z_tools/edimg.exe   imgin:../z_tools/fdimg0at.tek \
		wbinimg src:ipl.bin len:512 from:0 to:0   imgout:helloos.img

# 命令

asm :
	../z_tools/make.exe -r ipl.bin

img :
	../z_tools/make.exe -r helloos.img

run :
	../z_tools/make.exe img
	copy helloos.img ..\z_tools\qemu\fdimage0.bin
	../z_tools/make.exe -C ../z_tools/qemu

install :
	../z_tools/make.exe img
	../z_tools/imgtol.com w a: helloos.img

clean :
	-del ipl.bin
	-del ipl.lst

src_only :
	../z_tools/make.exe clean
	-del helloos.img

Makefile强大之处就是很“智能”,因为我已经将程序执行的所有操作都写入Makefile中了,在程序执行的过程中Makefile会自动生成各种所需的文件,也会自动执行各种批处理文件,还会刷新文件(就是我修改了命令的话,Makefile会改变之前的动作,适应新命令)。还可以在Makefile中对命令进行重定义。
如此一来,只要在命令窗口中输入make run命令,Makefile就会执行所有操作,包括生成镜像文件和启动模拟器。

看到一篇博客对Makefile的描述非常详细,链接:
Makefile

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值