1 ; haribote-os boot asm 2 ; TAB=4 3 4 5 VBEMODE EQU 0x118 ; 1024 x 768 x 24bitカラー 6 BITPERPIXEL EQU 24 7 MEMORYMODEL EQU 6 ; 4ならインデックスカラー 6ならダイレクトカラー 8 ; (画面モード一覧) 9 ; 0x100 : 640 x 400 x 8bitカラー 10 ; 0x101 : 640 x 480 x 8bitカラー 11 ; 0x103 : 800 x 600 x 8bitカラー 12 ; 0x105 : 1024 x 768 x 8bitカラー 13 ; 0x107 : 1280 x 1024 x 8bitカラー 14 ; 0x118 : 1024 x 768 x 24bitカラー 15 16 17 BOOTPACK_CODE EQU 0x00280000 ; bootpackのロード先 18 19 ;DSKCAC EQU 0x00100000 ; ディスクキャッシュの場所 20 ;DSKCAC0 EQU 0x00008000 ; ディスクキャッシュの場所(リアルモード) 21 22 SYSPAGEDIR EQU 0x00100000 23 24 ; BOOT_INFO関係 25 BOOTDRIVE EQU 0x0ff0 ; ブートセクタが設定する 26 LEDS EQU 0x0ff1 27 VMODE EQU 0x0ff2 ; 色数に関する情報。何ビットカラーか? 28 SCRNX EQU 0x0ff4 ; 解像度のX 29 SCRNY EQU 0x0ff6 ; 解像度のY 30 VRAM EQU 0x0ff8 ; グラフィックバッファの開始番地 31 32 ORG 0xc200 ; このプログラムがどこに読み込まれるのか 33 34 ;ブートデバイスを保存 35 00000000 8816F00F mov [BOOTDRIVE], dl 36 ; VBE存在確認 37 38 00000004 B80090 MOV AX,0x9000 39 00000007 8EC0 MOV ES,AX 40 00000009 BF0000 MOV DI,0 41 0000000C B8004F MOV AX,0x4f00 42 0000000F CD10 INT 0x10 43 00000011 3D4F00 CMP AX,0x004f 44 00000014 7553 JNE scrn320 45 46 ; VBEのバージョンチェック 47 48 00000016 268B4504 MOV AX,[ES:DI+4] 49 0000001A 3D0002 CMP AX,0x0200 50 0000001D 724A JB scrn320 ; if (AX < 0x0200) goto scrn320 51 52 ; 画面モード情報を得る 53 54 0000001F B91801 MOV CX,VBEMODE 55 00000022 B8014F MOV AX,0x4f01 56 00000025 CD10 INT 0x10 57 00000027 3D4F00 CMP AX,0x004f 58 0000002A 753D JNE scrn320 59 60 ; 画面モード情報の確認 61 62 0000002C 26807D1918 CMP BYTE [ES:DI+0x19],BITPERPIXEL 63 00000031 7536 JNE scrn320 64 00000033 26807D1B06 CMP BYTE [ES:DI+0x1b],MEMORYMODEL 65 00000038 752F JNE scrn320 66 0000003A 268B05 MOV AX,[ES:DI+0x00] 67 0000003D 258000 AND AX,0x0080 68 00000040 7427 JZ scrn320 ; モード属性のbit7が0だったのであきらめる 69 70 ; 画面モードの切り替え 71 72 00000042 BB1841 MOV BX,VBEMODE | 0x4000 73 00000045 B8024F MOV AX,0x4f02 74 00000048 CD10 INT 0x10 75 0000004A C606F20F18 MOV BYTE [VMODE],BITPERPIXEL ; 画面モードをメモする(C言語が参照する) 76 0000004F 268B4512 MOV AX,[ES:DI+0x12] 77 00000053 A3F40F MOV [SCRNX],AX 78 00000056 268B4514 MOV AX,[ES:DI+0x14] 79 0000005A A3F60F MOV [SCRNY],AX 80 0000005D 26668B4528 MOV EAX,[ES:DI+0x28] 81 00000062 66A3F80F MOV [VRAM],EAX 82 00000066 E92000 JMP keystatus 83 84 scrn320: 85 00000069 B013 MOV AL,0x13 ; VGAグラフィックス、320x200x8bitカラー 86 0000006B B400 MOV AH,0x00 87 0000006D CD10 INT 0x10 88 0000006F C606F20F08 MOV BYTE [VMODE],8 ; 画面モードをメモする(C言語が参照する) 89 00000074 C706F40F4001 MOV WORD [SCRNX],320 90 0000007A C706F60FC800 MOV WORD [SCRNY],200 91 00000080 66C706F80F00000A00 MOV DWORD [VRAM],0x000a0000 92 93 ; キーボードのLED状態をBIOSに教えてもらう 94 95 keystatus: 96 00000089 B402 MOV AH,0x02 97 0000008B CD16 INT 0x16 ; keyboard BIOS 98 0000008D A2F10F MOV [LEDS],AL 99 100 ; PICが一切の割り込みを受け付けないようにする 101 ; AT互換機の仕様では、PICの初期化をするなら、 102 ; こいつをCLI前にやっておかないと、たまにハングアップする 103 ; PICの初期化はあとでやる 104 105 00000090 B0FF MOV AL,0xff 106 00000092 E621 OUT 0x21,AL 107 00000094 90 NOP ; OUT命令を連続させるとうまくいかない機種があるらしいので 108 00000095 E6A1 OUT 0xa1,AL 109 110 00000097 FA CLI ; さらにCPUレベルでも割り込み禁止 111 112 ; CPUから1MB以上のメモリにアクセスできるように、A20GATEを設定 113 114 00000098 E8F600 CALL waitkbdout 115 0000009B B0D1 MOV AL,0xd1 116 0000009D E664 OUT 0x64,AL 117 0000009F E8EF00 CALL waitkbdout 118 000000A2 B0DF MOV AL,0xdf ; enable A20 119 000000A4 E660 OUT 0x60,AL 120 000000A6 E8E800 CALL waitkbdout 121 122 ;[INSTRSET "i486p"] ; 486の命令まで使いたいという記述 123 124 ; プロテクトモード移行 125 ; page size = 4mb or 4kb (混在) pys addr size = 32 bit 126 127 000000A9 0F0116[DA01] LGDT [GDTR0] ; 暫定GDTを設定 128 000000AE 0F20C0 MOV EAX,CR0 129 ;or eax, 1 << 0x1f ; paging flag 130 ;AND EAX,0x7fffffff ; bit31を0にする(ページング禁止のため) 131 000000B1 660D01000000 OR EAX,0x00000001 ; bit0を1にする(プロテクトモード移行のため) 132 000000B7 0F22C0 MOV CR0,EAX 133 000000BA E90000 JMP pipelineflush 134 pipelineflush: 135 ;ページディレクトリ等の設定 136 137 000000BD 6631C0 xor eax, eax 138 000000C0 66B900000000 mov ecx, 0 139 140 000000C6 90 align 16 141 pagedirloop: 142 000000D0 6689C8 mov eax, ecx 143 000000D3 66C1E016 shl eax, 22 144 000000D7 660D83010000 or eax, ((1 << 8)|(1 << 7)|(1 << 1)|1) 145 000000DD 676689048D00001000 mov [SYSPAGEDIR + 4 * ecx], eax 146 147 000000E6 6641 inc ecx 148 000000E8 6681F900040000 cmp ecx, 0x400 149 000000EF 72DF jb pagedirloop 150 151 152 ;ページングの設定 153 000000F1 0F20D8 mov eax, cr3 154 000000F4 660D00001000 or eax, SYSPAGEDIR 155 000000FA 0F22D8 mov cr3, eax 156 157 000000FD 0F20E0 mov eax, cr4 158 00000100 6625DFFFFFFF and eax, ~(1 << 5) ; physical addr ext(pae) を無効に 159 00000106 660D10000000 or eax, 1 << 4; enable paging size ext(pse) 160 0000010C 0F22E0 mov cr4, eax 161 162 ;TLB無効化? 163 0000010F 0F20D8 mov eax, cr3 164 00000112 0F22D8 mov cr3, eax 165 166 00000115 0F20C0 MOV EAX,CR0 167 00000118 660D00000080 or eax, 1 << 0x1f ; paging flag 168 0000011E 0F22C0 MOV CR0,EAX 169 00000121 E90000 JMP pipelineflush2 170 pipelineflush2: 171 172 00000124 B80800 MOV AX,1*8 ; 読み書き可能セグメント32bit 173 00000127 8ED8 MOV DS,AX 174 00000129 8EC0 MOV ES,AX 175 0000012B 8EE0 MOV FS,AX 176 0000012D 8EE8 MOV GS,AX 177 0000012F 8ED0 MOV SS,AX 178 179 180 ; ついでにディスクデータも本来の位置へ転送 181 182 ; まずはブートセクタから 183 184 ;MOV ESI,0x7c00 ; 転送元 185 ;MOV EDI,DSKCAC ; 転送先 186 ;MOV ECX,512/4 187 ;CALL memcpy 188 189 ; asmheadでしなければいけないことは全部し終わったので、 190 ; あとはbootpackに任せる 191 192 ; bootpackの起動 193 194 00000131 66BB[E0010000] MOV EBX, bootpack 195 00000137 67668B4B3C MOV ECX, [EBX+0x3C] ; lfanew 196 0000013C 6601CB add ebx, ecx ; nt header 32 197 0000013F 678B4306 mov ax, [ebx + 6] ; number of section 198 00000143 67668B6B28 mov ebp, [ebx + 0x28] ; entry point 199 00000148 6681C500002800 add ebp, BOOTPACK_CODE 200 0000014F 6681C3F8000000 add ebx, 0xf8 ; section header 201 readsection: 202 00000156 67668B7B0C mov edi, [ebx + 0x0C] ; virtual addr 203 0000015B 67668B4B10 mov ecx, [ebx + 0x10] ; size of raw data 204 00000160 67668B7314 mov esi, [ebx + 0x14] ; pointer to raw data 205 00000165 6681C700002800 add edi, BOOTPACK_CODE ; このセクションのコピー先 206 0000016C 6681C6[E0010000] add esi, bootpack ; コピー元 207 00000173 FC cld 208 209 00000174 F367A4 a32 rep movsb 210 ;db 0xf3 211 ;db 0x67 212 ;db 0xa4 213 ;rep dword movsb ; f3 a4 214 215 216 00000177 6681C328000000 add ebx, 0x28 ; section header size 217 0000017E 48 dec ax 218 0000017F 75D5 jnz readsection 219 220 221 00000181 66BC00003800 MOV ESP, 0x00380000 ; スタック初期値 222 223 00000187 666810000000 push dword 2*8 224 0000018D 6655 push ebp 225 226 ;sti 227 228 229 0000018F 66CB o32 retf 230 ; call eipload 231 ; eipload: 232 ; pop ax 233 ; movzx eax, ax 234 ; mov [eax+0x15], ebp 235 ; mov dword [eax+0x19], 2*8 236 237 ; jmp dword 0:0 238 ; db 0,0 239 240 waitkbdout: 241 00000191 E464 IN AL,0x64 242 00000193 2402 AND AL,0x02 243 00000195 E460 IN AL,0x60 ; から読み(受信バッファが悪さをしないように) 244 00000197 75F8 JNZ waitkbdout ; ANDの結果が0でなければwaitkbdoutへ 245 00000199 C3 RET 246 247 memcpy: 248 0000019A 6650 push eax 249 memcpy_loop: 250 0000019C 67668B06 MOV EAX,[ESI] 251 000001A0 6681C604000000 ADD ESI,4 252 000001A7 67668907 MOV [EDI],EAX 253 000001AB 6681C704000000 ADD EDI,4 254 000001B2 6681E901000000 SUB ECX,1 255 000001B9 75E1 JNZ memcpy_loop ; 引き算した結果が0でなければmemcpyへ 256 000001BB 6658 pop eax 257 000001BD C3 RET 258 ; memcpyはアドレスサイズプリフィクスを入れ忘れなければ、ストリング命令でも書ける 259 260 261 000001BE ALIGNB 16 262 ****************** warning: uninitialized space declared in .text section: zeroing 263 GDT0: 264 000001C0 RESB 8 ; ヌルセレクタ 265 ****************** warning: uninitialized space declared in .text section: zeroing 266 000001C8 FFFF00000092CF00 db 0xff,0xff,0x00,0x00,0x00,0x92,0xcf,0x00 ; 読み書き可能セグメント32bit 267 ;db 0xff,0xff,0x00,0x00,0x28,0x9a,0x4f,0x00 ; 実行可能セグメント32bit(bootpack用) 268 000001D0 FFFF0000009ACF00 db 0xff,0xff,0x00,0x00,0x00,0x9a,0xcf,0x00 ; 実行可能セグメント32bit(bootpack用) 269 270 000001D8 0000 DW 0 271 GDTR0: 272 000001DA 1700 DW 8*3-1 273 000001DC [C0010000] DD GDT0 274 275 ALIGNB 16 276 bootpack: