操作系统开发教程#02-1
在上一节里,我们写了一个非常简单的“操作系统”,看起来还不错,对吗?不过你好像看起来根本不知道发生了什么。(如果你已经有了很好的汇编基础,可以跳过以下内容,进入下一节)
对于第一行,“; MKOS-0-0 上节代码”,这是一个注释,不起任何作用(“注释不是用来解释程序或用来记录作者的话之类的吗?”,拜托,我基本都不看也不写注释的欸。)在汇编里,从“;”开始到这一行的结束都会算作注释(类似于c中的“//”)
第二行,“ORG 0x7c00”是一句伪指令【1】,作用是告诉编译器这个程序将来会被装载到0x7c00的位置
第三行,“JMP start”,即“jump”到start所在的位置(类似于c中的“goto”)
第四行,“Message0”为标签名,可以在同一行写语句(可不加":",如“ADR0 db 0x7c00”),也可以在下面写语句(加":",如“Start:”);“DB ……”为直接在程序里写入字节。
第六行,返回(Return)指令,返回到上一个调用(Call)指令。(类似于c中的“return ;”)
第八行,转移(Move)指令,将SI寄存器【2】所对于内存的值赋给AL 寄存器。(类似于c中的“AL=((char*)0)[SI];”)
第九行,加法(Add)指令,将SI寄存器的值加1。(类似于c中的“SI+=1;”)
第十行,比较(Compare)指令,将AL寄存器的值与0比较,比较结果存入flag(标志)寄存器。
第十一行,等于则跳转(Jump if equal)指令,跳转到rtn标签所在位置。
第十四行,调用中断(interrupt)【3】0x10
第二十三行,调用指令,调用putloop。(类似于c中的“putloop();”)
第二十四行,跳转到当前($)
第二十六行,伪指令,重复(Times)510-$+$$【4】次DB 0伪指令
第二十七行,伪指令,写入0x55,0xaa【5】
【1】:伪指令不是真正的指令,也就是不是最终的指令,而是用于指示汇编程序如何汇编源程序。至于为什么是7c00,这个比 32KB 小1024字节的地方。可以参见计算机是如何启动的【7】以及Why BIOS loads MBR into 0x7C00 in x86 ?【6】或者我上一篇文章。
【2】:寄存器是CPU内部用来存放数据的一些小型存储区域,用来暂时存放参与运算的数据和运算结果。在x86的16位CPU上的寄存器,通常可以分为“通用寄存器”“指针和变址寄存器”“段寄存器”和“标志寄存器”。对于通用寄存器,有

十六位 高八位 低八位 名称 用途

AX AH AL 累加器 些指令约定以AX(或AL)为源或目的寄存器。

BX BH BL 基址寄存器 BX可用作间接寻址的地址寄存器和基地址寄存器,BH、BL可用作8位通用数据寄存器。

CX CH CL 计数寄存器 CX在循环和串操作中充当计数器,指令执行后CX内容自动修改,因此称为计数寄存器。

DX DH DL 数据寄存器 除用作通用寄存器外,在I/O指令中可用作端口地址寄存器,乘除指令中用作辅助累加器。

对于指针和变址寄存器,有

十六位 名称 用途

BP 基址指针寄存器 BP中存放现行堆栈段中一个数据区的“基址”的偏移量。

SP 堆栈指针寄存器 SP寄存器在堆栈操作中使用,PUSH和POP指令是从SP寄存器得到现行堆栈段的段内地址偏移量,所以称SP寄存器为堆栈指针,SP始终指向栈顶。

SI 源变址寄存器 为访问现行数据段提供段内地址偏移量。其中源操作数的偏移量存放在SI中,目的操作数的偏移量存放在DI中。
DI 目的变址寄存器

IP 指令指针寄存器 用来存放将要执行的下一条指令在现行代码段中的偏移地址。程序运行中,它由BIU自动修改,使IP始终指向下一条将要执行的指令的地址,因此它是用来控制指令序列的执行流程的,是一个重要的寄存器。8086程序不能直接访问IP,但可以通过某些指令修改IP的内容。

对于段寄存器,有

十六位 名称 用途

CS 代码段寄存器 由它们给出相应逻辑段的首地址,称为“段基址”。段基址与段内偏移地址组合形成20位物理地址,段内偏移地址可以存放在寄存器中,也可以存放在存储器中。
DS 数据段寄存器
SS 堆栈段寄存器
ES 附加段寄存器

标志寄存器FR,有

一位 用途

CF 用于寄存程序运行的状态信息,这些标志往往用作后续指令判断的依据。
PF
AF
ZF
SF
OF

IF 用于控制CPU的操作,是人为设置的。
DF
TF

【3】指处理机处理程序运行中出现的紧急事件的整个过程.程序运行过程中,系统外部、系统内部或者现行程序本身若出现紧急事件,处理机立即中止现行程序的运行,自动转入相应的处理程序(中断服务程序),待处理完后,再返回原来的程序运行,这整个过程称为程序中断;当处理机接受中断时,只需暂停一个或几个周期而不执行处理程序的中断,称为简单中断.中断又可分为屏蔽中断和非屏蔽中断两类.可由程序控制其屏蔽的中断称为屏蔽中断或可屏蔽中断.屏蔽时,处理机将不接受中断.反之,不能由程序控制其屏蔽,处理机一定要立即处理的中断称为非屏蔽中断或不可屏蔽中断.非屏蔽中断主要用于断电、电源故障等必须立即处理的情况.处理机响应中断时,不需执行查询程序.由被响应中断源向CPU发向量地址的中断称为向量中断,反之为非向量中断.向量中断可以提高中断响应速度。
分类:
·可屏蔽中断(maskable interrupt)。硬件中断(Hardware Interrupt)
的一类,可通过在中断屏蔽寄存器中设定位掩码来关闭。
·非可屏蔽中断(non-maskable interrupt,NMI)。硬件中断的一类,无法通过在中断屏蔽寄存器中设定位掩码来关闭。典型例子是时钟中断(一个硬件时钟以恒定频率—如50Hz—发出的中断)。
·处理器间中断(interprocessor interrupt)。一种特殊的硬件中断。由处理器发出,被其它处理器接收。仅见于多处理器系统,以便于处理器间通信或同步。
·伪中断(spurious interrupt)。一类不希望被产生的硬件中断。发生的原因有很多种,如中断线路上电气信号异常,或是中断请求设备本身有问题。
·软件中断(Software Interrupt)是一条CPU指令,用以自陷一个中断。由于软中断指令通常要运行一个切换CPU至内核态(Kernel Mode/Ring 0)的子例程,它常被用作实现系统调用(System call)。——引自百度百科
【4】$当前位置 $$当前段起始位置
【5】引导程序标记,在引导扇区的512字节中最后两个字节写入55aa标记此扇区为引导扇区。至于为什么是55AA,那得问IBM的爷爷们了。
【6】https://www.glamenv-septzen.net/en/view/6
【7】https://www.ruanyifeng.com/blog/2015/09/0x7c00.html