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

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

新規登録して質問してみよう
ただいま回答率
85.50%
アセンブリ言語

アセンブリ言語とは、機械語を人間にわかりやすい形で記述した低水準言語です。

OS

OS(オペレーティングシステム)は、システムソフトウェアの一種であり、一般的に、ハードウェアを直接的に管理・操作する最も中心的な機能を有するソフトウェアがオペレーティングシステムとして呼ばれます。

x86

x86はIntel 8086 CPU シリーズの命令セットアルキテクチャーです。

Q&A

解決済

2回答

3771閲覧

x86のリアルモードから保護モードへの移行について

miraiz

総合スコア8

アセンブリ言語

アセンブリ言語とは、機械語を人間にわかりやすい形で記述した低水準言語です。

OS

OS(オペレーティングシステム)は、システムソフトウェアの一種であり、一般的に、ハードウェアを直接的に管理・操作する最も中心的な機能を有するソフトウェアがオペレーティングシステムとして呼ばれます。

x86

x86はIntel 8086 CPU シリーズの命令セットアルキテクチャーです。

2グッド

1クリップ

投稿2017/03/23 01:20

編集2017/03/23 01:24

現在、「作りながら学ぶOSカーネル 保護モードプログラミングの基本と実践」という本でOSの仕組みについて学んでいます。

そこで、x86プロセッサについてリアルモードから保護モードへ移行する際にCR0の最下位ビット(PEビット)を1にすることでCPUが保護モードとして動作するようになるという記載がありました。
しかし、その後の32ビットコード部分へのジャンプ命令では、prefix(0x66, 0x67)をつけているようです。
CPUはすでに保護モード(32ビット)として動いているはずなのでprefixは不要と思えるのですが、なぜ必要となるのでしょうか?
確かに、prefixを外して実行するとうまくいきませんでした。

実際のNASMのコードは下記となります。

mov eax, cr0 or eax, 0x00000001 mov cr0, eax jmp $+2 nop nop db 0x66 # <- ここ db 0x67 # <- ここ db 0xEA dd PM_Start dw SysCodeSelector
kazuya0409, tatsuya6502👍を押しています

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

動作としては PE ビットをセットした瞬間に protected mode に移行しています。
この結果としてセグメントレジスタの使い方が変わります。
(real mode であればアドレスラインの上位を直接指定していますが、protected mode では GDT を指します)

が、CPU はパイプライン(命令プリフェッチキュー)を持っているため、protected mode に移行する前にプリフェッチされた命令群は、リアルモードの CS のつもりで動作しようとしてしまいます。既に GDT に切り替わっているのに、です。当然うまく動いてくれません。
かといって protected mode に移行する前に CS を書き換えてもダメです(そうしたらそのあとの命令がうまく動かない)。
これを回避するために、キューをクリアするための方法として far jump を使うというテクニックなのです。
※far jump は同時に CS を変更できる(GDTのロードも同時に行える)ので推奨されています

投稿2017/03/23 02:14

編集2017/03/23 08:20
tacsheaven

総合スコア13703

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

miraiz

2018/06/07 19:28

今更で申し訳ないですが、質問させてください。 回答していただきましたキューをクリアするためのfar jumpについてですが、 キューのクリアはjmp $+2部分で実施していると本に書いてありました。 そのため、dbなどで直接命令を書き込んでfar jumpを実行している部分はCSを変更するためだと思うのですが、 質問の意図としては、PEビットを1にしている時点でCPUはプロテクトモードに切り替わっているはずなのに、 far jump命令になぜprefix(16ビット→32ビットと解釈させる)をつける必要があるのかということでした。 おわかりでしたら、教えていただけると嬉しいです。
tacsheaven

2018/06/07 23:45

ですから、パイプライン中に存在する「プロテクトモードで動くのだが、命令プリフェッチ時点ではリアルモードにある」命令群は、それを見越して prefix を書く必要がある、のです。
miraiz

2018/06/08 02:03

プリフェッチしたものはjmp $+2を実行した時点で消えているはずなので、far jmpのタイミングではすでにプロテクトモードで動くと思うのですが、違いますでしょうか?
tacsheaven

2018/06/08 02:26 編集

違います。大本で考えると、 mov cr0, eax を実際に実行するとき(プロテクトモードに切り替わるとき)には、その次にある jmp $+2 どころか、その先の命令群も命令プリフェッチされて解釈が終わってしまっています。ですから、その時点では「リアルモードで解釈」されてしまっているので、far jump であるという指定が必要になるのです。 ただし、far jump が完了すればその時点でパイプラインがリセットされて解釈し直されますから、後ろの全ての命令に対して記述する必要はありません。
miraiz

2018/06/08 03:12

ありがとうございます。 ということは、jmp $+2(ショートジャンプ)を実行してもパイプラインはリセットされないということでしょうか? 本には、パイプラインをリセットするためにショートジャンプを実施していると書いてありました。 ただ、実際にjmp $+2をコメントアウトして実行してみたら、確かに正常にプロテクトモードに移行できました。
tacsheaven

2018/06/08 03:19

jmp 命令を実行すればnear でも far でもパイプラインはリセットされますよ、当然。 ただ、プロテクトモードに切り替えただけでは、CSレジスタの中身がリロードされていないのです。それまでのリアルモード時のCSの中身のままだと、プロテクトモード用のGDTへアクセスできません。そこで CS レジスタのリロードを兼ねて、far jump するのです。
miraiz

2018/06/08 03:26

CSレジスタのリロードをfar jumpで実施しているというのは理解できるのですが、 jmp $+2(ショートジャンプ)でもパイプラインはリセットされるということは、 その次のfar jump命令は改めて「プロテクトモードで解釈」されていると思います。 それなのになぜprefix(16ビット→32ビットと解釈させる)が必要なのかという質問です。 プロテクトモードであればデフォルトで32ビットとして解釈するのではないでしょうか?
tacsheaven

2018/06/08 04:58 編集

ああ、どこで躓いているか分かりました。現在の 32bit/64bit な x86 プロセッサしか触ってないと勘違いしますが、プロテクトモードに切り替えただけでは、「16bit」のままなんです。ですからデフォルト32bitではないんですよ。 セグメントディスクリプタ内に16bit/32bit を制御する D ビットがあり、これがオフの場合は16bitとなります。これは80286 との互換性を担保するためです。
miraiz

2018/06/08 05:07

ありがとうございます。 プロテクトモードに切り替わっただけなら16ビットのままなんですね。 たびたびの質問申し訳ないですが、それではDビットが切り替わるタイミングはいつになるのでしょうか? farジャンプしたあとはデフォルト32ビットで動いてるようでしたので、farジャンプのタイミングでオンになるのでしょうか?
tacsheaven

2018/06/08 15:36

違います。far jump したことによりロードされた CSレジスタが指し示すセグメントディスクリプタのDビットの状態に依存します。ですから far jump したとしても、必ずしも32bit モードになるとは限りません。 ※16/32の切り替えが起きうるタイミングとしては正しい認識ですが
guest

0

5分ほど調べただけですが、

Wikipediaによると、

CR0レジスタのPEビットをセットして、far jump 命令を実行することで命令プリフェッチキューをクリアしなければならない

と書いてあるので、まだプロテクトモードにはなっていないのではないでしょうか?

投稿2017/03/23 01:44

fuzzball

総合スコア16731

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問