3日目のアセンブラをダンプ(後編) - HobbyOSs/opennask GitHub Wiki

  • ちなみにwine上でnaskを実行して正解を出している

winemsysを起動しつつ、以下のコマンド

$ nask ipl.nas ipl.img
$ od -t x1 ipl.img      // リトルエンディアンで出力

確認時は ninja -t targets all | grep od | grep harib00g 等のコマンドでninjaのターゲットを絞り込める

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は動くはず
  • MOVBYTE, 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

; 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