1 ; haribote-os boot asm
2 ; TAB=4
3
4 BOTPAK EQU 0x00280000 ; bootpackのロード先
5 DSKCAC EQU 0x00100000 ; ディスクキャッシュの場所
6 DSKCAC0 EQU 0x00008000 ; ディスクキャッシュの場所(リアルモード)
7
8 ; 有关BOOT_INFO
9 CYLS EQU 0x0ff0 ; 设定启动区
10 LEDS EQU 0x0ff1
11 VMODE EQU 0x0ff2 ; 关于颜色数目的信息。颜色的位数。
12 SCRNX EQU 0x0ff4 ; 分辨率的X(screen x)
13 SCRNY EQU 0x0ff6 ; 分辨率的Y(screen y)
14 VRAM EQU 0x0ff8 ; 图像缓冲区的开始地址
15
16 ORG 0xc200 ; 这个程序将要被装载到内存的什么地方呢?
17
18 ; 画面モードを設定
19
20 MOV AL,0x13 ; VGA显卡,320x200x8bit彩色
21 MOV AH,0x00
22 INT 0x10
23 MOV BYTE [VMODE],8 ; 记录画面模式
24 MOV WORD [SCRNX],320
25 MOV WORD [SCRNY],200
26 MOV DWORD [VRAM],0x000a0000
27
28 ; 用BIOS取得键盘上各种LED指示灯的状态
29
30 MOV AH,0x02
31 INT 0x16 ; keyboard BIOS
32 MOV [LEDS],AL
33
34 ; PICが一切の割り込みを受け付けないようにする
35 ; AT互換機の仕様では、PICの初期化をするなら、
36 ; こいつをCLI前にやっておかないと、たまにハングアップする
37 ; PICの初期化はあとでやる
38
39 MOV AL,0xff
40 OUT 0x21,AL
41 NOP ; OUT命令を連続させるとうまくいかない機種があるらしいので
42 OUT 0xa1,AL
43
44 CLI ; さらにCPUレベルでも割り込み禁止
45
46 ; CPUから1MB以上のメモリにアクセスできるように、A20GATEを設定
47
48 CALL waitkbdout
49 MOV AL,0xd1
50 OUT 0x64,AL
51 CALL waitkbdout
52 MOV AL,0xdf ; enable A20
53 OUT 0x60,AL
54 CALL waitkbdout
55
56 ; プロテクトモード移行
57
58 [INSTRSET "i486p"] ; 486の命令まで使いたいという記述
59
60 LGDT [GDTR0] ; 暫定GDTを設定
61 MOV EAX,CR0
62 AND EAX,0x7fffffff ; bit31を0にする(ページング禁止のため)
63 OR EAX,0x00000001 ; bit0を1にする(プロテクトモード移行のため)
64 MOV CR0,EAX
65 JMP pipelineflush
66 pipelineflush:
67 MOV AX,1*8 ; 読み書き可能セグメント32bit
68 MOV DS,AX
69 MOV ES,AX
70 MOV FS,AX
71 MOV GS,AX
72 MOV SS,AX
73
74 ; bootpackの転送
75
76 MOV ESI,bootpack ; 転送元
77 MOV EDI,BOTPAK ; 転送先
78 MOV ECX,512*1024/4
79 CALL memcpy
80
81 ; ついでにディスクデータも本来の位置へ転送
82
83 ; まずはブートセクタから
84
85 MOV ESI,0x7c00 ; 転送元
86 MOV EDI,DSKCAC ; 転送先
87 MOV ECX,512/4
88 CALL memcpy
89
90 ; 残り全部
91
92 MOV ESI,DSKCAC0+512 ; 転送元
93 MOV EDI,DSKCAC+512 ; 転送先
94 MOV ECX,0
95 MOV CL,BYTE [CYLS]
96 IMUL ECX,512*18*2/4 ; シリンダ数からバイト数/4に変換
97 SUB ECX,512/4 ; IPLの分だけ差し引く
98 CALL memcpy
99
100 ; asmheadでしなければいけないことは全部し終わったので、
101 ; あとはbootpackに任せる
102
103 ; bootpackの起動
104
105 MOV EBX,BOTPAK
106 MOV ECX,[EBX+16]
107 ADD ECX,3 ; ECX += 3;
108 SHR ECX,2 ; ECX /= 4;
109 JZ skip ; 転送するべきものがない
110 MOV ESI,[EBX+20] ; 転送元
111 ADD ESI,EBX
112 MOV EDI,[EBX+12] ; 転送先
113 CALL memcpy
114 skip:
115 MOV ESP,[EBX+12] ; スタック初期値
116 JMP DWORD 2*8:0x0000001b
117
118 waitkbdout:
119 IN AL,0x64
120 AND AL,0x02
121 JNZ waitkbdout ; ANDの結果が0でなければwaitkbdoutへ
122 RET
123
124 memcpy:
125 MOV EAX,[ESI]
126 ADD ESI,4
127 MOV [EDI],EAX
128 ADD EDI,4
129 SUB ECX,1
130 JNZ memcpy ; 引き算した結果が0でなければmemcpyへ
131 RET
132 ; memcpyはアドレスサイズプリフィクスを入れ忘れなければ、ストリング命令でも書ける
133
134 ALIGNB 16
135 GDT0:
136 RESB 8 ; ヌルセレクタ
137 DW 0xffff,0x0000,0x9200,0x00cf ; 読み書き可能セグメント32bit
138 DW 0xffff,0x0000,0x9a28,0x0047 ; 実行可能セグメント32bit(bootpack用)
139
140 DW 0
141 GDTR0:
142 DW 8*3-1
143 DD GDT0
144
145 ALIGNB 16
146 bootpack: