プロテクトモードのセグメント

さて、今回はプロテクトモードについてのお話ですが、リアルモード時の欠陥を補うための工夫が沢山されているので かなり難しい内容となっていますが、順番に理解していってください。

リアルモードでは、セグメントレジスタにセグメントアドレスをセットするだけでセグメントを利用できるように なりますが、プロテクトモードでは、その前にいくつかの準備をしなくてはなりません。 基本的に3つの段階がありますので、順番に説明していきます。


・セレクタ値

セグメントレジスタにセットする値のことを、セグメントを選択するという意味で「セレクタ値」と呼びます。 概念的にはセグメントの番号だと思ってください。 リアルモードでは、セグメントアドレスとセグメントベースの関係は固定的でしたが、プロテクトモードでは、セレクタ値と セグメントベースとの間に固定的な関係はありません。つまり、セレクタ値の大小が物理メモリ上での配置とは関係しないということです。 また、セレクタ値に対応するセグメントが(メモリ上に)存在しない場合さえあります。


リアルモードのセグメントアドレスは16ビットの大きさで、セグメントベースの値に応じて0000hからFFFFhまでの範囲の値をとります。 プロテクトモードのセレクタ値も同様に16ビットの大きさを持つのですが、任意の値を利用できるわけではありません。まず、セレクタ値の うち、0はセグメントレジスタを無効にするために使われます。つまり、セグメントレジスタに0をセットすると、そのセグメントレジスタを 使ったセグメントのアクセスはできなくなります。有効な値としては、0008h、0010h、0018h、0020hと、8つおきの値のみを考えることにします。 その他の値は、また後で説明します。

・セグメントディスクリプタ

プロテクトモードでも、セグメントレジスタにセグメントのセレクタ値をロードすると、その番号の付いたセグメントを指し示す ことになります。CPUがメモリをアクセスするときにはCPU内のアドレス変換回路がセグメントベースを算出しますが、セレクタ値は リニアアドレスと直接対応しないので、単純な演算で算出することはできません。

その対応は、あらかじめ「セグメントディスクリプタ」と呼ばれるものに設定しておく仕組みになっています。

プロテクトモードへの移行

486のすぐれた機能をを使用するためにはまず、プロテクトモードへ移行しなければなりません。 リアルモードからプロテクトモードへ移行するのは、意外と簡単でCR0(コントロールレジスタ0)というレジスタのPEビット (プロテクションイネーブル・ビット)のフラグを立てるだけです。

	mov eax,cr0
	or  eax,1
	mov cr0,eax
		; 以降プロテクトモードで実行される。
		;

さあ、これであなたもプロテクター使いと言いたい所ですが、実際問題プロテクトモードでは保護機能が働くのでその他にも下準備が必要です。 その手順を以下に示します。



GDTの作成 セグメントの設定
GDTRの設定
IDTの作成 割り込みの設定
IDTRの設定
アドレスバスA20ビットのマスク解除 アドレス制限の設定
CR0のPEビットをセット プロテクトモードへの移行
セグメントレジスタの再設定


プロテクトモード移行関数
;-----------------------------------------------------------
; The transition from Real-mode to Protect-mode.
; The transition from Protect-mode to Real-mode.
;       2000/12/06 Daisuke c-maker@spica.freemail.ne.jp
;-----------------------------------------------------------

.386p
_TEXT	segment byte public use16 'CODE'
	assume	cs:_TEXT

;-----------------------------------------------------------
; _RealToProtect
;
;  The transition from Real-mode to Protect-mode.
;-----------------------------------------------------------
public		_RealToProtect
_RealToProtect	proc	near
		push	bp
		mov	bp,sp
		;
		cli
		;
		mov	eax,cr0
		or	eax,1
		mov	cr0,eax
		;
		jmp	flush_q1
flush_q1:
		pop	bp
		ret
_RealToProtect	endp

;-----------------------------------------------------------
; _ProtectToReal
;
;  The transition from Protect-mode to Real-mode.
;-----------------------------------------------------------
public		_ProtectToReal
_ProtectToReal	proc	near
		push	bp
		mov	bp,sp
		;
		mov	eax,cr0
		or	eax,0fffffffeh
		mov	cr0,eax
		;
		jmp	flush_q2
flush_q2:
		pop	bp
		ret
_ProtectToReal	endp

_TEXT	ends
	end
;-----------------------------------------------------------
 プロテクトモードに移行した直後にまず実行しなければならないことは、jmp命令です。486はパイプライン処理を行っている ため、命令の取り出し・解釈・実行を並列して行っています。つまり、プロテクトモードへ移行した次の瞬間に関しては、 リアルモードとして読み込んだ命令が、プロテクトモードとして実行されるという不都合が起きてしまいます。
時間↓ 命令読み出し 命令解釈 命令実行
 1↓ 命令→ mov cr0,eax 命令→ or eax,1 命令→ mov eax,cr0
 2↓ 次の命令 mov cr0,eax or eax,1
 3↓ 次の次の命令 次の命令 mov cr0,eax

時間3の瞬間にプロテクトモードへ移行するわけだが、パイプライン処理によって、すでに次の命令次の次の命令の命令が読み込まれているので、時間4で次の命令を 実行しようとした瞬間に、リアルモードで読み込み、解釈した命令をプロテクトモードで実行しようとし不都合が発生する。 JMP命令は、実行されると、一度パイプライン中の命令が無効化されるので、この機能を利用しパイプラインを初期化しています。

リアルモードへの移行

リアルモードへの移行は、プロテクトモードへの移行の仕方とまったく一緒です。(上記プログラム参照)

上記のプログラムはC言語からコールできるようにしたあるので、実際に動作させてみましょう。

//-----------------------------------------------------------
// The transition from Real-mode to Protect-mode, and return.
//       2000/12/06 Daisuke c-maker@spica.freemail.ne.jp
//-----------------------------------------------------------

#include < stdio.h >
#include < dos.h >
#include "proto0.h"

void main()
{
	printf("Now going to Potected mode...");
	getchar();

	RealToProtect();
	ProtectToReal();

	printf("Returned from Protected mode.\n");
}
//-----------------------------------------------------------

//-----------------------------------------------------------
// Header of transition to Real-mode or Protect-mode.
//       2000/12/06 Daisuke c-maker@spica.freemail.ne.jp
//-----------------------------------------------------------
void RealToProtect();
void ProtectToReal();
//-----------------------------------------------------------

(2000/12/06)



Gポイントポイ活 Amazon Yahoo 楽天

無料ホームページ 楽天モバイル[UNLIMITが今なら1円] 海外格安航空券 海外旅行保険が無料!