一看到題目寫著 匯編二字,是不是心里一瞬間就產生畏懼感了呢(笑),其實匯編沒有想得那么可怕的,我第一次接觸匯編的時候因為不得法,也是感到頭昏腦漲,被一堆寄存器搞得暈暈乎乎,現在回頭再看,發現其實理清楚邏輯,它并沒有那么可怕。
之所以在這里介紹幾個匯編指令是因為,在開發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語言,看起來也不會很吃力,不過必要的時候還是要用匯編這張“王牌”,哈哈那么,這次的文章就告一段落了,有些地方說的不對的,還請大家提出意見和建議,現行謝過了