view asmhead.asm @ 0:1a23828953f2

haribote day 4
author mir3636
date Wed, 03 Oct 2018 21:06:50 +0900
parents
children 70754edc1f50
line wrap: on
line source

; 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: