彙編+qemu玩轉控制檯列印

ChebyshevTST發表於2024-07-30

有段時間開始對彙編感興趣,也因此在寫各種不同的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: 累加器,用於大多數算術和資料傳輸操作。它是ALAH的組合。
  • 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下的服務號(需要可以查手冊)

  1. 0x02 - 設定游標位置

    • 將文字模式下的游標移動到指定位置。DH 暫存器包含行號,DL 暫存器包含列號,BH 暫存器包含頁號。
  2. 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暫存器的數字一改,就可以重複列印。

下期講更加深入,這是第一次更彙編相關的內容,感謝關注~

相關文章