
長らく8087FPUの命令の練習を続けてきましたが、前回にて一応の完了といたしたいと思います(本人まだやる気ですが別シリーズ化の予定。)今回から32ビット、とも思いましたが、x86(16bit)範疇にはまだまだ命令が存在します。80186と80286で追加された命令どもです。なかなか32ビットモードに入れんぞなもし。
※「ぐだぐだ低レベル プログラミング」投稿順indexはこちら
※実機動作確認(といってもエミュレータなんだけれども)には以下を使用させていただいております。
現在までに練習してきた命令の範囲
x86(x64)は、広大無辺な命令セットを3つの世界に散りばめております。
-
- インテル8086を起源とする16ビット世界
- インテル80386を起源とする32ビット世界
- AMD64を起源とする64ビット世界
ここまで「1」のカテゴリを x86(16bit)と題して練習してきたつもりであったのですが、練習済の範囲は以下のようです。
-
- 8086/8088の命令セット
- 8087の命令セット
8086と8088の命令セットは同一、違いはバス幅とプリフェッチ・キューの深さのみです(蛇足ですが、8086のプリフェッチキュー2バイト分の面積を潰して、バス幅が常に8ビットになるように細工を施したものが8088デス。)
一方8087のFPU命令セットも、後継機種(80387など)が追加されるにつれ「拡張」されてますが、今までの練習では原則8087範囲といいつつ、メンドイところ(三角関数とか)は80387範囲にはみだして練習してしまってます。
さてまだ16ビット世界には残りがあります。
-
- 80186/80286に共通の拡張命令群
- 80286で導入された16ビット・プロテクトモードの命令群
「1」のカテゴリの命令は、8086/8088には無い命令ですが、長らく後継機種で活用されるものどもなので、飛ばすわけにもいきませぬ。
「2」のカテゴリの命令は、今やx86の黒歴史的な扱いでアプリケーションレベルではお目にかかることはないかと思います。しかしOSやBIOSによっては今でもブートの奥底に潜んでいるかもな命令どもデス。
今回は次回以降、そそくさと練習するつもりの命令共の一覧を掲げたいと思います。
80186/80286に共通の拡張命令群
この範疇の命令どもが以下に。
mnemonic | 命令動作 |
---|---|
ENTER | プロシージャに入る(スタックフレーム生成) |
LEAVE | プロシージャを去る(スタックフレーム消去) |
BOUND | 配列アクセスの検証命令 |
INS | ブロック入力 |
OUTS | ブロック出力 |
PUSHA | 汎用レジスタを全てプッシュ |
POPA | 汎用レジスタを全てポップ |
PUSHI | 即値のプッシュ |
IMUL immS | 符号付即値の掛け算、結果は16ビット |
shift/rotate imm | 即値指定のシフト、ローテイト |
32ビット以降でも使われている命令もあり、そうでない命令もあり。上記テーブルの先頭部分におかれたENTER/LEAVE命令などは、「セマンティック・ギャップ」が問題と叫ばれていたころに、PASCALコンパイラなどのコード生成で使われているのを見た記憶があります(いつの時代だ?) しかし、最近は使っているのを見ないなあ、残念。因みにENTER/LEAVE命令については186以降の拡張命令なのですが、x86の「標準的なスタックフレーム」を説明するのにドンピシャな命令であるので、以下の過去回で先走って既に練習済です。
ぐだぐだ低レベルプログラミング(199)x86(16bit)、ENTER、LEAVEその1
ぐだぐだ低レベルプログラミング(200)x86(16bit)、ENTER、LEAVEその2
次回以降、残りいくつかを16ビット環境で練習して、お茶を濁したいと思います。
80286で導入された16ビット・プロテクトモードの命令群
80286において導入されたプロテクトモードは、x86に4層の特権構造に基づく保護機構を導入した上で、仮想記憶も構築してくれる当時過激な「新モード」でした。ただし、286時点では16ビットの処理であり、メモリモデルはセグメンテーションのみです。
80386以降、プロテクトモードの中で32ビットのセグメントという新概念が有効となった上で、そのセグメント内でさらにページング機構によりメモリマネージメントを行う仕組みができました。すると多くのオペレーティング・システムはメンドクさいセグメンテーションの仕組みを後ろに隠し(無くなったわけではなく、初期設定時に通り抜けるのですが)、「32ビットのフラットでリニアな」メモリ空間の中で32ビットのネイティブ・アプリケーションを動かすようになりました。以降、セグメンテーションによるプロテクトモードは忘れ去られていきます。しかし、ハードウエアの奥底に隠れており、OSやBIOSのシステムブート時にこっそり動いていたりするみたいです。
この範疇の命令どもが以下に。
mnemonic | 命令動作 | リアルモードでの実行可否 |
---|---|---|
LMSW | MSWへのロード | 実行可能 |
SMSW | MSWのストア | 実行可能 |
LGDT | GDTRへのロード | 実行可能 |
SGDT | GDTRのストア | 実行可能 |
LLDT | LDTRへのロード | #UD |
SLDT | LDTRのストア | #UD |
LIDT | IDTRへのロード | 実行可能 |
SIDT | IDTRのストア | 実行可能 |
LTR | TRへのロード | #UD |
STR | TRのストア | #UD |
VERR | 読み取り可能か検証 | #UD |
VERW | 書き込み可能か検証 | #UD |
LAR | アクセス権バイトのロード | #UD |
LSL | セグメントリミットロード | #UD |
ARPL | 特権レベルの調整 | #UD |
CLTS | TSフラグのクリア | 実行可能 |
上記の命令どものうち限られたいくつかは、RESET時のデフォルトである16ビット・リアルモードから、プロテクトモードへ遷移するのに必要なので、リアルモードでも実行可能です。一方、上記で#UDと書かれた命令共は、リアルモード実行中では無用の命令どもで、実行すると未定義命令例外を引き起こすことになります。
こいつ等の練習は、ちょっとメンドイ。多分、すごくメンドイ。特にFreeDOS上で練習するのはどしたら良いの?まあ、考えてみるのが練習か。大丈夫か。