2019年7月2日 星期二

自製64位元作業系統04──組合語言的印訊息函式:使用BIOS中斷

我們之前每一次印出訊息都要重複好幾行的東西,而且每一次都要自己計算字串有多少的字數,十分麻煩。加上我們以前印出字的地方都在螢幕左上角,而不是游標的位置。我們這次就來製作一個函式,解決這些問題。
首先,我們介紹一下函式的呼叫。在呼叫函式的時候,會用一定的方法將所有的參數準備傳遞。並且利用call指令呼叫。call指令會將下一個指令的位置入棧,並且讓之後的ret指令可以運作。
我們的程式碼如下
print:
# Get cursor position (Return dh = row, dl = column ...)
# 利用中斷得出游標位置
movb $0x03, %ah
movb $0, %bh
int $0x10

# Count String 計算字串長度,存在cx暫存器
xorw %cx, %cx
movw %bp, %si
cnt:
movb (%si), %ah
cmpb $0, %ah
je cnt_exit
incw %si
incw %cx
jmp cnt
cnt_exit:

# Print
# (ah = 0x13, al = 0x0, bh = 0, bl = 7, cx = strlen, dh:dl=row:column, es:bp=7c0:Message)
movw $0x1300, %ax
movw $0x7, %bx
int $0x10

# Move cursor to next line
# 把游標移到下一行
incb %dh
xorb %dl, %dl
movb $0, %bh
movb $0x02, %ah
int $0x10
# 函式結束,返回
ret
#=====================================================================
一定要記得,利用這個函式印出的字串一定要用.asciz,來自動為字串末加上一個NUL字元。加入這段程式後,只要將字串的位置存在bp暫存器,並呼叫函式,就可以印出訊息。將所有要印出訊息的部分都改為使用此函式後的程式碼如下:

.code16
.section .text
# Init all the registers
xorw %ax, %ax
xorw %bx, %bx
xorw %cx, %cx
xorw %dx, %dx

movw $0x7c0, %ax
movw %ax, %es
movw %ax, %ds
movw %ax, %ss

# Reset Floppy (int 0x13, ah = 0x0, dl = 0 (first floppy))
movb $0, %ah
int $0x13

# Read Number 2 (CHS)
# (int 0x13, ah = 0x2, al = 1, ch = 0, cl = 2, dh = 0, dl = 0, ES:BX = 0x7E00)
movw $0x200, %bx
movb $0x2, %ah
movb $0x1, %al
movb $0x0, %ch
movb $0x2, %cl
movb $0x0, %dh
movb $0x0, %dl
int $0x13

jc error

jmp second_sector

error:
# Print Error
movw $ERROR_MSG, %bp
call print
jmp .

ERROR_MSG:
.asciz "READ FLOPPY ERROR"

# ====================================================================
# print function
# ====================================================================
# es:bp as Message position, zero-term string
print:
# Get cursor position (Return dh = row, dl = column ...)
movb $0x03, %ah
movb $0, %bh
int $0x10

# Count String
xorw %cx, %cx
movw %bp, %si
cnt:
movb (%si), %ah
cmpb $0, %ah
je cnt_exit
incw %si
incw %cx
jmp cnt
cnt_exit:

# Print
# (ah = 0x13, al = 0x0, bh = 0, bl = 7, cx = strlen, dh:dl=row:column, es:bp=7c0:Message)
movw $0x1300, %ax
movw $0x7, %bx
int $0x10

# Move cursor to next line
incb %dh
xorb %dl, %dl
movb $0, %bh
movb $0x02, %ah
int $0x10
ret
#=====================================================================


.org 0x1FE, 0x62
.byte 0x55
.byte 0xAA

second_sector:
# Print
movw $HELLO_MESSAGE, %bp
call print

jmp .

HELLO_MESSAGE:
.asciz "Hello world!"

.org 0x400, 0x62
# 接前面的superblock
最後,在qemu測試的畫面截圖如下:



👉【幫我們一個忙!】👈

👋如果您喜歡這篇文章,請在下方按5個Like!
 ❤您的支持是我們最大的動力!

您只要登入帳號(Facebook、Google),在下方按5個Like,我們就會收到來自LikeCoin基金會的贊助。
您只需要支持我們,完全不會花到錢!