30天自制操作系统(第02天)–汇编语言学习和MakeFile入门

第二天,我们将之前的程序进一步翻译成汇编语言,进一步了解启动程序到底做了些啥。
还记得第一天中有一部分程序主体么,以及最开头的代码,我们把它们翻译成汇编看看。

; hello-os
; TAB=4
        ORG     0x7c00          ; 指名程序的装载地址
; 以下一段是标准FAT12格式软盘专用的代码

        JMP     entry      
        DB      0x90
        DB      "HELLOIPL"      ; 引导扇区的名称,随意写,8字节
        DW      512             ; 每个扇区(sector)的大小,必须是512
        DB      1               ; 簇(cluster)的大小,必须为1
        DW      1               ; FAT起始位置,一般从第一个扇区开始
        DB      2               ; FAT的个数,必须为2
        DW      224             ; 根目录大小,一般设置成224
        DW      2880            ; 磁盘的大小,必须为2880扇区
        DB      0xf0            ; 磁盘的种类,必须为0xf0
        DW      9               ; FAT的长度,必须是9扇区
        DW      18              ; 1个磁道(track)有几个扇区,必?是18
        DW      2               ; 磁头数,必须为2
        DD      0               ; 因为不使用分区,所以必须是0,4字?
        DD      2880            ; 重写一次磁盘大小,4字节
        DB      0,0,0x29        ; 意义不明,固定
        DD      0xffffffff      ; 卷标号
        DB      "HELLO-OS   "   ; 磁盘名称,11字节
        DB      "FAT12   "      ; 磁盘格式名称,8字节
        RESB    18              ; 空出18字节

; 程序主体

entry:
        MOV     AX,0            ; 初始化寄存器
        MOV     SS,AX
        MOV     SP,0x7c00
        MOV     DS,AX
        MOV     ES,AX

        MOV     SI,msg          ;将msg的地址存放到SI
putloop:
        MOV     AL,[SI]         ;将SI中的地址存放到AL
        ADD     SI,1            ; SI+1
        CMP     AL,0
        JE      fin
        MOV     AH,0x0e         ; 显示一个文字
        MOV     BX,14           ; 指定颜色
        INT     0x10            ; 调用显卡BIOS
        JMP     putloop
fin:
        HLT                     ; 让CPU停止,等待指令
        JMP     fin             ; 无限循环

; 信息显示

msg:
        DB      0x0a, 0x0a      ; 2个换行
        DB      "Hello!Beauty!"
        DB      0x0a            ; 换行
        DB      0

        RESB    0x1fe-$         ; 填写0x00,直到0x001fe

        DB      0x55, 0xaa

; 以下是启动区以外部分的输出

        DB      0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
        RESB    4600
        DB      0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
        RESB    1469432

在解释这些语句之前,我们先来了解一下CPU以及内存的基本知识。

寄存器

寄存器是CPU中的一个临时存储数据的地方,由于其就在CPU内部,因而速度极快。我们通常所说的CPU指令,其实是CPU操作寄存器的指令。CPU完成各类运算都是借助寄存器而实现的。因而在底层的语言中(如机器语言、汇编语言),其实都是控制CPU进行寄存器的操作。我们的操作系统程序也不例外,目前已经完成的程序就是使用指令操作寄存器。
目前计算机已经到了32位、64位,其寄存器容量各不相同,但是原理都是相似的。本书中以16位的寄存器为例,其主要有以下几个:

  • AX–累加寄存器。包含了AH和AL,高位和低位。
  • CX–计数寄存器。包含了CH和CL,高位和低位。
  • DX–数据寄存器。包含了DH和DL,高位和低位。
  • BX–基址寄存器。包含了BH和BL,高位和低位。
  • SP–栈指针寄存器
  • BP–基址指针寄存器
  • SI–源变址寄存器
  • DI–目的变址寄存器
  • ES–附加段寄存器
  • CS–代码段寄存器
  • SS–栈段寄存器
  • DS–数据段寄存器
  • FS–未命名
  • GS–未命名

每个不同的寄存器除了可以存放数据以外,还有着各自不同的作用。比如要让计算机在屏幕上显示一个字符,就需要把0x0e存进AH中,然后再调用10号中断指令。这些寄存器的特殊所用,会在日后的课程中不断介绍。

汇编语言基础

了解完了寄存器,我们就来了解一下汇编语言是如何对寄存器进行操作的。

Mov

Mov来自于英语的Move,意为移动,但在这里其实用“赋值”来形容它更为恰当。它是一个赋值语句,语法如下:
Mov 目标地址,原始数据
比如:

Mov AX,0

其实等效于我们在高级语言中的赋值语句

AX=0

其作用就是将0存到AX寄存器中
除了指定寄存器以外,还可以指定地址。比如:

Mov [123],0

在123两边加上了方括号,就表示这个数字是一个内存地址。因而这句语句的含义就是将内存地址为123的内存设置为0,但是这样的语句一般要配合BYTE、WORD、DWORD使用,以确定需要操作多少大小的内存。比如:

Mov WORD [123],0

这句语句就是将内存地址为123开始的两个字节的内存设置为0。
当然还可以这样用:

Mov AX,[BX]

[BX]就表示BX寄存器中的数值所代表的内存地址。比如BX中存放的值为222,那么[BX]就等价于[222],也就是内存中222地址中的内容,将它赋值给AX寄存器。

ORG

这个很简单。作用是指明程序装在的地址,也就是把程序装载到内存的哪里。

JMP

JMP是英文JUMP就是跳转的意思,这个语句相当于高级语言中的GOTO语句。也就是可以在程序中指定标签,然后跳转到某个标签中。

CMP和JE

CMP就是Compare比较的意思,是用来比较两个值是否相等。JE是配合CMP一起用的,就是JUMP IF EQUALS也就是如果相等就执行JUMP指令。在CMP比较后,就直接用JE来判断是否相等,然后相应跳转。相应的还有JNE指令,就是不相等的时候跳转。

ADD

加法操作,如下列语句就是将AX中的值加1:

ADD AX,1

HLT

让CPU停止,等待指令

INT

调用中断指令

系统程序启动流程

学会了所有的指令,我们就可以梳理所有的程序以及流程了。
1、首先还是定义了系统的一些基本参数
2、在Entry中初始化了一些寄存器:AX,SS,DS,ES,SP,并将msg的地址存入SI中
3、不断累加SI中的地址,并从中读取内容。当内容不等于0时,调用中断显示字符,然后重复本步骤;当内容为0时,跳转到fin
4、fin中让CPU停止,进入等待模式,并不断循环
经过上述步骤,即可显示hello world并让计算机进入一个死循环的等待中。

死循环

此处的死循环完全不用担心,因为CPU不会做任何事,只是静静等待。不像我们在程序中如果写了死循环,那可讨厌了,因为程序中始终让CPU在工作,所以会让程序完全无法响应并消耗计算机大量资源。

MAKEFILE

最初的系统引导,只需要512字节,所以这里把最后的那些DB删除了(其实前面部分的代码已经足够可以完成启动系统了)。
首先使用asm.bat(helloos04)可以得到一个ipl.lst文件,这个文件展示了汇编语言是如何分配到每个存储空间的,看看还挺有意思。
然后用MAKEFILE吧,这个机制设计很有意思。随意引用一段:

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

这句表示,要制作ipl.bin文件需要ipl.nas以及makefile两个文件,如果两个文件都有了,那就执行第二行的语句生成ipl.bin文件。
这个文件编写好之后,在DOS中只需要输入 MAKE ipl.bin指令,就会按照上述的方法生成了。
然后利用这个特性,就可以将很多东西串起来,然后一步步生成最终所需要的文件并启动操作系统。
本章的MAKEFILE如下:

# 默认动作

default :
    ../z_tools/make.exe img

# 文件生成规则

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

补遗

0x7c00

这个东西到底怎么来的。这是让计算机把这个程序装载到内存地址为0x7c00的地方,这个存储区域只有512字节。为什么是0x7c00呢,这是一个约定。详情可以参见这个网站(原书中的链接已经没用了)。
http://wiki.osdev.org/Memory_Map_(x86)

中断

中断到底是个啥,这个有点复杂。简而言之就是发送一个指令,让CPU执行相应的操作。与之相对的是查询,那个模式下,CPU始终在询问你要干啥,类似于一个死循环,而中断则是CPU平时在睡觉,直到执行了中断指令然后CPU开始工作。
基本的一些中断可以参考这个
http://wiki.osdev.org/BIOS

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值