3日目のアセンブラをダンプ(後編) - HobbyOSs/opennask GitHub Wiki
- ちなみに
wine
上でnaskを実行して正解を出している
wine
でmsys
を起動しつつ、以下のコマンド
$ nask ipl.nas ipl.img
$ od -t x1 ipl.img // リトルエンディアンで出力
確認時は ninja -t targets all | grep od | grep harib00g
等のコマンドでninjaのターゲットを絞り込める
-
3日目のアセンブラで新出のオペコード
-
アセンブラ
harib00f
- この日から
haribote.nas
がアセンブル対象に追加される JMP 0xc200
の部分しか変更点がない
; haribote-ipl
; TAB=4
CYLS EQU 10 ; EQUはバイナリには現れない
ORG 0x7c00 ; ORGはバイナリには現れない
; 以下は標準的なFAT12フォーマットフロッピーディスクのための記述
JMP entry ; eb4e
DB 0x90 ; 90
DB "HARIBOTE" ; 48415249424f5445
DW 512 ; 0002
DB 1 ; 01
DW 1 ; 0100
DB 2 ; 02
DW 224 ; e000
DW 2880 ; 400b
DB 0xf0 ; f0
DW 9 ; 0900
DW 18 ; 1200
DW 2 ; 0200
DD 0 ; 00000000
DD 2880 ; 400b0000
DB 0,0,0x29 ; 000029
DD 0xffffffff ; ffffffff
DB "HARIBOTEOS " ; 48415249424f54454f5320
DB "FAT12 " ; 4641543132202020
RESB 18 ; 000000000000000000000000000000000000
; プログラム本体
entry:
MOV AX,0 ; b80000
MOV SS,AX ; 8ed0
MOV SP,0x7c00 ; bc007c
MOV DS,AX ; 8ed8
; ディスクを読む
MOV AX,0x0820 ; b82008
MOV ES,AX ; 8ec0
MOV CH,0 ; b500
MOV DH,0 ; b600
MOV CL,2 ; b102
readloop:
MOV SI,0 ; be0000
retry:
MOV AH,0x02 ; b402
MOV AL,1 ; b001
MOV BX,0 ; bb0000
MOV DL,0x00 ; b200
INT 0x13 ; cd13
JNC next ; 7310
ADD SI,1 ; 83c601
CMP SI,5 ; 83fe05
JAE error ; 732e
MOV AH,0x00 ; b400
MOV DL,0x00 ; b200
INT 0x13 ; cd13
JMP retry ; ebe3
next:
MOV AX,ES ; 8cc0
ADD AX,0x0020 ; 052000
MOV ES,AX ; 8ec0
ADD CL,1 ; 80c101
CMP CL,18 ; 80f912
JBE readloop ; 76d1
MOV CL,1 ; b101
ADD DH,1 ; 80c601
CMP DH,2 ; 80fe02
JB readloop ; 72c7
MOV DH,0 ; b600
ADD CH,1 ; 80c501
CMP CH,CYLS ; 80fd0a
JB readloop ; 72bd
; 読み終わったのでharibote.sysを実行だ!
JMP 0xc200 ; e95545
error:
MOV SI,msg
putloop:
MOV AL,[SI]
ADD SI,1 ; SIに1を足す
CMP AL,0
JE fin
MOV AH,0x0e ; 一文字表示ファンクション
MOV BX,15 ; カラーコード
INT 0x10 ; ビデオBIOS呼び出し
JMP putloop
fin:
HLT ; 何かあるまでCPUを停止させる
JMP fin ; 無限ループ
msg:
DB 0x0a, 0x0a ; 改行を2つ
DB "load error"
DB 0x0a ; 改行
DB 0
RESB 0x7dfe-$ ; 0x7dfeまでを0x00で埋める命令
DB 0x55, 0xaa
harib00g
MOV [0x0ff0],CH
が追加
; haribote-ipl
; TAB=4
CYLS EQU 10 ; EQUはバイナリには現れない
ORG 0x7c00 ; ORGはバイナリには現れない
; 以下は標準的なFAT12フォーマットフロッピーディスクのための記述
JMP entry ; eb4e
DB 0x90 ; 90
DB "HARIBOTE" ; 48415249424f5445
DW 512 ; 0002
DB 1 ; 01
DW 1 ; 0100
DB 2 ; 02
DW 224 ; e000
DW 2880 ; 400b
DB 0xf0 ; f0
DW 9 ; 0900
DW 18 ; 1200
DW 2 ; 0200
DD 0 ; 00000000
DD 2880 ; 400b0000
DB 0,0,0x29 ; 000029
DD 0xffffffff ; ffffffff
DB "HARIBOTEOS " ; 48415249424f54454f5320
DB "FAT12 " ; 4641543132202020
RESB 18 ; 000000000000000000000000000000000000
; プログラム本体
entry:
MOV AX,0 ; b80000
MOV SS,AX ; 8ed0
MOV SP,0x7c00 ; bc007c
MOV DS,AX ; 8ed8
; ディスクを読む
MOV AX,0x0820 ; b82008
MOV ES,AX ; 8ec0
MOV CH,0 ; b500
MOV DH,0 ; b600
MOV CL,2 ; b102
readloop:
MOV SI,0 ; be0000
retry:
MOV AH,0x02 ; b402
MOV AL,1 ; b001
MOV BX,0 ; bb0000
MOV DL,0x00 ; b200
INT 0x13 ; cd13
JNC next ; 7310
ADD SI,1 ; 83c601
CMP SI,5 ; 83fe05
JAE error ; 732e
MOV AH,0x00 ; b400
MOV DL,0x00 ; b200
INT 0x13 ; cd13
JMP retry ; ebe3
next:
MOV AX,ES ; 8cc0
ADD AX,0x0020 ; 052000
MOV ES,AX ; 8ec0
ADD CL,1 ; 80c101
CMP CL,18 ; 80f912
JBE readloop ; 76d1
MOV CL,1 ; b101
ADD DH,1 ; 80c601
CMP DH,2 ; 80fe02
JB readloop ; 72c7
MOV DH,0 ; b600
ADD CH,1 ; 80c501
CMP CH,CYLS ; 80fd0a
JB readloop ; 72bd
; 読み終わったのでharibote.sysを実行だ!
MOV [0x0ff0],CH ; 882ef00f
JMP 0xc200 ; e95545
error:
MOV SI,msg
putloop:
MOV AL,[SI]
ADD SI,1 ; SIに1を足す
CMP AL,0
JE fin
MOV AH,0x0e ; 一文字表示ファンクション
MOV BX,15 ; カラーコード
INT 0x10 ; ビデオBIOS呼び出し
JMP putloop
fin:
HLT ; 何かあるまでCPUを停止させる
JMP fin ; 無限ループ
msg:
DB 0x0a, 0x0a ; 改行を2つ
DB "load error"
DB 0x0a ; 改行
DB 0
RESB 0x7dfe-$ ; 0x7dfeまでを0x00で埋める命令
DB 0x55, 0xaa
harib00h
- ここからは
ipl10.nas
には変化がなく、haribote.nas
に変更が入る EQU
は動くはずMOV
にBYTE
,WORD
,DWORD
を使ってるのが新しい
また、こいつらは結構手こずった
- 即値をメモリにぶち込む処理 →
MOV BYTE [VMODE],8
- レジスタをメモリにぶち込む処理 →
MOV [LEDS],AL
; haribote-os
; TAB=4
; BOOT_INFO関係
CYLS EQU 0x0ff0 ; ブートセクタが設定する
LEDS EQU 0x0ff1
VMODE EQU 0x0ff2 ; 色数に関する情報。何ビットカラーか?
SCRNX EQU 0x0ff4 ; 解像度のX
SCRNY EQU 0x0ff6 ; 解像度のY
VRAM EQU 0x0ff8 ; グラフィックバッファの開始番地
ORG 0xc200 ; このプログラムがどこに読み込まれるのか
MOV AL,0x13 ; b013
MOV AH,0x00 ; b400
INT 0x10 ; cd10
MOV BYTE [VMODE],8 ; c606 - f20f - 08
MOV WORD [SCRNX],320 ; c706 - f40f - 4001
MOV WORD [SCRNY],200 ; c706 - f60f - c800
MOV DWORD [VRAM],0x000a0000 ; 66c706 - f80f - 00000a00
; キーボードのLED状態をBIOSに教えてもらう
MOV AH,0x02 ;
INT 0x16 ;
MOV [LEDS],AL ;
fin:
HLT
JMP fin
harib00i
- ここからは
asmhead.nas
にわりと複雑なアセンブラを書くことになる EAX
,EBX
,ECX
など、32bitのレジスタが登場するJMP DWORD 2*8:0x0000001b
の命令はOS自体の仕様とJMP命令の仕様のわかりづらさのため2つの解説ページを書いた
; haribote-os boot asm
; TAB=4
BOTPAK EQU 0x00280000 ; bootpackのロード先
DSKCAC EQU 0x00100000 ; ディスクキャッシュの場所
DSKCAC0 EQU 0x00008000 ; ディスクキャッシュの場所(リアルモード)
; BOOT_INFO関係
CYLS EQU 0x0ff0 ; ブートセクタが設定する
LEDS EQU 0x0ff1
VMODE EQU 0x0ff2 ; 色数に関する情報。何ビットカラーか?
SCRNX EQU 0x0ff4 ; 解像度のX
SCRNY EQU 0x0ff6 ; 解像度のY
VRAM EQU 0x0ff8 ; グラフィックバッファの開始番地
ORG 0xc200 ; このプログラムがどこに読み込まれるのか
; 画面モードを設定
MOV AL,0x13 ; b013
MOV AH,0x00 ; b400
INT 0x10 ; cd10
MOV BYTE [VMODE],8 ; c606f20f08
MOV WORD [SCRNX],320 ; c706f40f4001
MOV WORD [SCRNY],200 ; c706f60fc80066
MOV DWORD [VRAM],0x000a0000 ; c706f80f00000a00
; キーボードのLED状態をBIOSに教えてもらう
MOV AH,0x02 ; b402
INT 0x16 ; cd16
MOV [LEDS],AL ; a2f10f
; PICが一切の割り込みを受け付けないようにする
; AT互換機の仕様では、PICの初期化をするなら、
; こいつをCLI前にやっておかないと、たまにハングアップする
; PICの初期化はあとでやる
MOV AL,0xff ; b0ff
OUT 0x21,AL ; e621
NOP ; 90
OUT 0xa1,AL ; e6a1
CLI ; fa
; CPUから1MB以上のメモリにアクセスできるように、A20GATEを設定
CALL waitkbdout ; e8b500 <-- [0xE8 cw]
MOV AL,0xd1 ; b0d1
OUT 0x64,AL ; e664
CALL waitkbdout ; e8ae00 <-- [0xE8 cw]
MOV AL,0xdf ; b0df
OUT 0x60,AL ; e660
CALL waitkbdout ; e8a700 <-- [0xE8 cw]
; プロテクトモード移行
[INSTRSET "i486p"] ; 486の命令まで使いたいという記述
; [INSTRSET ***] 命令は直接バイナリに影響しない、モード変更のみする
LGDT [GDTR0] ; 0f01162ac3
MOV EAX,CR0 ; 0f20c0 ... 0x0F 0x20 /r MOV r32, CR0
AND EAX,0x7fffffff ; 6625ffffff7f
OR EAX,0x00000001 ; 6683c801
MOV CR0,EAX ; 0f22c0
JMP pipelineflush ; eb00
pipelineflush:
MOV AX,1*8 ; b80800
MOV DS,AX ; 8ed8
MOV ES,AX ; 8ec0
MOV FS,AX ; 8ee0
MOV GS,AX ; 8ee8
MOV SS,AX ; 8ed0
; bootpackの転送
MOV ESI,bootpack ; 66be30c30000
MOV EDI,BOTPAK ; 66bf00002800
MOV ECX,512*1024/4 ; 66b9000002
CALL memcpy ; e85f00
; ついでにディスクデータも本来の位置へ転送
; まずはブートセクタから
MOV ESI,0x7c00 ; 66be007c0000
MOV EDI,DSKCAC ; 66bf00001000
MOV ECX,512/4 ; 66b980000000
CALL memcpy ; e86000
; 残り全部
MOV ESI,DSKCAC0+512 ; 66be 00820000
MOV EDI,DSKCAC+512 ; 66bf 00021000
MOV ECX,0 ; 66b9 00000000 <-- ここまで完了 2016/10/21
MOV CL,BYTE [CYLS] ; 8a0e f00f
IMUL ECX,512*18*2/4 ; 6669 c9 00120000 (512*18*2/4 = d4608 => 0x12000000)
SUB ECX,512/4 ; 6681e9 800000
CALL memcpy ; e83900 <-- まだ動いてない
; asmheadでしなければいけないことは全部し終わったので、
; あとはbootpackに任せる
; bootpackの起動
MOV EBX,BOTPAK ; 66bb 00002800
MOV ECX,[EBX+16] ; 67 668b 4b10
ADD ECX,3 ; 6683c1 03
SHR ECX,2 ; 66c1e9 02
JZ skip ; 74 10 67
MOV ESI,[EBX+20] ; 668b 7314
ADD ESI,EBX ; 6601de
MOV EDI,[EBX+12] ; 67668b 7b0c
CALL memcpy ; e81400 <-- まだ動いてない
skip:
MOV ESP,[EBX+12] ; 67668b 630c
JMP DWORD 2*8:0x0000001b ; 66ea 1b0000001000
waitkbdout:
IN AL,0x64 ; e464
AND AL,0x02 ; 2402
JNZ waitkbdout ; 75fa
RET ; c3
memcpy:
MOV EAX,[ESI] ; 6766 8b06
ADD ESI,4 ; 66 83c604
MOV [EDI],EAX ; 6766 8907
ADD EDI,4 ; 66 83c704
SUB ECX,1 ; 66 83e901
JNZ memcpy ; 75 ea
RET ; c3
; memcpyはアドレスサイズプリフィクスを入れ忘れなければ、ストリング命令でも書ける
ALIGNB 16
GDT0:
RESB 8 ; ヌルセレクタ
DW 0xffff,0x0000,0x9200,0x00cf ; 読み書き可能セグメント32bit
DW 0xffff,0x0000,0x9a28,0x0047 ; 実行可能セグメント32bit(bootpack用)
DW 0
GDTR0:
DW 8*3-1
DD GDT0
ALIGNB 16
bootpack:
harib00j
- 3日目最後の砦、
[FORMAT "WCOFF"]
がPE形式のヘッダを出力している
; naskfunc
; TAB=4
[FORMAT "WCOFF"] ; オブジェクトファイルを作るモード
[BITS 32] ; 32ビットモード用の機械語を作らせる
; オブジェクトファイルのための情報
[FILE "naskfunc.nas"] ; ソースファイル名情報
GLOBAL _io_hlt ; このプログラムに含まれる関数名
; 以下は実際の関数
[SECTION .text] ; オブジェクトファイルではこれを書いてからプログラムを書く
_io_hlt: ; void io_hlt(void);
HLT
RET