はじめて読む486 5章
セグメント
- メモリの区画割り
- 8086のセグメント機構は64Kバイトに制限されていたため有害無益と言われていた
プロテクトモードではセグメント機構が持つメリットを十分に発揮できるようになっている
セグメント方式
- メモリを区画割りする方式の一種
8086のセグメント方式の欠点
- セグメントの大きさが64Kバイトに制限されている
- セグメント間に保護機能がない
- 486では上記を解決した
セグメントアドレスとオフセットアドレス
セグメント方式によるメモリの指定方法
- CPUとメモリはアドレスバスという信号線で結ばれている
- CPUからメモリにアクセスする際には、アドレスバスに物理メモリのアドレスをアドレスバスに出力する
- しかし、CPUが実行するマシン語プログラムは物理メモリを指定することができない
- そこで、セグメントアドレスとオフセットアドレスによってメモリを指定する
セグメントアドレス
- セグメントに付けられたアドレス - オフセットアドレス
- セグメントの先頭から数えた通し番号
アドレス変換回路
アドレス変換回路の役割
- ソフトウェアからみたメモリのイメージをハードウェアとしてのメモリのイメージに変換する
セグメントとセグメントレジスタ
マシン語プログラムでは必ずセグメントアドレスとオフセットアドレスの組によってメモリを指定する
- セグメントアドレスは最初にセグメントレジスタに設定しておき、メモリをアクセスする個々の命令ではオフセットアドレスのみ指定する
セグメントレジスタ
CS
DS
命令を実行する時に見に行くセグメントを指定
命令の解釈はCPU内で行うのでメモリにアクセスはいかない
- 命令の実行時にメモリのアクセスが発生する
- 命令の実行によるメモリアクセスは原則としてDSレジスタの指すセグメント
SS
スタック領域として使うセグメントを指し示す
命令の実行時によるメモリアクセスでDS以外のセグメントレジスタが使われるときはSSのものが使われる
- スタック領域へのアクセス
- PUSH,POP,CALL,RETなどスタック領域をアクセスする命令ではSSレジスタの指すセグメントがアクセスされる
その他のセグメントレジスタ
- 予備のレジスタ
- マシンご命令の実行によるメモリアクセスは、スタック領域へのアクセス以外は基本的にDSレジスタの指すセグメントに対して行われる
- この原則を変更するのがセグメントオーバーライドプリフィックス
- DSレジスタを使うはずの命令でESを使ったりできる
リアルモードのセグメント
アドレス変換回路にセグメントアドレスとセグメントベースを対応させる方法は、リアルモードとプロテクトモードで異なる
リアルモード
- セグメントアドレスは、セグメントベースと固定的に対応する
- セグメントアドレスをそのまま4~19ビット目までに当てはめて、残りのビットを0にする
OSはメモリ空間全体を通して付けられた一連の番号であるリニアアドレスを用いてセグメントの区切りを管理する
- しかし、実際にメモリにアクセスするときには、リニアアドレスではなく、セグメントアドレスを使用する
- ゆえに、セグメントベースからセグメントアドレスを逆算する
問題点
- セグメント先頭の物理アドレスの下位4ビットは常に0となるため、セグメントは必ず16の倍数のアドレスから始まらないといけない
- セグメントベースの20ビット目より上が常に0になる
- 20ビットで表せる範囲(1Mバイト)より大きなアドレスをセグメントベースとするセグメントを扱えない
- 1Mバイトの壁
- 20ビットで表せる範囲(1Mバイト)より大きなアドレスをセグメントベースとするセグメントを扱えない
- オフセットアドレスも16ビットのあたしか指定することができないのでセグメントの大きさは最大で64Kバイトになる
- 64Kバイトの壁
- セグメントの大きさはすべて64Kバイトになる
- セグメントの大きさを任意に設定する機構がない
- 他のセグメントにアクセスしてしまう可能性がある
- セグメントの大きさを任意に設定する機構がない
プロテクトモードのセグメント
- 下記の3つの手順を行ってから、セグメントを利用する
- メモリの割当を決める
- ディスクリプタテーブルを作る
GDTRにディスクリプタテーブルのアドレスをロードする
セレクタ値
セグメントディスクリプタ
セグメント割り当ての仕組み
286のセグメントディスクリプタ
- セグメントのリミット値、セグメントベース、属性が順番に入っている
- セグメントベース
- セグメント先頭とのリニアアドレスを入れておく
- 24ビットあるので16Mバイトのメモリの任意のアドレスをセットできる
- リミット値
- 「セグメントの大きさ - 1」 = オフセットアドレスとして許される最大値をいれる
- 属性
- セグメントの種類などの情報をいれておく
486のセグメントディスクリプタ
- セグメントベースが1バイト増えて32ビット(=4Gバイト)になった
- リミット値、属性は20ビット
GDTR
セグメントディスクリプタキャッシュ