Intel x86 Assembly Language & Microarchitecture
登録の基礎
サーチ…
16ビットレジスタ
インテルがオリジナルの8086を定義したとき、それは20ビットのアドレスバスを持つ16ビットプロセッサでした(下記参照)。彼らは8つの汎用16ビットレジスタを定義しましたが、特定の命令に特定の役割を与えました。
-
AXAccumulatorレジスタ。
多くのオペコードがこのレジスタを使用していたか、指定されていれば高速でした。 -
DXデータレジスタ。
これは、時には乗算の結果として、AXとの32ビット値の上位16ビットとして結合されました。 -
CXCountレジスタ。
これは、LOOPNE(等しくなければループ)やREP(繰り返しの移動/比較)などのループの暗黙のカウンタとして、多くのループ指向の命令で使用されていました。 -
BXベースレジスタ。
これはメモリ内の構造体の基底を索引付けするために使用できます。上記のいずれのレジスタもメモリに直接索引付けすることはできません。 -
SIソースインデックスレジスタ。
これは、特定の移動操作と比較操作のためのメモリへの暗黙のソース索引でした。 -
DIデスティネーションインデックスレジスタ。
これは、特定の移動および比較操作のためのメモリへの暗黙の宛先インデックスでした。 -
SPスタックポインタレジスタ。
これはセット内で最も汎用性の低いレジスタです!スタックの現在の位置を指していました。これはPUSHとPOP操作に明示的に使用され、暗黙的にサブルーチンでCALLとRET、割り込み中に暗黙的に使用されました。そのようなものとして、それを他のものに使用することはあなたのプログラムにとって危険でした! -
BPベースポインタレジスタ。
サブルーチンが他のサブルーチンを呼び出すとき、スタックは複数の "スタックフレーム"を保持します。BPは現在のスタックフレームを保持するために使用され、新しいサブルーチンが呼び出されるとスタックに保存され、新しいスタックフレームが作成されて使用され、内部サブルーチンから戻ると古いスタックフレーム値が復元されます。
ノート:
最初の3つのレジスタは、メモリへのインデックス付けには使用できません。
BX、SI、およびDIを既定で現在のデータセグメントにインデックスします(下記参照)。MOV AX, [BX+5] ; Point into Data Segment MOV AX, ES:[DI+5] ; Override into Extra SegmentDI、MOVSやCMPSなどのメモリからメモリへの操作で使用される場合、Extra Segmentを単独で使用します(下記参照)。これは無効にすることはできません。SPとBPはデフォルトでスタックセグメント(下記参照)を使用します。
32ビットレジスタ
インテルが80386を生産したとき、彼らは16ビットプロセッサから32ビットプロセッサにアップグレードしました。 32ビット処理とは、操作されるデータが32ビットであり、アクセスされるメモリアドレスが32ビットであったという2つのことを意味します。これを行うには、以前のプロセッサーとの互換性を維持しながら、プロセッサーには全く新しいモードが導入されました。これは16ビットモードまたは32ビットモードのいずれかでしたが、データ、アドレッシング、またはその両方のために命令ごとにこのモードをオーバーライドすることができます。
まず、32ビットレジスタを定義しなければなりませんでした。彼らは、既存の8ビットを16ビットから32ビットに単純に拡張し、 E接頭辞: EAX 、 EBX 、 ECX 、 EDX 、 ESI 、 EDI 、 EBP 、およびESP持つ「拡張」名を付けるだけです。これらのレジスタの下位16ビットは以前と同じでしたが、レジスタの上半分はADDやCMPなどの32ビット演算で使用できました。上半分は、8ビットレジスタで行ったように個別にアクセスすることはできませんでした。
インテルは16ビットモードとCMP EAX,EDX CMP AX,DX 、32ビットモードのCMP EAX,EDXが同じオペコードを使用していたため、プロセッサは別々の16ビットと32ビットモードを持つ必要がありました。 !つまり、どちらのモードでも同じコードを実行することはできませんでした。
"Move immediate into
AX"のオペコードは0xB8であり、2バイトの0xB8に続く:0xB8 0x12 0x34
「Move immediate into
EAX」のオペコードは0xB8、その後に4バイトの0xB8が続きます0xB8 0x12 0x34 0x56 0x78
したがって、assemberは、コードを実行するときにプロセッサがどのモードにあるかを知っていなければならないので、正しいバイト数を出力することができます。
8ビットレジスタ
最初の4つの16ビット・レジスタは、自身のレジスタとして直接アクセスされる上位バイトと下位バイトを持つことができます。
-
AHとALはAXレジスタの上位と下位の半分です。 -
BHおよびBLは、BXレジスタのBXおよび下位の半分です。 -
CHとCLはCXレジスタのHighとLowの半分です。 -
DHとDLはDXレジスタの上位と下位の半分です。
これは、 AHまたはALを変更するとAXもすぐに変更されることに注意してください。また、8ビットレジスタ上のどのような操作も、 0xFFから0x00オーバフローしてAH変更しないように、その "パートナー"インクリメントAL影響を与えることはできません。
64ビットレジスタには、下位バイトを表す8ビットバージョンもあります。
-
RSISIL -
RDIためのDIL -
RBPBPL -
RSPSPL
同じことは、レジスタに適用R8経由R15 :それぞれの下位バイトのパーツの名前はR8B - R15B 。
セグメントレジスタ
セグメンテーション
インテルがオリジナルの8086を設計していたときには、既に16ビット機能を備えた8ビットプロセッサが多数存在しましたが、真の16ビットプロセッサを作りたがっていました。彼らはまた、すでに存在していたものよりも優れたものを作り出すことを望んでいたので、16ビットアドレッシングレジスタが意味する最大65,536バイト以上のメモリにアクセスできるようにしたいと考えました。
オリジナルセグメントレジスタ
そこで彼らは、「セグメント」(16ビットアドレスレジスタによってインデックスされた64キロバイトのメモリブロック)の考え方を実装しました。これは、トータルメモリのさまざまな領域に対応するために再ベースされる可能性があります。これらのセグメントベースを保有するために、セグメントレジスタ:
-
CSコードセグメントレジスタ。
これは現在実行中のコードのセグメントを保持し、暗黙のIP(命令ポインタ)レジスタによってインデックスされます。 -
DSデータセグメントレジスタ。
これは、プログラムによって操作されるデータのデフォルトセグメントを保持します。 -
ESエクストラセグメントレジスタ。
これは、全メモリにわたる同時データ操作のための第2のデータセグメントを保持する。 -
SSスタックセグメントレジスタ。
現在のスタックを保持するメモリのセグメントを保持します。
セグメントサイズ?
セグメントレジスタのサイズは任意ですが、16ビット幅にすると他のレジスタとの相互運用が容易になりました。次の質問は、セグメントが重なっているかどうか、そうであれば、いくらですか?その質問に対する答えは、アクセス可能なメモリの合計サイズを指定します。
オーバーラップがまったくない場合、アドレス空間は32ビット - 4ギガバイトになります - その時点ではまったく知られていないサイズです! 8ビットの「自然な」オーバーラップは、24ビットのアドレス空間、つまり16メガバイトを生成します。最後に、インテルはプロセッサに4つのアドレスピンを追加することにしました。これは12メガバイトのアドレス空間を12ビットのオーバーラップで作成することで実現しました。
より多くのセグメントレジスタ!
インテルが80386を設計していたとき、彼らは既存の4セグメントレジスタのスイートでは、サポートできるプログラムの複雑さが十分ではないことを認識しました。彼らはさらに2つを追加しました:
-
FSファーセグメントレジスタ -
GSグローバルセグメント登録
これらの新しいセグメントレジスタには、プロセッサによって強制される用途はありませんでした。
いくつかの名前は、単に既存のセットの
C、D、Eテーマを続行するために選択されたと言う...
64ビットレジスタ
AMDは互換性があるが競合するバージョンを作成するためにインテルから80386の設計をライセンスしたプロセッサーメーカーです。設計の内部的な変更を行ってスループットやその他のデザインの強化を改善し、同じプログラムを実行することができました。
Intelは、Intel 32ビット設計の64ビット拡張を思いつき、32ビットx86コードを実行できる最初の64ビットチップを製造した。 Intelは64ビットアーキテクチャのバージョンでAMDの設計に従った。
64ビットデザインでは、レジスタセットに多くの変更が加えられましたが、それでも下位互換性があります。
- 既存の汎用レジスタは64ビットに拡張され、
R接頭辞:RAX、RBX、RCX、RDX、RSI、RDI、RBP、およびRSP名前が付けられました。再び、これらのレジスタの下半分は以前と同じ
Eプリフィックスレジスタであり、上半分は独立してアクセスすることができませんでした。 -
R8、R9、R10、R11、R12、R13、R14、R158つの64ビットレジスタが追加され、名前は付けられていません。- これらのレジスタの32ビットの下位半分は
R8DR15D(DWORDは通常どおり)。 - これらのレジスタの最下位16ビットが接尾辞を付けることによってアクセスすることができる
W:レジスタ名にR8W介しR15W。
- これらのレジスタの32ビットの下位半分は
- 16個のレジスタすべての下位8ビットにアクセスできるようになりました。
- 伝統的な
AL、BL、CL、DL。 - (伝統的に)ポインタレジスタの下位バイト:
SIL、DIL、BPL、およびSPL。 - そして8つの新しいレジスタの下位バイト:
R8BからR15B。 - ただし、
AH、BH、CH、およびDHは、REX接頭辞(64ビットオペランドサイズ、R8〜R15へのアクセス、SIL、DIL、BPL、またはSPLへのアクセス)を使用する命令ではアクセスできません。 REXプレフィックスを使用すると、代わりにAHを意味していたマシンコードのビットパターンはSPLを意味します。インテルの命令リファレンスマニュアル(第2巻)の表3-1を参照してください。
- 伝統的な
32ビットレジスタへの書き込みは、8ビットまたは16ビットレジスタへの書き込みとは異なり、フルサイズレジスタの上位32ビットを常にゼロにします(これは古い値とマージします。これは、アウトオブオーダー実行の余分な依存性です) )。
フラグ登録
x86算術論理装置(ALU)がNOTやADDような演算を実行すると、特別な16ビットFLAGSレジスタでこれらの演算の結果にフラグを立てます( "0"、 "オーバーフロー"、 "負になりました")。 32ビットプロセッサはこれを32ビットにアップグレードしてEFLAGSと呼び、64ビットプロセッサはこれを64ビットにアップグレードしてRFLAGSと呼んだ。
条件コード
しかし、名前にかかわらず、登録簿に直接アクセスすることはできません(いくつかの指示を除いて - 下記参照)。代わりに、個々のフラグはJccおよびSETccと呼ばれる条件付きジャンプまたは条件付きセットなどの特定の命令で参照され、 ccは「条件コード」を意味し、次の表を参照します。
| コンディションコード | 名 | 定義 |
|---|---|---|
E 、 Z | 等しい、ゼロ | ZF == 1 |
NE 、 NZ | 平等ではない、ゼロでない | ZF == 0 |
O | オーバーフロー | OF == 1 |
NO | オーバーフローなし | OF == 0 |
S | 署名された | SF == 1 |
NS | 署名されていない | SF == 0 |
P | パリティ | PF == 1 |
NP | パリティなし | PF == 0 |
| -------------- | ---- | ---------- |
C 、 B 、 NAE | 持ち運ぶ、下に、上にない、または等しい | CF == 1 |
NC 、 NB 、 AE | 運ばない、下にない、等しいまたは等しい | CF == 0 |
A 、 NBE | 上、下またはそれ以下 | CF == 0およびZF == 0 |
NA 、 BE | 上ではない、以下または等しい | CF == 1またはZF == 1 |
| --------------- | ---- | ---------- |
GE 、 NL | より大きいか等しい、より少なくない | SF == OF |
NGE 、 L | より大きいまたは等しい、より少ない | SF != OF |
G 、 NLE | より大きい、少ない、または同等ではない | ZF == 0、 SF == OF |
NG 、 LE | そうではない、より小さい、または等しい | ZF == 1またはSF != OF |
16ビットでは、 0から1を引いた0は、符号なしまたは符号付き算術が使用されているかどうかによって65,535または-1いずれかですが、宛先は0xFFFFいずれかの方法で保持します。それは、意味が明確である条件コードを解釈することだけです。さらに1が0x8000から減算されているかどうかを示します。符号なし算術では、 32,768が32,767変更されます。署名付き算術演算では-32,768を32,767に変更します - はるかに注目すべきオーバーフローです!
条件コードは、表内の3つのブロックにグループ分けされています。つまり、符号無関係、符号なし、および符号付きです。後者の2つのブロック内の名前は、符号なしの場合は「Above」と「Below」を使用し、署名の場合は「Greater」または「Less」を使用します。だから、 JBは「ジャンプするならば」(署名なし)、 JLは「ジャンプするならば」(署名した)となります。
FLAGSへの直接アクセス
上記の条件コードはあらかじめ定義された概念を解釈するのに便利ですが、実際のフラグビットは次の2つの命令で直接利用できます。
-
LAHFAHレジスタにフラグをロードする -
SAHFAHレジスタをフラグに格納する
特定のフラグだけがこれらの命令でコピーされます。 FLAGS / EFLAGS / RFLAGSレジスタ全体をスタックに保存または復元することができます。
-
PUSHF/POPFプッシュ/ポップ16ビットFLAGSスタックから/へ -
PUSHFD/POPFDプッシュ/ポップは、32ビットEFLAGSスタックから/へ -
PUSHFQ/POPFQプッシュ/ポップ64ビットRFLAGS上/スタックから
割り込みは、現在の[R/E]FLAGSレジスタを自動的に保存および復元することに注意してください。
その他のフラグ
上記のALUフラグと同様に、 FLAGSレジスタは他のシステム状態フラグを定義します。
-
IF割り込みフラグ。
これは、割り込みをグローバルに有効にするSTI命令で設定され、CLI命令でクリアされて割り込みをグローバルに無効にします。 -
DF方向フラグ。
CMPSおよびMOVS(メモリ位置を比較および移動する)などのメモリ間演算は、命令の一部としてインデックスレジスタを自動的にインクリメントまたはデクリメントします。DFフラグは、どちらが起きるかを指示します:CLD命令でクリアされた場合、それらはインクリメントされます。STD命令で設定されている場合、それらはデクリメントされます。 -
TFトラップフラグ。これはデバッグフラグです。これを設定すると、プロセッサは「シングルステップ」モードになります。各命令が実行されると、デバッガによって処理されると予想される「シングルステップ割り込みハンドラ」が呼び出されます。このフラグを設定またはクリアする方法はありません。ビットがメモリにある間にビットを操作する必要があります。
80286フラグ
Intelは、80286の新しいマルチタスキング機能をサポートするために、 FLAGSレジスタに追加のフラグを追加しました。
-
IOPLI / O特権レベル。
マルチタスクコードを保護するために、I / Oポートにアクセスするための権限が必要なタスクもあれば、アクセスを停止する必要があったタスクもありました。インテルはで、4レベルの特権スケールを導入002は、ほとんどの特権であり、かつ112以上です。IOPLが現在の特権レベルよりもIOPLた場合、I / Oポートへのアクセスやインタラプトの有効/無効を試みると、代わりに一般保護違反が発生します。 -
NTネストされたタスクフラグ。
このフラグは、1つのタスクが別のタスクをCALL設定され、コンテキスト切り替えが発生しました。セットフラグは、RETが実行されたときにコンテクストスイッチバックを行うようにプロセッサに指示した。
80386フラグ
'386には、プロセッサに設計された特別な機能をサポートするために余分なフラグが必要でした。
-
RF再開フラグ。
`386はデバッグレジスタを追加しました。これは、特定のmemry場所の読み込み、書き込み、実行など、さまざまなハードウェアアクセスでデバッガを呼び出す可能性があります。しかし、デバッグハンドラが命令を実行するために返されたとき、 アクセスは即座にデバッグハンドラを呼び出すでしょう!少なくとも、デバッグハンドラへのエントリ時に自動的に設定され、命令ごとに自動的にクリアされるレジュームフラグがない場合は、再開フラグが設定されている場合、デバッグハンドラは呼び出されません。 -
VM仮想8086フラグ。
古い32ビットコードと新しい32ビットコードをサポートするため、80386はVirtual 8086エグゼクティブの助けを借りて、 "Virtual 8086"モードで16ビットタスクを実行できます。VMフラグは、このタスクが仮想8086タスクであることを示しました。
80486フラグ
インテルのアーキテクチャーが向上するにつれて、キャッシュやスーパースカラーの実行などの技術により高速化しました。それは前提を作ることによってシステムへのアクセスを最適化しなければならなかった。これらの仮定を制御するために、より多くのフラグが必要でした:
-
ACアライメントチェックフラグx86アーキテクチャでは、サイズを調整する必要があるアーキテクチャ(4バイトの値は4バイトの境界にある必要があります)とは異なり、常にすべてのバイト境界でマルチバイトのメモリ値にアクセスできます。しかし、整列されていないデータにアクセスするには複数のメモリ・アクセスが必要だったため、効率的ではありませんでした。ACフラグがセットされていれば、アラインされていないアクセスはコードを実行するのではなく例外を発生させます。こうすることで、ACコードを使用してコードを開発する際にコードを改善することができますが、実動コードではコードを無効にすることができます。
Pentium Flags
Pentiumは、仮想化のサポートとCPUID命令のサポートを追加しました。
-
VIF仮想割り込みフラグ。
これは、このタスクのIF仮想コピーです。このタスクが割り込みを無効にしたいかどうかに関係なく、実際にグローバル割り込みに影響することはありません。 -
VIP仮想割り込みペンディングフラグ。
これは、割り込みがVIFによって実質的にブロックされたことを示します。したがって、タスクがSTIすると、仮想割り込みを発生させることができます。 -
IDCPUID許可されたフラグ。
このタスクがCPUID命令を実行することを許可するかどうか。仮想モニタはそれを禁止し、命令を実行する場合は要求しているタスクに「横たわる」ことができます。