我這邊寫的不一定是對的,可能有些前提條件,不過我可能還不是全懂?
接著的例子就是會介紹如何切換到 big real mode 或是保護模式,好突破記憶體的限制,再來可能是想辦法把硬碟上的程式載入到記憶體,接著是初始化 C 語言環境,然後我們就可以有好用的 C 語言可用了。
雖然大部份的書入門都是這樣介紹,但我個人比較好奇的是 510 Byte 大概可以寫下怎樣的程式?如果把 x86 CPU 當成 MCU 來操作,在這樣的大小之下,可以寫一個猜數字或是簡單的打磚塊遊戲嗎?
故我第一個程式便是先嘗試用到 INT 0x10 和 INT 0x16 的 BIOS 中斷,這樣就可以印東西到螢幕,也可以讀取鍵盤的輸入字元。即使之後可能有很大機會就只是玩到這裡為止,但至少是個開始。
真正的程式很簡單不到 30 行,機器碼也只有 30 Byte,在 qemu 上跑起來也算順利。
但在真實的機器上跑便遇到兩個問題:
01. 在我家的板子上無法使用 INT 0x16 讀取鍵盤。
02. 在我自己的筆電上無法使用 USB 隨身碟開機。
我決定先把這兩個問題搞定就好。
2022/02/14 更新
我的程式沒有使用 org 告知組譯器開始位置 0x7C00,那是因為我並未宣告字串的空間,故沒有定址到那塊空間的需求,即使我有宣告字串,也可以自己計算 offset 的位置,當然使用 org 讓組譯器幫你計算是比較好的作法。順帶一提,這個 0x7C00 不是 INTEL 的標準,而是當初開發 IBM PC 5150 時用的,就一直延用至今,變成一個類似 BIOS 的標準。
2022/02/15 更新
Short jump—A near jump where the jump range is limited to –128 to +127 from the current EIP value.
opcode EB 是短跳轉,後面帶的是從目前的 EIP 要跳多少位置。這個位置是 -128 ~ +127。
故 section start 的最後一道指令 jmp check 轉成 opcode 是 EB E4(負數,二補數法),也就是往回跳 28 個 Byte,也就是 0x02 的位置,也就是 section check 的第一道指令 mov ah, 0x0d,也就是 opcode B4 0D。
mov 會隨著使用不同的暫存器而有不同的 opcode。
2022/03/08 更新
不懂 x86 也不懂 BIOS 的我,實在不知道為什麼 Legacy BIOS 的鍵盤中斷 INT 0x16 無法使用?沉思中 ...
2022/03/09 更新
找到原因了,從 Google 得知,某些 BIOS 中斷需要 stack 才能正常工作,故我們必須一併設定 SS 和 SP,但我只設定這兩個還是不正常,故把 DS、ES 也順便一起設定。
org 0x7c00
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0xb800
雖然現在鍵盤中斷可以正常工作,但我判斷是否按下 enter 鍵的 code 無法成功判斷,目前還要努力,至於其他鍵是沒有問題的。
2022/03/10 更新
即使是支小程式,在真實的機器上跑還是有很多眉角要注意,我終於知道為什麼我嘗試想要換行會無法成功,原因是我誤用了 BL 暫存器,0EH 的 INT 10h 中斷會用到 BL,但我嘗試在比較時對這個暫存器設值,導致 INT 10h 異常,同樣的之前我以為要設定 stack 才能正常使用鍵盤中斷也是錯的,只要我不要用到 BL 暫存器,即使不設定 stack,鍵盤中斷仍然是可以使用的。
寫組語用暫存器真的是要小心呀XD
最後版的程式
;org 0x7c00
;mov ax, cs
;mov ds, ax
;mov es, ax
;mov ss, ax
;mov sp, 0xb800
init:
jmp start
check:
mov cl, 0x0d
cmp al, cl
je nextline
print:
mov ah, 0x0e ;tty mode
int 0x10
jmp start
nextline:
mov ah, 0x0e ;tty mode
mov al, 0x0d
int 0x10
mov al, 0x0a
int 0x10
jmp start
nextline1:
mov ah, 0x03
int 0x10
inc dh
mov dl, 0x00
mov ah, 0x02
int 0x10
start:
mov ah, 0x10
int 0x16
jmp check
debug:
;mov al, 0x4c
out 0x80, al
hlt
jmp debug
; padding and magic number
times 510 - ($-$$) db 0
dw 0xaa55
沒有留言:
張貼留言