有段時間開始對彙編感興趣,也因此在寫各種不同的demo,現在分享之前學習的成果,需要下載的東西有nasm和qemu-system-i386,看看枯燥的彙編能產生多大的能量。
先來複習一下通用暫存器:
8位通用暫存器:
AL
: 用於儲存運算元低8位的資料暫存器。AH
: 用於儲存運算元高8位的資料暫存器(通常與AL
結合使用,形成16位的AX
暫存器)。BL
: 另一個用於儲存資料的暫存器,常用於BIOS中斷呼叫中設定顏色或作為其他引數。BH
: 與BL
配合使用,形成16位的BX
暫存器。CL
: 常用於計數器,例如在迴圈或位移操作中。CH
: 與CL
配合使用,形成16位的CX
暫存器。DL
: 用於儲存資料,也可用於指定I/O埠對映。DH
: 與DL
配合使用,形成16位的DX
暫存器。
16位通用暫存器:
AX
: 累加器,用於大多數算術和資料傳輸操作。它是AL
和AH
的組合。BX
: 基址暫存器,常用於儲存記憶體地址或作為迴圈計數器。CX
: 計數暫存器,常用於迴圈計數和字串操作。DX
: 資料暫存器,常用於I/O操作和某些算術操作。
這些暫存器在稍後的demo當中會涉及到,因此先留意一下;除了暫存器,還要了解中斷號和服務號。簡單來說中斷號就是標識中斷處理程式的,服務號是用於在中斷處理程式中內部選擇服務的,上程式碼。
; MBR引導載入程式示例,列印一個帶有顏色的字元 'H'
; NASM語法
; 編譯:nasm hello.asm
org 0x7C00 ; MBR起始位置
; 初始化BIOS資料區(可選)
; mov [0x0500], byte 0x00
; 設定列印位置到第一行第一列
mov dh, 4 ; 行號 (BIOS中的行號從0開始)
mov dl, 9 ; 列號
mov bh, 0 ; 頁號,通常設定為0
mov ah, 0x02 ; 設定游標位置的服務號
int 0x10
; 列印字元'H',設定顏色屬性
mov ah, 0x09 ; 列印字串的服務號
mov al, 'H' ; 待列印的字元
mov bl, 0x13 ; 顏色屬性:前景白色(15),背景藍色(1)
mov bp, color_string ; 字串的記憶體偏移地址(一般都用bp暫存器儲存字串地址)
mov cx, 1 ; 字串長度
int 0x10
; 填充剩餘空間並新增MBR簽名
; 確保MBR大小為512位元組
times 510 - ($ - $$) db 0
dw 0xAA55 ; MBR簽名
; 定義儲存字元的記憶體位置
color_string db 'H', 0
這期先將注意力主要放在一系列的mov指令當中,其它部分程式碼可以先直接跳過,int 0x10是用於訪問和控制影片顯示的中斷,因此我們無論要設定游標還是列印字元都需要到用它。可以發現都是將一系列的引數放到不同的暫存器,然後再觸發中斷,這個中斷裡面值得注意的是AH這個暫存器,前面說到了它是AX暫存器的高8位,需要將服務號放置到這個AH暫存器裡面,先來看看int 0x10下的服務號(需要可以查手冊)
-
0x02
- 設定游標位置- 將文字模式下的游標移動到指定位置。
DH
暫存器包含行號,DL
暫存器包含列號,BH
暫存器包含頁號。
- 將文字模式下的游標移動到指定位置。
-
0x03
- 獲取游標位置- 讀取當前游標的位置。呼叫後,
DH
暫存器包含行號,DL
暫存器包含列號,BH
暫存器包含頁號。
- 讀取當前游標的位置。呼叫後,
3. 0x09
- 寫字串
-
- 在當前游標位置列印一個字串。
AL
暫存器包含要列印的字元,BL
暫存器包含顏色屬性,CX
暫存器包含重複次數。
- 在當前游標位置列印一個字串。
4. 0x0E
- 列印字元
-
- 在當前游標位置列印一個字元。
AL
暫存器包含要列印的字元,BL
暫存器包含顏色屬性。
- 在當前游標位置列印一個字元。
目前想做的是將一種顏色的字串列印到螢幕上面,因此先設定游標位置,確定位置之後再列印字串,結合註釋和這些暫存器規範就比較好理解了。完了再用匯編器nasm進行彙編。
nasm hello.asm
接著放在qemu上面跑。
qemu-system-i386 hello
結果不出意外長這樣。
需要注意一點,比如說設定游標的那個服務號不要忘記推到AH暫存器,不然會出現奇怪的錯誤,比如每次列印的字串不同。簡言之就是在觸發中斷之前一定要記得設定好服務號;另外定義字串最後也別忘記了加上一個0,這點和C語言字串類似。
把CX暫存器的數字一改,就可以重複列印。
下期講更加深入,這是第一次更彙編相關的內容,感謝關注~