ikemonn's blog

技術ネタをちょこちょこと

はじめて読む486 5章

セグメント

  • メモリの区画割り
  • 8086のセグメント機構は64Kバイトに制限されていたため有害無益と言われていた
  • プロテクトモードではセグメント機構が持つメリットを十分に発揮できるようになっている

  • セグメント方式

    • メモリを区画割りする方式の一種
  • 8086のセグメント方式の欠点

      1. セグメントの大きさが64Kバイトに制限されている
      1. セグメント間に保護機能がない
    • 486では上記を解決した

セグメントアドレスとオフセットアドレス

  • セグメント方式によるメモリの指定方法

    • CPUとメモリはアドレスバスという信号線で結ばれている
    • CPUからメモリにアクセスする際には、アドレスバスに物理メモリのアドレスをアドレスバスに出力する
    • しかし、CPUが実行するマシン語プログラムは物理メモリを指定することができない
    • そこで、セグメントアドレスとオフセットアドレスによってメモリを指定する
  • セグメントアドレス

    • セグメントに付けられたアドレス - オフセットアドレス
    • セグメントの先頭から数えた通し番号
  • アドレス変換回路

    • セグメントと物理アドレスを結びつける
    • セグメントアドレスとオフセットアドレスの組をリニアアドレスと呼ばれるアドレスに変換する
      • セグメントアドレスをセグメント先頭のリニアアドレスに変換する(セグメントベース)
      • セグメントベースにオフセットアドレスを加えてリニアアドレスを算出
      • リニアアドレスとは物理アドレスと同様に、全メモリの先頭から待つ今で連続して付けられた通し番号のこと
        • ページング機能をONにしなければ、そのまま物理アドレスとしてアドレスバスに出力される
  • アドレス変換回路の役割

    • ソフトウェアからみたメモリのイメージをハードウェアとしてのメモリのイメージに変換する

セグメントとセグメントレジスタ

  • マシン語プログラムでは必ずセグメントアドレスとオフセットアドレスの組によってメモリを指定する

    • セグメントアドレスは最初にセグメントレジスタに設定しておき、メモリをアクセスする個々の命令ではオフセットアドレスのみ指定する
  • セグメントレジスタ

    • セグメントを指し示すためのレジスタ
    • セグメントレジスタにセグメントアドレスをセットすると、そのセグメントを指し示すようになる
    • オフセットアドレスはセグメント内のアドレスとかんがえられる
    • CS,DS,ES,SS,FS,GSの6つある

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バイトの壁
        
    • オフセットアドレスも16ビットのあたしか指定することができないのでセグメントの大きさは最大で64Kバイトになる
      • 64Kバイトの壁
    • セグメントの大きさはすべて64Kバイトになる
      • セグメントの大きさを任意に設定する機構がない
        • 他のセグメントにアクセスしてしまう可能性がある

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

  • 下記の3つの手順を行ってから、セグメントを利用する
  • メモリの割当を決める
  • ディスクリプタテーブルを作る
  • GDTRにディスクリプタテーブルのアドレスをロードする

  • セレクタ

    • セグメントレジスタにセットする値のこと
    • リアルモードでは「セグメントアドレス」
    • プロテクトモードでは「セレクタ値」
    • 概念としてはセグメントにつけた背番号のようなもの
    • セレクタ値とセグメントベースの間に固定的な関係はない
      • セレクタ値の大小は物理メモリ上での配置とは関係しない
    • セレクタ値も16ビットの大きさを持つが、0008,0010,0018のように8つおきのアドレスを使う
  • セグメントディスクリプタ

    • セグメントに関する情報をひとまとめにしたもので、セグメントの設計図ともいえる
      • セグメントベース、エグメンとの大きさ、セグメントの属性の3つからなる(バイト)
    • アドレス変換回路がここから情報を読み出すことで、セレクタ値をセグメントベースに変換する
    • セレクタ値の順番にディスクリプタテーブルに納められている
  • セグメント割り当ての仕組み

    1. . OSがメモリ割り当ての要求を受ける
    2. メモリの空いている領域を確保する
    3. ディスクリプタテーブルの空いている引き出しを探して確保する
    4. その引き出しのセグメントディスクリプタに確保したメモリ領域の先頭アドレス(セグメントベース)、サイズ等の情報をいれる
    5. この引き出しの番号を返す
    6. 返ってきたセレクタ値をセグメントレジスタにセット
    7. メモリにアクセス
  • 286のセグメントディスクリプタ

    • セグメントのリミット値、セグメントベース、属性が順番に入っている
    • セグメントベース
      • セグメント先頭とのリニアアドレスを入れておく
      • 24ビットあるので16Mバイトのメモリの任意のアドレスをセットできる
    • リミット値
      • 「セグメントの大きさ - 1」 = オフセットアドレスとして許される最大値をいれる
    • 属性
      • セグメントの種類などの情報をいれておく
  • 486のセグメントディスクリプタ

    • セグメントベースが1バイト増えて32ビット(=4Gバイト)になった
    • リミット値、属性は20ビット
  • GDTR

  • セグメントディスクリプタキャッシュ