技术干货码农の日常汇编语言

开发OS二日目之必要汇编指令

2014-12-07  本文已影响232人  TaXue_WWL
2e2eb9389b504fc2e40ad6e0e4dde71191ef6df9.jpg

一看到题目写着 汇编二字,是不是心里一瞬间就产生畏惧感了呢(笑),其实汇编没有想得那么可怕的,我第一次接触汇编的时候因为不得法,也是感到头昏脑涨,被一堆寄存器搞得晕晕乎乎,现在回头再看,发现其实理清楚逻辑,它并没有那么可怕。

之所以在这里介绍几个汇编指令是因为,在开发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语言,看起来也不会很吃力,不过必要的时候还是要用汇编这张“王牌”,哈哈那么,这次的文章就告一段落了,有些地方说的不对的,还请大家提出意见和建议,现行谢过了

上一篇下一篇

猜你喜欢

热点阅读