86系のPCをブートさせて遊んでみよう、というお話の7回目になります。テキストは『OSを書く:初歩から一歩ずつ』です。
環境はAMD64+Windows10+VMware Workstation 17 Player+Debian 12.4です。
テキストの練習問題もこれで最後です。
頑張りましゅっ(噛んだ)
6. BIOSからキー押下情報を取り込む。
キーボードからの入力を得ることができれば、いろんな事が出来そうです。
期待が膨らみます。
使うBIOSコールは0x16。設定値は無し。キーが押されるとahとalに値が入って戻ってくるみたいです。ソースはこんな感じ?
; boot.asm
;
mov ax, 0x07c0
mov ds, ax
mov ah, 0x0
mov al, 0x3
int 0x10
mov ah, 0x00
int 0x16
mov cx, ax
mov ch, 0x00
mov bx, 10
loop:
mov dx, 0
mov ax, cx
div bx
mov cx, ax
mov ah, 0x0e
mov al, dl
add al, 0x30
int 0x10
cmp cx, 0
jne loop
jmp hang
[text]
; end of proccess
;
hang:
jmp hang
times 510-($-$$) db 0
db 0x55
db 0xAA
PlayWithBoot.6.1
実行すると、こんな感じ。
これはエンターを押した場合のalの値ですね。
なんだか簡単に終わってしまった?
一応、練習問題はこれで終わりですけど、これだけだと寂しいので、少し遊んでみましょう。
おまけ
せっかくなので練習問題の1から6まで、一つにまとめてみました。
; boot.asm
;
mov ax, 0x07c0
mov ds, ax
mov ah, 0x0
mov al, 0x3
int 0x10
; practice 1 (print other)
mov ax, p1_title
call print_str
mov al, 1
mov ah, 0x0e
add al, 0x30
int 0x10
mov ax, crlf
call print_str
call print_str
; practice 2 (add 2 num)
mov ax, p2_title
call print_str
mov ax, p2_msg
call print_str
mov bh, 1
mov bl, 3
add bl, bh
mov ah, 0x0e
mov al, bl
add al, 0x30
int 0x10
mov ax, crlf
call print_str
call print_str
; practice 3 (add 1 to 100 and print it)
mov ax, p3_title
call print_str
mov bx, 0
mov ax, 0
add_loop:
add ax, bx
add bx, 1
cmp bx, 100
jle add_loop
mov bx, ax
print_loop:
mov dx, 0
mov ax, bx
mov bx, 10
div bx
mov bx, ax
mov ah, 0x0e
mov al, dl
add al, 0x30
int 0x10
cmp bx, 0
jne print_loop
mov ax, crlf
call print_str
call print_str
; practice 4 (print valu in address)
mov ax, p4_title
call print_str
mov ax, 0x0000
mov bx, _test
mov byte al, [bx]
mov bx, ax
p4_loop:
mov dx, 0
mov ax, bx
mov bx, 10
div bx
;mov cx, dx
mov bx, ax
mov ah, 0x0e
mov al, dl
add al, 0x30
int 0x10
cmp bx, 0
jne p4_loop
mov ax, crlf
call print_str
call print_str
; practice 5 (read disk)
mov ax, p5_title
call print_str
mov ax, 0x07c0
mov es, ax
mov bx, 512
mov ah, 0x02 ; Read Sectors From Drive
mov dl, 0x80 ; Drive
mov al, 0x01 ; Sectors To Read Count ;
mov ch, 0x00 ; Cylinder
mov cl, 0x02 ; Sector(starts from 1, not 0) ; set 2. becouse not need MBR
mov dh, 0x00 ; Head
int 0x13 ; Execute disk read
mov ax, 512
call print_str
mov ax, crlf
call print_str
call print_str
; practice 6 (key read)
mov ax, p6_title
call print_str
mov ax, p6_msg
call print_str
mov ah, 0x00
int 0x16
mov bx, ax
mov bh, 0
p6_loop:
mov dx, 0
mov ax, bx
mov bx, 10
div bx
mov bx, ax
mov ah, 0x0e
mov al, dl
add al, 0x30
int 0x10
cmp bx, 0
jne p6_loop
jmp hang
; end of proccess
;
hang:
jmp hang
p1_title:
db 'practice 1 (print other)', 0x0a, 0x0d, 0x0a, 0x0d, 0x00
p2_title:
db 'practice 2 (add 2 num)', 0x0a, 0x0d, 0x0a, 0x0d, 0x00
p2_msg:
db '1 + 3 : ', 0x00
p3_title:
db 'practice 3 (add 1 to 100 and print it)', 0x0a, 0x0d, 0x0a, 0x0d, 0x00
p4_title:
db 'practice 4 (print valu in address)', 0x0a, 0x0d, 0x0a, 0x0d, 0x00
p5_title:
db 'practice 5 (read disk)', 0x0a, 0x0d, 0x0a, 0x0d, 0x00
p6_title:
db 'practice 6 (key read)', 0x0a, 0x0d, 0x0a, 0x0d, 0x00
p6_msg:
db 'ascii code : ', 0x00
crlf:
db '', 0x0a, 0x0d, 0x00
_test:
db 0x15, 0x00
print_str:
push ax
push si
mov si, ax
mov ah, 0x0E
loop:
lodsb
or al, al
jz loop_end
int 0x10
jmp loop
loop_end:
pop si
pop ax
ret
times 510-($-$$) db 0
db 0x55
db 0xAA
top_of_2nd_sector:
db 'Hello Sector No.1', 0x0d, 0x0a, 0x00
times 1024-($-$$) db 0
PlayWithBoot.6.2
実行すると、こんな感じです。
これで一通りやり切しました。
他にもやりようはあるし、数値の表示を左からきちんと表示するとか、手を加えられるところも沢山あると思います。
そのあたり、気になった部分はそれそれ直してみていただければと。
一連のソースですが、githubに上げてみました。素の設定なので公開されている筈です。よろしければ覗いてやってください。
https://github.com/cbwb-inc/software/PlayWithBoot
かなり時間がかかってしまいましたが、『ブートで遊ぼっ!』これにて終了です。
物凄く楽しかった♪
《2024/5/9 12:30:24》