|
| 1 | +[INSTRSET "i486p"] |
| 2 | +;============================================ |
| 3 | +;============================================ |
| 4 | + |
| 5 | + |
| 6 | +VBEMODE EQU 0x103 |
| 7 | +; 0x100 : 640 x 400 x 8bitキヨア貭ハ |
| 8 | +; 0x101 : 640 x 480 x 8bitキヨア貭ハ |
| 9 | +; 0x103 : 800 x 600 x 8bitキヨア貭ハ |
| 10 | +; 0x105 : 1024 x 768 x 8bitキヨア貭ハ |
| 11 | +; 0x107 : 1280 x 1024 x 8bitキヨア貭ハ |
| 12 | + |
| 13 | + |
| 14 | +;============================================ |
| 15 | +;============================================ |
| 16 | + |
| 17 | +BOTPAK EQU 0x00280000 |
| 18 | +DSKCAC EQU 0x00100000 |
| 19 | +DSKCAC0 EQU 0x00008000 |
| 20 | + |
| 21 | + |
| 22 | +CYLS EQU 0x0ff0 |
| 23 | +LEDS EQU 0x0ff1 |
| 24 | +VMODE EQU 0x0ff2 |
| 25 | +SCRNX EQU 0x0ff4 |
| 26 | +SCRNY EQU 0x0ff6 |
| 27 | +VRAM EQU 0x0ff8 |
| 28 | + |
| 29 | + ORG 0xc200 |
| 30 | + MOV AX,0x9000 |
| 31 | + MOV ES,AX |
| 32 | + MOV DI,0 |
| 33 | + MOV AX,0x4f00 |
| 34 | + INT 0x10 |
| 35 | + CMP AX,0x004f |
| 36 | + JNE scrn320 |
| 37 | + MOV AX,[ES:DI+4] |
| 38 | + CMP AX,0x0200 |
| 39 | + JB scrn320 ; if (AX < 0x0200) goto scrn320 |
| 40 | + MOV CX,VBEMODE |
| 41 | + MOV AX,0x4f01 |
| 42 | + INT 0x10 |
| 43 | + CMP AX,0x004f |
| 44 | + JNE scrn320 |
| 45 | + CMP BYTE [ES:DI+0x19],8 |
| 46 | + JNE scrn320 |
| 47 | + CMP BYTE [ES:DI+0x1b],4 |
| 48 | + JNE scrn320 |
| 49 | + MOV AX,[ES:DI+0x00] |
| 50 | + AND AX,0x0080 |
| 51 | + JZ scrn320 ; モード属性のbit7が0だったのであきらめる |
| 52 | + MOV BX,VBEMODE+0x4000 |
| 53 | + MOV AX,0x4f02 |
| 54 | + INT 0x10 |
| 55 | + MOV BYTE [VMODE],8 ; 画面モードをメモする(C言語が参照する) |
| 56 | + MOV AX,[ES:DI+0x12] |
| 57 | + MOV [SCRNX],AX |
| 58 | + MOV AX,[ES:DI+0x14] |
| 59 | + MOV [SCRNY],AX |
| 60 | + MOV EAX,[ES:DI+0x28] |
| 61 | + MOV [VRAM],EAX |
| 62 | + JMP keystatus |
| 63 | + |
| 64 | +scrn320: |
| 65 | + MOV AL,0x13 ; VGAグラフィックス、320x200x8bitカラー |
| 66 | + MOV AH,0x00 |
| 67 | + INT 0x10 |
| 68 | + MOV BYTE [VMODE],8 ; 画面モードをメモする(C言語が参照する) |
| 69 | + MOV WORD [SCRNX],320 |
| 70 | + MOV WORD [SCRNY],200 |
| 71 | + MOV DWORD [VRAM],0x000a0000 |
| 72 | + |
| 73 | +; キーボードのLED状態をBIOSに教えてもらう |
| 74 | + |
| 75 | +keystatus: |
| 76 | + MOV AH,0x02 |
| 77 | + INT 0x16 ; keyboard BIOS |
| 78 | + MOV [LEDS],AL |
| 79 | + |
| 80 | +; PICが一切の割り込みを受け付けないようにする |
| 81 | +; AT互換機の仕様では、PICの初期化をするなら、 |
| 82 | +; こいつをCLI前にやっておかないと、たまにハングアップする |
| 83 | +; PICの初期化はあとでやる |
| 84 | + |
| 85 | + MOV AL,0xff |
| 86 | + OUT 0x21,AL |
| 87 | + NOP ; OUT命令を連続させるとうまくいかない機種があるらしいので |
| 88 | + OUT 0xa1,AL |
| 89 | + |
| 90 | + CLI ; さらにCPUレベルでも割り込み禁止 |
| 91 | + |
| 92 | +; CPUから1MB以上のメモリにアクセスできるように、A20GATEを設定 |
| 93 | + |
| 94 | + CALL waitkbdout |
| 95 | + MOV AL,0xd1 |
| 96 | + OUT 0x64,AL |
| 97 | + CALL waitkbdout |
| 98 | + MOV AL,0xdf ; enable A20 |
| 99 | + OUT 0x60,AL |
| 100 | + CALL waitkbdout |
| 101 | + |
| 102 | +; プロテクトモード移行 |
| 103 | + |
| 104 | + LGDT [GDTR0] ; 暫定GDTを設定 |
| 105 | + MOV EAX,CR0 |
| 106 | + AND EAX,0x7fffffff ; bit31を0にする(ページング禁止のため) |
| 107 | + OR EAX,0x00000001 ; bit0を1にする(プロテクトモード移行のため) |
| 108 | + MOV CR0,EAX |
| 109 | + JMP pipelineflush |
| 110 | +pipelineflush: |
| 111 | + MOV AX,1*8 ; 読み書き可能セグメント32bit |
| 112 | + MOV DS,AX |
| 113 | + MOV ES,AX |
| 114 | + MOV FS,AX |
| 115 | + MOV GS,AX |
| 116 | + MOV SS,AX |
| 117 | + |
| 118 | +; bootpackの転送 |
| 119 | + |
| 120 | + MOV ESI,bootpack ; 転送元 |
| 121 | + MOV EDI,BOTPAK ; 転送先 |
| 122 | + MOV ECX,512*1024/4 |
| 123 | + CALL memcpy |
| 124 | + |
| 125 | +; ついでにディスクデータも本来の位置へ転送 |
| 126 | + |
| 127 | +; まずはブートセクタから |
| 128 | + |
| 129 | + MOV ESI,0x7c00 ; 転送元 |
| 130 | + MOV EDI,DSKCAC ; 転送先 |
| 131 | + MOV ECX,512/4 |
| 132 | + CALL memcpy |
| 133 | + |
| 134 | +; 残り全部 |
| 135 | + |
| 136 | + MOV ESI,DSKCAC0+512 ; 転送元 |
| 137 | + MOV EDI,DSKCAC+512 ; 転送先 |
| 138 | + MOV ECX,0 |
| 139 | + MOV CL,BYTE [CYLS] |
| 140 | + IMUL ECX,512*18*2/4 ; シリンダ数からバイト数/4に変換 |
| 141 | + SUB ECX,512/4 ; IPLの分だけ差し引く |
| 142 | + CALL memcpy |
| 143 | + |
| 144 | +; asmheadでしなければいけないことは全部し終わったので、 |
| 145 | +; あとはbootpackに任せる |
| 146 | + |
| 147 | +; bootpackの起動 |
| 148 | + |
| 149 | + MOV EBX,BOTPAK |
| 150 | + MOV ECX,[EBX+16] |
| 151 | + ADD ECX,3 ; ECX += 3; |
| 152 | + SHR ECX,2 ; ECX /= 4; |
| 153 | + JZ skip ; 転送するべきものがない |
| 154 | + MOV ESI,[EBX+20] ; 転送元 |
| 155 | + ADD ESI,EBX |
| 156 | + MOV EDI,[EBX+12] ; 転送先 |
| 157 | + CALL memcpy |
| 158 | +skip: |
| 159 | + MOV ESP,[EBX+12] ; スタック初期値 |
| 160 | + JMP DWORD 2*8:0x0000001b |
| 161 | + |
| 162 | +waitkbdout: |
| 163 | + IN AL,0x64 |
| 164 | + AND AL,0x02 |
| 165 | + IN AL,0x60 ; から読み(受信バッファが悪さをしないように) |
| 166 | + JNZ waitkbdout ; ANDの結果が0でなければwaitkbdoutへ |
| 167 | + RET |
| 168 | + |
| 169 | +memcpy: |
| 170 | + MOV EAX,[ESI] |
| 171 | + ADD ESI,4 |
| 172 | + MOV [EDI],EAX |
| 173 | + ADD EDI,4 |
| 174 | + SUB ECX,1 |
| 175 | + JNZ memcpy ; 引き算した結果が0でなければmemcpyへ |
| 176 | + RET |
| 177 | +; memcpyはアドレスサイズプリフィクスを入れ忘れなければ、ストリング命令でも書ける |
| 178 | + |
| 179 | + ALIGNB 16 |
| 180 | +GDT0: |
| 181 | + RESB 8 ; ヌルセレクタ |
| 182 | + DW 0xffff,0x0000,0x9200,0x00cf ; 読み書き可能セグメント32bit |
| 183 | + DW 0xffff,0x0000,0x9a28,0x0047 ; 実行可能セグメント32bit(bootpack用) |
| 184 | + |
| 185 | + DW 0 |
| 186 | +GDTR0: |
| 187 | + DW 8*3-1 |
| 188 | + DD GDT0 |
| 189 | + |
| 190 | + ALIGNB 16 |
| 191 | +bootpack: |
0 commit comments