一看到题目写着 汇编二字,是不是心里一瞬间就产生畏惧感了呢(笑),其实汇编没有想得那么可怕的,我第一次接触汇编的时候因为不得法,也是感到头昏脑涨,被一堆寄存器搞得晕晕乎乎,现在回头再看,发现其实理清楚逻辑,它并没有那么可怕。
之所以在这里介绍几个汇编指令是因为,在开发OS的过程中,如果一直用二进制编码去写程序是一件让人很难受的事情,而借助汇编,可以极大的缩短代码量,更好的理清思维。 在第一篇文章中我们用二进制编辑器写出了一个简单的开机引导,在这一篇文章中我们用汇编语言对其进行改写,不要这么快就畏惧哦~相信看完本文,大家对汇编会有一个新的认识, “哦,其实汇编并不是很可怕嘛~”
首先看一下改写之后的代码
汇编代码表示
; hello-os
; TAB=4
ORG 0x7c00
JMP entry
DB 0x90
DB "HELLOIPL"
DW 512
DB 1
DW 1
DB 2
DW 224
DW 2880
DB 0xf0
DW 9
DW 18
DW 2
DD 0
DD 2880
DB 0,0,0x29
DD 0xffffffff
DB "HELLO-OS "
DB "FAT12 "
RESB 18
entry:
MOV AX,0
MOV SP,0x7c00
MOV DS,AX
MOV ES,AX
MOV SI,msg
putloop:
MOV AL,[SI]
ADD SI,1
CMP AL,0
JE fin
MOV AH,0x0e
MOV BX,15
INT 0x10
JMP putloop
fin:
HLT
JMP fin
msg:
DB 0x0a, 0x0a
DB "hello, world"
DB 0x0a
DB 0
RESB 0x7dfe-$
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
好吧,我承认这一堆看起来很难受,那么我们把它改写成C代码,这样开起来就会容易些
C代码表示
entry:
AX = 0;
SS = AX;
SP = 0X7C00;
DS = AX;
ES = AX;
SI = msg;
putloop:
AL = BYTE[SI];
SI = SI + 1;
if(AL == 0)
{
goto fin;
}
AH = 0X0E;
BX = 15;
INT 0X10;
goto putloop;
fin:
HLT;
goto fin;
这样看起来好多了吧
不过好像那些奇怪的大写字符还是很多,别急,那些就是开头提到的寄存器了,接下来详细解释一下这些寄存器的功能和语句的含义。
详解汇编语句以及寄存器
DB指令:即data byte,它的含义是往文件中直接写入1个字节的指令
RESB指令:即reserve byte,从当前的地址开始空出N个字节, eg:RESB 10:从当前地址空出10个字节
DW:data word,代表8位(2字节)
DD:data doubleword,代表16位(4字节)
IPL:initial program loader,启动程序加载器
MOV指令:很常用的指令,功能非常简单,即赋值
eg: MOV AX, 0 ;即AX = 0; MOV SS, AX ;即SS = AX; 还是很好理解吧~
寄存器解释
接下来就是重头戏了,也就是对几个重要的寄存器进行解释
AX(accumulator):累加寄存器(进行加法运算)
CX(counter):计数寄存器
DX(data):数据寄存器
BX(base):基址寄存器,(大家在数据结构应该接触过这个概念,就是地址的起始参照地址)
SP(stackpointer):栈指针寄存器
BP(basepointer):基址指针寄存器
SI(sourceindex):源变址寄存器
DI(destinationindex):目的变址寄存器 ps:上面所说的都是16位寄存器
下面的寄存器是8位寄存器,很简单是将上述的AX,CX,DX,BX分为高八位低八位
AH,CH,DH,BH:他们是上述的寄存器的高八位(high)
AL,CL,DL,BL:他们是上述的寄存器的低八位(low)
有心的同学们在这里也会会发问,
”既然有16位和8位寄存器,那么有没有32位的寄存器呢?” 当然是有的,因为我们用的不多,这里就不赘述了,感兴趣的可以去google一下,相信会有很多收获。
那我们继续,接下来说到的是段寄存器
ES(extra segment):附加段寄存器
CS(code segment):代码段寄存器
SS(stack segment):栈段寄存器
DS(data segment):数据段寄存器 他们的功能从名称上就可以反映出来
大家看下面这条语句
MOV AX [SI]
如果SI没有加“[]”,大家都能猜到他的作用是将SI中的数据赋值给AX,但此处加了括号,它的意思就变成将 SI的地址存储到AX中。 MOV指令有一个规则,即源数据和目的数据必须位数相同 所以上述语句就是讲SI地址的 一个字节给予AX。
ADD指令 顾名思义,进行加法运算,比如: >ADD SI, 1 ; SI = SI + 10:从当前地址空出10个字节
CMP指令 比较指令
JE指令 条件跳转指令,根据比较的结果决定跳转与否。JE即 jump if equal 与CMP结合使用,当比较的结果相等,则跳转到指定的地址;若比较结果不同,则不跳转,继续执行下一条指令。
看下面这段代码
CMP AL, 0
JE fin
其实等价于
if(AL == 0)
{
goto fin;
}
INT指令 软件中断指令,(interrupt),INT后面是一个数字,使用不同的数字代表调用不同的函数,这些函数都是写在BIOS中的,方便程序员调用。
HLT指令 这条指令的目的是让CPU停止动作,但不是完全停止,那样的话就得断电。此处是指让CPU进入待机状态。 玩过linux的同学应该都用过“halt”这条指令进行关机操作吧。_
结语
这次介绍汇编还是比较吃力,毕竟自己明白一些和给别人讲解还是不一样的,不过大家放心啦,今后的开发会转到C语言,看起来也不会很吃力,不过必要的时候还是要用汇编这张“王牌”,哈哈那么,这次的文章就告一段落了,有些地方说的不对的,还请大家提出意见和建议,现行谢过了