diff --git a/05_day/!cons_9x.bat b/05_day/!cons_9x.bat new file mode 100644 index 0000000..e42252a --- /dev/null +++ b/05_day/!cons_9x.bat @@ -0,0 +1 @@ +command \ No newline at end of file diff --git a/05_day/!cons_nt.bat b/05_day/!cons_nt.bat new file mode 100644 index 0000000..6e07473 --- /dev/null +++ b/05_day/!cons_nt.bat @@ -0,0 +1 @@ +cmd.exe \ No newline at end of file diff --git a/05_day/Makefile b/05_day/Makefile new file mode 100644 index 0000000..c33afc9 --- /dev/null +++ b/05_day/Makefile @@ -0,0 +1,85 @@ +TOOLPATH = ../z_tools/ +INCPATH = ../z_tools/haribote/ + +MAKE = $(TOOLPATH)make.exe -r +NASK = $(TOOLPATH)nask.exe +CC1 = $(TOOLPATH)cc1.exe -I$(INCPATH) -Os -Wall -quiet +GAS2NASK = $(TOOLPATH)gas2nask.exe -a +OBJ2BIM = $(TOOLPATH)obj2bim.exe +BIM2HRB = $(TOOLPATH)bim2hrb.exe +RULEFILE = $(TOOLPATH)haribote/haribote.rul +EDIMG = $(TOOLPATH)edimg.exe +IMGTOL = $(TOOLPATH)imgtol.com +COPY = copy +DEL = del + +# デフォルト動作 + +default : + $(MAKE) img + +# ファイル生成規則 + +ipl10.bin : ipl10.nas Makefile + $(NASK) ipl10.nas ipl10.bin ipl10.lst + +asmhead.bin : asmhead.nas Makefile + $(NASK) asmhead.nas asmhead.bin asmhead.lst + +bootpack.gas : bootpack.c Makefile + $(CC1) -o bootpack.gas bootpack.c + +bootpack.nas : bootpack.gas Makefile + $(GAS2NASK) bootpack.gas bootpack.nas + +bootpack.obj : bootpack.nas Makefile + $(NASK) bootpack.nas bootpack.obj bootpack.lst + +naskfunc.obj : naskfunc.nas Makefile + $(NASK) naskfunc.nas naskfunc.obj naskfunc.lst + +bootpack.bim : bootpack.obj naskfunc.obj Makefile + $(OBJ2BIM) @$(RULEFILE) out:bootpack.bim stack:3136k map:bootpack.map \ + bootpack.obj naskfunc.obj +# 3MB+64KB=3136KB + +bootpack.hrb : bootpack.bim Makefile + $(BIM2HRB) bootpack.bim bootpack.hrb 0 + +haribote.sys : asmhead.bin bootpack.hrb Makefile + copy /B asmhead.bin+bootpack.hrb haribote.sys + +haribote.img : ipl10.bin haribote.sys Makefile + $(EDIMG) imgin:../z_tools/fdimg0at.tek \ + wbinimg src:ipl10.bin len:512 from:0 to:0 \ + copy from:haribote.sys to:@: \ + imgout:haribote.img + +# コマンド + +img : + $(MAKE) haribote.img + +run : + $(MAKE) img + $(COPY) haribote.img ..\z_tools\qemu\fdimage0.bin + $(MAKE) -C ../z_tools/qemu + +install : + $(MAKE) img + $(IMGTOL) w a: haribote.img + +clean : + -$(DEL) *.bin + -$(DEL) *.lst + -$(DEL) *.gas + -$(DEL) *.obj + -$(DEL) bootpack.nas + -$(DEL) bootpack.map + -$(DEL) bootpack.bim + -$(DEL) bootpack.hrb + -$(DEL) haribote.sys + +src_only : + $(MAKE) clean + -$(DEL) haribote.img diff --git a/05_day/asmhead.nas b/05_day/asmhead.nas new file mode 100644 index 0000000..4b8b8ae --- /dev/null +++ b/05_day/asmhead.nas @@ -0,0 +1,146 @@ +; 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 ; VGAグラフィックス、320x200x8bitカラー + MOV AH,0x00 + INT 0x10 + MOV BYTE [VMODE],8 ; 画面モードをメモする(C言語が参照する) + 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 ; 読み書き可能セグメント32bit + 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 +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: diff --git a/05_day/bootpack.c b/05_day/bootpack.c new file mode 100644 index 0000000..3c9f8ce --- /dev/null +++ b/05_day/bootpack.c @@ -0,0 +1,122 @@ +void io_hlt(void); +void io_cli(void); +void io_out8(int port, int data); +int io_load_eflags(void); +void io_store_eflags(int eflags); + +void init_palette(void); +void set_palette(int start, int end, unsigned char *rgb); +void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1); +void init_screen(char *vram, int x, int y); + +#define COL8_000000 0 +#define COL8_FF0000 1 +#define COL8_00FF00 2 +#define COL8_FFFF00 3 +#define COL8_0000FF 4 +#define COL8_FF00FF 5 +#define COL8_00FFFF 6 +#define COL8_FFFFFF 7 +#define COL8_C6C6C6 8 +#define COL8_840000 9 +#define COL8_008400 10 +#define COL8_848400 11 +#define COL8_000084 12 +#define COL8_840084 13 +#define COL8_008484 14 +#define COL8_848484 15 + +void HariMain(void) +{ + char *vram; + int xsize, ysize; + short *binfo_scrnx, *binfo_scrny; + int *binfo_vram; + + init_palette(); + binfo_scrnx = (short *) 0x0ff4; + binfo_scrny = (short *) 0x0ff6; + binfo_vram = (int *) 0x0ff8; + xsize = *binfo_scrnx; + ysize = *binfo_scrny; + vram = (char *) *binfo_vram; + + init_screen(vram, xsize, ysize); + + for (;;) { + io_hlt(); + } +} + +void init_palette(void) +{ + static unsigned char table_rgb[16 * 3] = { + 0x00, 0x00, 0x00, /* 0:黒 */ + 0xff, 0x00, 0x00, /* 1:明るい赤 */ + 0x00, 0xff, 0x00, /* 2:明るい緑 */ + 0xff, 0xff, 0x00, /* 3:明るい黄色 */ + 0x00, 0x00, 0xff, /* 4:明るい青 */ + 0xff, 0x00, 0xff, /* 5:明るい紫 */ + 0x00, 0xff, 0xff, /* 6:明るい水色 */ + 0xff, 0xff, 0xff, /* 7:白 */ + 0xc6, 0xc6, 0xc6, /* 8:明るい灰色 */ + 0x84, 0x00, 0x00, /* 9:暗い赤 */ + 0x00, 0x84, 0x00, /* 10:暗い緑 */ + 0x84, 0x84, 0x00, /* 11:暗い黄色 */ + 0x00, 0x00, 0x84, /* 12:暗い青 */ + 0x84, 0x00, 0x84, /* 13:暗い紫 */ + 0x00, 0x84, 0x84, /* 14:暗い水色 */ + 0x84, 0x84, 0x84 /* 15:暗い灰色 */ + }; + set_palette(0, 15, table_rgb); + return; + + /* static char 命令は、データにしか使えないけどDB命令相当 */ +} + +void set_palette(int start, int end, unsigned char *rgb) +{ + int i, eflags; + eflags = io_load_eflags(); /* 割り込み許可フラグの値を記録する */ + io_cli(); /* 許可フラグを0にして割り込み禁止にする */ + io_out8(0x03c8, start); + for (i = start; i <= end; i++) { + io_out8(0x03c9, rgb[0] / 4); + io_out8(0x03c9, rgb[1] / 4); + io_out8(0x03c9, rgb[2] / 4); + rgb += 3; + } + io_store_eflags(eflags); /* 割り込み許可フラグを元に戻す */ + return; +} + +void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1) +{ + int x, y; + for (y = y0; y <= y1; y++) { + for (x = x0; x <= x1; x++) + vram[y * xsize + x] = c; + } + return; +} + +void init_screen(char *vram, int x, int y) +{ + boxfill8(vram, x, COL8_008484, 0, 0, x - 1, y - 29); + boxfill8(vram, x, COL8_C6C6C6, 0, y - 28, x - 1, y - 28); + boxfill8(vram, x, COL8_FFFFFF, 0, y - 27, x - 1, y - 27); + boxfill8(vram, x, COL8_C6C6C6, 0, y - 26, x - 1, y - 1); + + boxfill8(vram, x, COL8_FFFFFF, 3, y - 24, 59, y - 24); + boxfill8(vram, x, COL8_FFFFFF, 2, y - 24, 2, y - 4); + boxfill8(vram, x, COL8_848484, 3, y - 4, 59, y - 4); + boxfill8(vram, x, COL8_848484, 59, y - 23, 59, y - 5); + boxfill8(vram, x, COL8_000000, 2, y - 3, 59, y - 3); + boxfill8(vram, x, COL8_000000, 60, y - 24, 60, y - 3); + + boxfill8(vram, x, COL8_848484, x - 47, y - 24, x - 4, y - 24); + boxfill8(vram, x, COL8_848484, x - 47, y - 23, x - 47, y - 4); + boxfill8(vram, x, COL8_FFFFFF, x - 47, y - 3, x - 4, y - 3); + boxfill8(vram, x, COL8_FFFFFF, x - 3, y - 24, x - 3, y - 3); + return; +} diff --git a/05_day/ipl10.nas b/05_day/ipl10.nas new file mode 100644 index 0000000..3e016f9 --- /dev/null +++ b/05_day/ipl10.nas @@ -0,0 +1,105 @@ +; haribote-ipl +; TAB=4 + +CYLS EQU 10 ; どこまで読み込むか + + ORG 0x7c00 ; このプログラムがどこに読み込まれるのか + +; 以下は標準的なFAT12フォーマットフロッピーディスクのための記述 + + JMP entry + DB 0x90 + DB "HARIBOTE" ; ブートセクタの名前を自由に書いてよい(8バイト) + DW 512 ; 1セクタの大きさ(512にしなければいけない) + DB 1 ; クラスタの大きさ(1セクタにしなければいけない) + DW 1 ; FATがどこから始まるか(普通は1セクタ目からにする) + DB 2 ; FATの個数(2にしなければいけない) + DW 224 ; ルートディレクトリ領域の大きさ(普通は224エントリにする) + DW 2880 ; このドライブの大きさ(2880セクタにしなければいけない) + DB 0xf0 ; メディアのタイプ(0xf0にしなければいけない) + DW 9 ; FAT領域の長さ(9セクタにしなければいけない) + DW 18 ; 1トラックにいくつのセクタがあるか(18にしなければいけない) + DW 2 ; ヘッドの数(2にしなければいけない) + DD 0 ; パーティションを使ってないのでここは必ず0 + DD 2880 ; このドライブ大きさをもう一度書く + DB 0,0,0x29 ; よくわからないけどこの値にしておくといいらしい + DD 0xffffffff ; たぶんボリュームシリアル番号 + DB "HARIBOTEOS " ; ディスクの名前(11バイト) + DB "FAT12 " ; フォーマットの名前(8バイト) + RESB 18 ; とりあえず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] + 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 diff --git a/05_day/make.bat b/05_day/make.bat new file mode 100644 index 0000000..e489766 --- /dev/null +++ b/05_day/make.bat @@ -0,0 +1 @@ +..\z_tools\make.exe %1 %2 %3 %4 %5 %6 %7 %8 %9 \ No newline at end of file diff --git a/05_day/naskfunc.nas b/05_day/naskfunc.nas new file mode 100644 index 0000000..005d0f1 --- /dev/null +++ b/05_day/naskfunc.nas @@ -0,0 +1,77 @@ +; naskfunc +; TAB=4 + +[FORMAT "WCOFF"] ; オブジェクトファイルを作るモード +[INSTRSET "i486p"] ; 486の命令まで使いたいという記述 +[BITS 32] ; 32ビットモード用の機械語を作らせる +[FILE "naskfunc.nas"] ; ソースファイル名情報 + + GLOBAL _io_hlt, _io_cli, _io_sti, _io_stihlt + GLOBAL _io_in8, _io_in16, _io_in32 + GLOBAL _io_out8, _io_out16, _io_out32 + GLOBAL _io_load_eflags, _io_store_eflags + +[SECTION .text] + +_io_hlt: ; void io_hlt(void); + HLT + RET + +_io_cli: ; void io_cli(void); + CLI + RET + +_io_sti: ; void io_sti(void); + STI + RET + +_io_stihlt: ; void io_stihlt(void); + STI + HLT + RET + +_io_in8: ; int io_in8(int port); + MOV EDX,[ESP+4] ; port + MOV EAX,0 + IN AL,DX + RET + +_io_in16: ; int io_in16(int port); + MOV EDX,[ESP+4] ; port + MOV EAX,0 + IN AX,DX + RET + +_io_in32: ; int io_in32(int port); + MOV EDX,[ESP+4] ; port + IN EAX,DX + RET + +_io_out8: ; void io_out8(int port, int data); + MOV EDX,[ESP+4] ; port + MOV AL,[ESP+8] ; data + OUT DX,AL + RET + +_io_out16: ; void io_out16(int port, int data); + MOV EDX,[ESP+4] ; port + MOV EAX,[ESP+8] ; data + OUT DX,AX + RET + +_io_out32: ; void io_out32(int port, int data); + MOV EDX,[ESP+4] ; port + MOV EAX,[ESP+8] ; data + OUT DX,EAX + RET + +_io_load_eflags: ; int io_load_eflags(void); + PUSHFD ; PUSH EFLAGS という意味 + POP EAX + RET + +_io_store_eflags: ; void io_store_eflags(int eflags); + MOV EAX,[ESP+4] + PUSH EAX + POPFD ; POP EFLAGS という意味 + RET