質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.04%

【アセンブリ言語】プロテクトモードへの移行

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 1,900
退会済みユーザー

退会済みユーザー

プロテクトモードへの移行をしたいんですが、仮想OSが重大エラーが起きて、上手くできないんです。まだ初めてばかりですので、どうかよろしくお願いします。

*追記*
A20以上有効とプロテクトモード有効をBIOSサービス割り込みのシステムサービスでやっても、重大エラーが起きたので、もしかしたらGDTの内容が間違っている部分があるかもしれません。よろしければGDTの解説もお願いします。

【変更したソースの一部】

        CALL Enable_A20;A20以上有効
        
        MOV EAX, CR0; CR0レジスタの値を読み出します
        OR  EAX, 1; PEビットをOR命令でONします
        MOV CR0, EAX; そのままCR0に書き込みます
        JMP CODE_DESC:OS32
-------------------------------------------------------------------------------------------------
Enable_A20:
        CLI; 割り込み禁止
        
        CALL A20wait; ウェイト処理
        MOV AL, 0xAD; キーボード無効化
        OUT 0x64, AL
        
        CALL A20wait; ウェイト処理
        MOV AL, 0xD0; リードアウトプットポートコマンド送信
        OUT 0x64, AL
        
        CALL A20wait2; アウトプットポートの値が書き込まれるまでウェイト
        IN AL, 0x60; リードバッファレジスタ読み込み
        PUSH EAX; 読み込んだデータをスタックに保存
        
        CALL A20wait; ウェイト処理
        MOV AL, 0xD1; ライトアウトプットポートコマンド送信
        OUT 0x64, AL
        
        CALL A20wait; ウェイト処理
        POP EAX; 読み込んだアウトプットポートの値を元に戻す
        OR AL, 0x2; A20有効ビットを1にする
        OUT 0x60, AL; A20有効にする出力データを送信
        
        CALL A20wait; ウェイト処理
        MOV AL, 0xAE; キーボード有効
        OUT 0x64, AL
        
        CALL A20wait; ウェイト処理
        
        STI; 割り込み有効
        RET
A20wait:; ウェイト処理関数
        IN AL, 0x64; ステータスレジスタ読み込み
        TEST AL, 0x2; 送信したコマンド処理が完了をチェック
        JNZ A20wait; 完了していない場合はループ
        RET
A20wait2:; アウトプットポートの値が書き込まれるまでウェイト処理関数
        IN AL, 0x64; ステータスレジスタ読み込み
        TEST AL, 0x1; 値が書き込まれたかインプットバッファフルをチェック
        JZ A20wait2; 書き込まれていない場合はループ
        RET

        MOV AX, 0x2401;A20以上有効
        INT 0x15
        
        MOV AH, 0x89;プロテクトモード有効
        PUSH CODE_DESC
        POP ES
        MOV SI, OS32
        INT 0x15


【仮想OSソフトウェア】
Oracle VM VirtualBox
VMware

【コンパイラ】
nasm

【現状】
初期化済み
カーネルロード済み
さらに初期化済み
VESAモード設定済み
GDT設定済み
A20以上有効済み
CR0でプロテクトモード有効・・・重大エラー発生
↓を追記して、コンパイルし、仮想OS起動すると重大エラーが起きました
        MOV EAX, CR0; CR0レジスタの値を読み出します
        OR  EAX, 1; PEビットをOR命令でONします
        MOV CR0, EAX; そのままCR0に書き込みます
        JMP CODE_DESC:OS32

【一部ソース】
CODE_DESC    EQU 0x08
DATA_DESC    EQU 0x10

[BITS 16]

ORG 0xC200

JMP OS

%include "SetVESAmode.inc"

OS:
        ;初期化
        XOR AX, AX
        XOR BX, BX
        XOR CX, CX
        XOR DX, DX
        MOV DS, AX
        MOV ES, AX
        MOV    AX, 0x9000        ; スタックポインタを0x0009FFFCに設定する
        MOV    SS, AX
        MOV    SP, 0xFFFC
        
        ;ビデオモード自動設定
        CALL SET_VIDEO_VESA
        JNC .set_video_vesa_OK
        JMP fin
        
        .set_video_vesa_OK:
        
        CALL _setup_gdt;GDT設定
        CALL Enable_A20;A20以上有効
        
        MOV EAX, CR0; CR0レジスタの値を読み出します
        OR  EAX, 1; PEビットをOR命令でONします
        MOV CR0, EAX; そのままCR0に書き込みます
        JMP CODE_DESC:OS32
        
        JMP fin
        
_setup_gdt:
        CLI
        PUSHA
        LGDT [gdt_OS32]
        STI
        POPA
        RET

Enable_A20:
        CLI; 割り込み禁止
        
        CALL A20wait; ウェイト処理
        MOV AL, 0xAD; キーボード無効化
        OUT 0x64, AL
        
        CALL A20wait; ウェイト処理
        MOV AL, 0xD0; リードアウトプットポートコマンド送信
        OUT 0x64, AL
        
        CALL A20wait2; アウトプットポートの値が書き込まれるまでウェイト
        IN AL, 0x60; リードバッファレジスタ読み込み
        PUSH EAX; 読み込んだデータをスタックに保存
        
        CALL A20wait; ウェイト処理
        MOV AL, 0xD1; ライトアウトプットポートコマンド送信
        OUT 0x64, AL
        
        CALL A20wait; ウェイト処理
        POP EAX; 読み込んだアウトプットポートの値を元に戻す
        OR AL, 0x2; A20有効ビットを1にする
        OUT 0x60, AL; A20有効にする出力データを送信
        
        CALL A20wait; ウェイト処理
        MOV AL, 0xAE; キーボード有効
        OUT 0x64, AL
        
        CALL A20wait; ウェイト処理
        
        STI; 割り込み有効
        RET
A20wait:; ウェイト処理関数
        IN AL, 0x64; ステータスレジスタ読み込み
        TEST AL, 0x2; 送信したコマンド処理が完了をチェック
        JNZ A20wait; 完了していない場合はループ
        RET
A20wait2:; アウトプットポートの値が書き込まれるまでウェイト処理関数
        IN AL, 0x64; ステータスレジスタ読み込み
        TEST AL, 0x1; 値が書き込まれたかインプットバッファフルをチェック
        JZ A20wait2; 書き込まれていない場合はループ
        RET
        
gdt_OS32:
        DW 8*3
        DD _gdt
_gdt:
        ;NULL
        DW 0x0000
        DW 0x0000
        DW 0x0000
        DW 0x0000
        ;コード
        DB 0xFF
        DB 0xFF
        DW 0x0000
        DB 0x00
        DB 0x9A
        DB 0xCF
        DB 0x00
        ;データ
        DB 0xFF
        DB 0xFF
        DW 0x0000
        DB 0x00
        DB 0x92
        DB 0xCF
        DB 0x00

fin:
        HLT
        JMP fin

[BITS 32]

OS32:
        ;初期化
        MOV AX, DATA_DESC; DATA_DESCには0x10が入っています
        MOV SS, AX; 以下データセグメントセレクタを入れています
        MOV ES, AX
        MOV FS, AX
        MOV GS, AX
        MOV DS, AX
        
        MOV ESP, 0x90000; スタックポインタも初期化します
        
fin32:
        HLT
        JMP fin32
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • kazuyakazuya

    2020/01/30 07:30

    これってfar jmpをせずに
    movでセグメントレジスターを設定しているから
    cpuの先読みのところでおかしくなっているのでは?

    と思ったのですが
    違うのでしょうか?

    キャンセル

  • kazuyakazuya

    2020/01/30 07:30

    OS32:
    ;初期化
    MOV AX, DATA_DESC; DATA_DESCには0x10が入っています
    MOV SS, AX; 以下データセグメントセレクタを入れています
    MOV ES, AX
    MOV FS, AX
    MOV GS, AX
    MOV DS, AX

    MOV ESP, 0x90000; スタックポインタも初期化します

    キャンセル

回答 1

checkベストアンサー

0

丸投げ感溢れる回答です。先に謝っておきます…ごめんなさい。

自分はOSを作るところまでの興味は持ち合わせていなかったのでブートローダの動作を読んだ程度ですが、もしPC向けOSの習作を考えているのであれば、この記事が足掛かりにできるのではないでしょうか。

ご存知なければ、一読してみては如何でしょう。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/08/10 10:29

    プロテクトモードへの移行できたかわかりませんが、紹介してもらったhttp://www.brokenthorn.com/Resources/OSDev8.htmlのGDT.incをインクルードし、CALLで処理させたら、BIOSサービス割り込みのプロテクトモード有効処理はエラーが起きましたが、前に設定してあったCR0のPE変更に元に戻すとエラー起きませんでした。解決できたと思うので何かまた問題など起きましたら、よろしくお願いします。

    キャンセル

  • 2015/08/10 21:05

    プロテクトモードへの移行が問題なくできているので、助かりました。

    キャンセル

  • 2015/08/10 22:12 編集

    後顧の憂はなくした方がいいので、GDTの設定内容は早めに把握した方がいいと思いますよw
    ともあれ役に立って良かったです。
    頑張ってください!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.04%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る