changeset 0:1a23828953f2

haribote day 4
author mir3636
date Wed, 03 Oct 2018 21:06:50 +0900
parents
children 70754edc1f50
files Makefile asmhead.asm bootpack.c ipl10.asm iplelf.asm nasmfunc.asm os.ls
diffstat 7 files changed, 488 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile	Wed Oct 03 21:06:50 2018 +0900
@@ -0,0 +1,51 @@
+# target name
+TARGET=ipl
+
+# dependencies
+asmhead.bin : asmhead.asm
+	nasm -f elf32 -g -o asmhead.bin asmhead.asm
+nasmfunc.o : nasmfunc.asm
+	nasm -f elf32 -g -o nasmfunc.o nasmfunc.asm
+#bootpack.bin : bootpack.c nasmfunc.o
+#	gcc -m32 -nostdlib -Wl,--oformat,binary bootpack.c nasmfunc.o -T os.ls -o bootpack.bin
+bootpack.o : bootpack.c
+	clang -target i386-pc-linux -c bootpack.c -o bootpack.o
+bootpack.bin : bootpack.o nasmfunc.o
+	i386-elf-ld -m elf_i386 -e HariMain -o bootpack.bin -T os.ls bootpack.o nasmfunc.o
+haribote.sys : asmhead.bin bootpack.bin
+	cat asmhead.bin bootpack.bin > haribote.sys
+iplelf.bin : iplelf.asm
+	nasm -o iplelf.bin iplelf.asm
+ipl10.bin : ipl10.asm
+	nasm -o ipl10.bin ipl10.asm
+haribote.img : ipl10.bin haribote.sys
+	mformat -f 1440 -C -B ipl10.bin -i haribote.img ::
+	mcopy -i haribote.img haribote.sys ::
+img :
+	make -r haribote.img
+
+kernel.elf: asmhead.bin bootpack.o nasmfunc.o
+	i386-elf-ld -m elf_i386 -e asmhead -o kernel.elf -T os.ls asmhead.bin bootpack.o nasmfunc.o
+
+elf.img : iplelf.bin kernel.elf
+	mformat -f 1440 -C -B iplelf.bin -i elf.img ::
+	mcopy -i elf.img kernel.elf ::
+
+clean:
+	-rm *.bin
+	-rm *.o
+	-rm *.sys
+	-rm *.img
+
+src_only :
+	make clean
+	rm haribote.img
+
+elf: elf.img kernel.elf
+	qemu-system-i386 -fda elf.img -m 512M  
+
+elfd: elf.img kernel.elf
+	qemu-system-i386 -fda elf.img -m 512M -gdb tcp::1234 -S 
+
+do: haribote.img
+	qemu-system-i386 -fda haribote.img -m 512M
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/asmhead.asm	Wed Oct 03 21:06:50 2018 +0900
@@ -0,0 +1,154 @@
+; haribote-os
+; 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(screen x)
+    SCRNY   EQU     0x0ff6 ; 解像度のY(screen y)
+    VRAM    EQU     0x0ff8 ; グラフィックバッファの開始番地
+
+;    ORG     0xc200 ; このプログラムがどこに読み込まれるのか
+
+section .text
+
+    global asmhead
+
+asmhead:
+    
+
+; 画面モードを設定
+
+    MOV     AL,0x13 ; VGAグラフィックス、320*200*8bitカラー
+    MOV     AH,0x00
+    INT     0x10
+    MOV     BYTE [VMODE],8 ; 画面モードをメモする
+    MOV     WORD [SCRNX],320
+    MOV     WORD [SCRNY],200
+    MOV     DWORD [VRAM],0x000a0000
+
+; キーボードのLED状態をBIOSに教えてもらう
+
+    MOV     AH,0x02
+    INT     0x16 ; keyboard BIOS
+    MOV     [LEDS],AL
+
+; PIC が一切の割り込みを受け付けないようにする
+; AT互換機の仕様では、PICの初期化をするなら、
+; こいつをCLI前にやっておかないと、たまにハングアップする
+; PICの初期化は後でやる
+
+    MOV     AL,0xff
+    OUT     0x21,AL
+    NOP ; OUT命令を連続させるとうまくいかない機種があるらしいので
+    OUT     0xa1,AL
+
+    CLI ; さらにCPUレベルでも割り込み禁止
+
+; CPUから1MB以上のメモリにアクセスできるように、A20GATEを設定
+
+    CALL    waitkbdout
+    MOV     AL,0xd1
+    OUT     0x64,AL
+    CALL    waitkbdout
+    MOV     AL,0xdf ; enable A20
+    OUT     0x60,AL
+    CALL    waitkbdout
+
+; プロテクトモード移行
+
+;[INSTRSET "i486p"] ; 486の命令まで使いたいという記述
+
+    LGDT    [GDTR0] ; 暫定GDTを設定
+    MOV     EAX,CR0
+    AND     EAX,0x7fffffff ; bit31を0にする(ページング禁止のため)
+    OR      EAX,0x00000001 ; bit0を1にする(プロテクトモード移行のため)
+    MOV     CR0,EAX
+    JMP     pipelineflush
+pipelineflush:
+    MOV     AX,1*8
+    MOV     DS,AX
+    MOV     ES,AX
+    MOV     FS,AX
+    MOV     GS,AX
+    MOV     SS,AX
+
+; bootpackの転送
+
+    MOV     ESI,bootpack ; 転送元
+    MOV     EDI,BOTPAK ; 転送先
+    MOV     ECX,512*1024/4
+    CALL    memcpy
+
+; ついでにディスクデータも本来の位置へ転送
+
+; まずはブートセクタから
+
+    MOV     ESI,0x7c00 ; 転送元
+    MOV     EDI,DSKCAC ; 転送先
+    MOV     ECX,512/4
+    CALL    memcpy
+
+; 残り全部
+    
+    MOV     ESI,DSKCAC0+512 ; 転送元
+    MOV     EDI,DSKCAC+512 ; 転送先
+    MOV     ECX,0
+    MOV     CL,BYTE[CYLS]
+    IMUL    ECX,512*18*2/4 ; シリンダ数からバイト数/4に変換
+    SUB     ECX,512/4 ; IPLの分だけ差し引く
+    CALL    memcpy
+
+; asmhead でしなければいけないことは全部し終わったので
+; あとはbootpackに任せる
+
+; bootpack の起動
+
+    MOV     EBX,BOTPAK
+    MOV     ECX,[EBX+16]
+    ADD     ECX,3 ; ECX += 3
+    SHR     ECX,2 ; ECX /= 4
+    JZ      skip ;転送すべきものがない
+    MOV     ESI,[EBX+20] ; 転送元
+    ADD     ESI,EBX
+    MOV     EDI,[EBX+12] ; 転送先
+    CALL    memcpy
+skip:
+    MOV     ESP,[EBX+12] ; スタック初期値
+    JMP     DWORD 2*8:0x0000001b
+
+waitkbdout:
+    IN      AL,0x64
+    AND     AL,0x02
+    JNZ     waitkbdout ; AND の結果が0でなければwaitkbdoutへ
+    RET
+
+memcpy:
+    MOV     EAX,[ESI]
+    ADD     ESI,4
+    MOV     [EDI],EAX
+    ADD     EDI,4
+    SUB     ECX,1
+    JNZ     memcpy ; 引き算した結果が0でなければmemcpy
+    RET
+; memcpyはアドレスサイズプリフィクスを入れ忘れなければ、ストリング命令でも書ける
+
+    ALIGNB  16,DB 0
+GDT0:
+    TIMES   8 DB 0 ; ヌルセクタ
+    DW      0xffff,0x0000,0x9200,0x00cf ; 読み書き可能セグメント32bit
+    DW      0xffff,0x0000,0x9a28,0x0047 ; 実行可能セグメント32bit (bootpack用)
+
+    DW      0
+GDTR0:
+    DW      8*3-1
+    DD      GDT0
+
+    ALIGNB  16,DB 0
+bootpack:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bootpack.c	Wed Oct 03 21:06:50 2018 +0900
@@ -0,0 +1,15 @@
+extern void _io_hlt(void);
+extern void _write_mem8(int addr, int data);
+
+void HariMain(void) {
+    int i;
+    
+    for (i = 0xa0000; i <= 0xaffff; i++) {
+        _write_mem8(i,i & 0x0f);
+    }
+
+fin:
+    _io_hlt(); //これでnasmfunc.asmのio_hltが実行される
+    goto fin;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipl10.asm	Wed Oct 03 21:06:50 2018 +0900
@@ -0,0 +1,107 @@
+; hello-os
+; TAB=4
+
+CYLS EQU    10 ; どこまで読み込むか
+
+    ORG     0x7c00
+
+; 以下は標準的なFAT12フォーマットフロッピーディスクのための記述
+    
+    JMP     entry
+    DB      0x90
+
+    DB      "HARIBOTE"
+
+    DW      512 ; 1セクタの大きさ
+    DB      1 ; クラスタの大きさ
+    DW      1 ; FATがどこから始まるか
+    DB      2 ; FATの個数
+    DW      224 ; ルートディレクトリの大きさ
+    DW      2880 ; このドライブの大きさ
+    DB      0xf0 ; メディアのタイプ
+    DW      9 ; FAT領域の長さ
+    DW      18 ; 1トラックに幾つのセクタがあるか
+    DW      2 ; ヘッドの数
+    DD      0 ; パーティションを使ってここは必ず0
+    DD      2880 ; このドライブの大きさをもう一度
+    DB      0 ; physical disk number
+    DB      0 ; current head
+    DB      0x29 ; extended boot signature (0x29 means DOS 4.0 EBPB)
+    DD      0xffffffff ; ボリュームシリアルナンバー
+    DB      "HARIBOTEOS " ; ディスクの名前11バイト
+    DB      "FAT12   " ; フォーマットの名前
+    
+    TIMES   18 DB 0 ; 18バイトあけておく
+
+; プログラム本体  
+entry:
+    MOV     AX,0
+    MOV     SS,AX
+    MOV     SP,0x7c00
+    MOV     DS,AX
+
+; ディスクを読む
+    MOV     AX,0x0820
+    MOV     ES,AX
+    MOV     CH,0 ; シリンダ0
+    MOV     DH,0 ; ヘッド0
+    MOV     CL,2 ; セクタ2
+readloop:
+    MOV     SI,0 ; 失敗回数を数えるレジスタ
+retry:    
+    MOV     AH,0x02 ; AH=0x02 ディスク読み込み
+    MOV     AL,1 ; 1セクタ
+    MOV     BX,0
+    MOV     DL,0x00 ; Aドライブ
+    INT     0x13 ; ディスクBIOS呼び出し
+    JNC     next ; エラーが起きなければnextへ
+    ADD     SI,1 ; SIに1を足す
+    CMP     SI,5 ; SIを5と比較
+    JAE     error ; SI >= 5だったらerrorへ
+    MOV     AH,0x00
+    MOV     DL,0x00 ; Aドライブ
+    INT     0x13 ; ドライブのリセット
+    JMP     retry
+next:
+    MOV     AX,ES ; アドレスを0x200進める
+    ADD     AX,0x0020
+    MOV     ES,AX ; ADD ES,0x020 という命令がないのでこうしている
+    ADD     CL,1 ; CLに1を足す
+    CMP     CL,18 ; CLと18を比較
+    JBE     readloop ; CL<=18だったらreadloopへ
+    MOV     CL,1
+    ADD     DH,1
+    CMP     DH,2
+    JB      readloop ; DH < 2 だったら readloop へ
+    MOV     DH,0
+    ADD     CH,1
+    CMP     CH,CYLS
+    JB      readloop ; CH < CYLS だったら readloop へ
+
+;  読み終わったのでharibote.sysを実行だ!
+
+    MOV     [0x0ff0],CH ; IPLがどこまで読んだかをメモ
+    JMP	    0xc200
+
+error:
+    MOV     SI,msg
+putloop:
+    MOV     AL,[SI] ; SI番地の1バイトの内容をALに書き込む
+    ADD     SI,1
+    CMP     AL,0
+    JE      fin
+    MOV     AH,0x0e ; 一文字表示ファンクション
+    MOV     BX,15
+    INT     0x10
+    JMP     putloop
+fin:
+    HLT
+    JMP     fin
+msg:
+    DB      0x0a, 0x0a ; 改行を2つ
+    DB      "hello, world"
+    DB      0x0a 
+    DB      0
+
+    TIMES   0x7dfe-0x7c00-($-$$) DB 0 ; 0x01ff までスキップ
+    DB      0x55, 0xaa ; boot signature
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/iplelf.asm	Wed Oct 03 21:06:50 2018 +0900
@@ -0,0 +1,109 @@
+; hello-os
+; TAB=4
+
+CYLS EQU    10 ; どこまで読み込むか
+
+    ORG     0x7c00
+
+; 以下は標準的なFAT12フォーマットフロッピーディスクのための記述
+    
+    JMP     entry
+    DB      0x90
+
+    DB      "HARIBOTE"
+
+    DW      512 ; 1セクタの大きさ
+    DB      1 ; クラスタの大きさ
+    DW      1 ; FATがどこから始まるか
+    DB      2 ; FATの個数
+    DW      224 ; ルートディレクトリの大きさ
+    DW      2880 ; このドライブの大きさ
+    DB      0xf0 ; メディアのタイプ
+    DW      9 ; FAT領域の長さ
+    DW      18 ; 1トラックに幾つのセクタがあるか
+    DW      2 ; ヘッドの数
+    DD      0 ; パーティションを使ってここは必ず0
+    DD      2880 ; このドライブの大きさをもう一度
+    DB      0 ; physical disk number
+    DB      0 ; current head
+    DB      0x29 ; extended boot signature (0x29 means DOS 4.0 EBPB)
+    DD      0xffffffff ; ボリュームシリアルナンバー
+    DB      "HARIBOTEOS " ; ディスクの名前11バイト
+    DB      "FAT12   " ; フォーマットの名前
+    
+    TIMES   18 DB 0 ; 18バイトあけておく
+
+; プログラム本体  
+entry:
+    MOV     AX,0
+    MOV     SS,AX
+    MOV     SP,0x7c00
+    MOV     DS,AX
+
+; ディスクを読む
+    MOV     AX,0x0800
+    MOV     ES,AX
+    MOV     CH,0 ; シリンダ0
+    MOV     DH,0 ; ヘッド0
+    MOV     CL,2 ; セクタ2
+readloop:
+    MOV     SI,0 ; 失敗回数を数えるレジスタ
+retry:    
+    MOV     AH,0x02 ; AH=0x02 ディスク読み込み
+    MOV     AL,1 ; 1セクタ
+    MOV     BX,0
+    MOV     DL,0x00 ; Aドライブ
+    INT     0x13 ; ディスクBIOS呼び出し
+    JNC     next ; エラーが起きなければnextへ
+    ADD     SI,1 ; SIに1を足す
+    CMP     SI,5 ; SIを5と比較
+    JAE     error ; SI >= 5だったらerrorへ
+    MOV     AH,0x00
+    MOV     DL,0x00 ; Aドライブ
+    INT     0x13 ; ドライブのリセット
+    JMP     retry
+next:
+    MOV     AX,ES ; アドレスを0x200進める
+    ADD     AX,0x0020
+    MOV     ES,AX ; ADD ES,0x020 という命令がないのでこうしている
+    ADD     CL,1 ; CLに1を足す
+    CMP     CL,18 ; CLと18を比較
+    JBE     readloop ; CL<=18だったらreadloopへ
+    MOV     CL,1
+    ADD     DH,1
+    CMP     DH,2
+    JB      readloop ; DH < 2 だったら readloop へ
+    MOV     DH,0
+    ADD     CH,1
+    CMP     CH,CYLS
+    JB      readloop ; CH < CYLS だったら readloop へ
+
+;  読み終わったのでharibote.sysを実行だ!
+
+    MOV     [0x0ff0],CH ; IPLがどこまで読んだかをメモ
+;    MOV     SI,0xd000+0x18 ; ELF entry point offset
+;    MOV     AX,[SI]
+    JMP	    0xd190
+
+error:
+    MOV     SI,msg
+putloop:
+    MOV     AL,[SI] ; SI番地の1バイトの内容をALに書き込む
+    ADD     SI,1
+    CMP     AL,0
+    JE      fin
+    MOV     AH,0x0e ; 一文字表示ファンクション
+    MOV     BX,15
+    INT     0x10
+    JMP     putloop
+fin:
+    HLT
+    JMP     fin
+msg:
+    DB      0x0a, 0x0a ; 改行を2つ
+    DB      "hello, world"
+    DB      0x0a 
+    DB      0
+
+    TIMES   0x7dfe-0x7c00-($-$$) DB 0 ; 0x01ff までスキップ
+    DB      0x55, 0xaa ; boot signature
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nasmfunc.asm	Wed Oct 03 21:06:50 2018 +0900
@@ -0,0 +1,22 @@
+; nasmfunc
+; TAB=4
+
+;[FORMAT "WCOFF"]  ; オブジェクトファイルを作るモード
+bits 32 ; 32ビットモード用の機械語を作らせる
+
+global _io_hlt ; このプログラムに含まれる関数名
+global _write_mem8
+
+; 以下は実際の関数
+
+section .text ; オブジェクトファイルはこれを書いてからプログラムを書く
+
+_io_hlt: ; void io_hlt(void);
+    HLT
+    RET
+
+_write_mem8:
+    MOV     ECX,[ESP+4] ; [ESP+4]にaddr が入っているのでそれをECXに読み込む
+    MOV     AL,[ESP+8] ; [ESP+8]にdataが入っているのでそれをALに読み込む
+    MOV     [ECX],AL
+    RET
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/os.ls	Wed Oct 03 21:06:50 2018 +0900
@@ -0,0 +1,30 @@
+/* os.ls */
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(asmhead)
+
+SECTIONS {
+	.head 0x0 : {
+		LONG(64 * 1024) /* 0 : size(stack+.data+heap) */
+		LONG(0x69726148) /* 4 : "Hari" */
+		LONG(0) /* 8 : mmarea*/
+		LONG(0x310000) /* 12 : stack初期値 & .data転送先 */
+		LONG(SIZEOF(.data)) /* 16 : size of .data */
+		LONG(LOADADDR(.data)) /* 20 : size of .data */
+		LONG(0xE9000000) /* 24 : E9000000 */
+		LONG(HariMain - 0x20) /* 28 : entry - 0x20 */
+		LONG(0) /* 32 : heap領域開始アドレス */
+	}
+
+    . = 0xd18d;
+
+.text	: {*(.text)}
+
+	.data 0x310000 : AT ( ADDR(.text) + SIZEOF(.text) ) {
+		*(.data)
+		*(.rodata*)
+		*(.bss)
+	}
+
+	/DISCARD/ : { *(.eh_frame) }
+}