• 検索結果がありません。

デスティネーション・オペランドがセグメント・レジスタDS、ES、FS、GS、または SSの1つである場合は、レジスタにロードされる値は、有効なセグメント・セレクタ でなければならない。保護モードでは、セグメント・セレクタをセグメント・レジス タにポップすると、そのセグメント・セレクタに関連するディスクリプタ情報がセグ メント・レジスタの隠蔽(シャドー)部分に自動的にロードされ、セレクタおよび ディスクリプタの情報が有効にされる(下記の「操作」の項を参照)。

一般保護フォルトを発生させずにヌル値(0000~0003)をDS、ES、FS、またはGS レジスタにポップすることができる。ただし、対応するセグメント・レジスタにヌル 値がロードされているセグメントをその後で参照しようとすると、一般保護例外

(#GP)が発生する。この状況では、メモリ参照は行われず、セグメント・レジスタの セーブされた値はヌルである。

POP命令では、値をCSレジスタにポップすることはできない。スタックからCSレジ スタにロードするには、RET命令を使用する。

メモリ内のデスティネーション・オペランドのアドレスを指定するベースレジスタと してESPレジスタを使用すると、POP命令は、ESPレジスタをインクリメントした後 にオペランドの実効アドレスを計算する。16ビット・スタックでPOP命令を実行した 結果、ESPレジスタが0hにラップされた場合は、結果のメモリ書き込みの位置はプロ セッサのファミリによって異なる。

POP ESP命令は、スタックの古いトップにあるデータをデスティネーションに書き込

む前に、スタックポインタ(ESP)をインクリメントする。

POP SS命令は、次の命令の実行後まで、NMI割り込みを含めたすべての割り込みを 禁止する。この処置によって、POP SS命令およびMOV ESP,EBP命令を逐次に実行し ても、割り込みによってスタックが無効になる危険はない2。ただし、SSレジスタお よびESPレジスタをロードする方法としては、LSS命令の使用が望ましい。

2.以降の命令を過ぎて割り込みを個別にディレイさせる命令シーケンスでは、シーケンスの最初の命令は、割り 込みをディレイさせることが保証されるが、後続の割り込みディレイ命令は、割り込みをディレイさせない場 合があることに注意する。そのため、次の命令シーケンス

STI POP SS POP ESP

では、STI1命令の間割り込みをディレイさせるので、POP ESPが実行される前に、割り込みが認識される ことがある。

POP—Pop a Value from the Stack(続き)

操作

IF StackAddrSize = 32 THEN

IF OperandSize = 32 THEN

DEST ← SS:ESP; (* copy a doubleword *) ESP ← ESP + 4;

ELSE (* OperandSize = 16*)

DEST ← SS:ESP; (* copy a word *) ESP ← ESP + 2;

FI;

ELSE (* StackAddrSize = 16* ) IF OperandSize = 16

THEN

DEST ← SS:SP; (* copy a word *) SP ← SP + 2;

ELSE (* OperandSize = 32 *)

DEST ← SS:SP; (* copy a doubleword *) SP ← SP + 4;

FI;

FI;

保護モードの間にセグメント・レジスタをロードすると、以下のリストで説明してい るように特殊な処置が行われる。これらのチェックは、セグメント・セレクタとそれ が指しているセグメント・ディスクリプタに対して行われる。

IF SS is loaded;

THEN

IF segment selector is null THEN #GP(0);

FI;

IF segment selector index is outside descriptor table limits OR segment selector's RPL ≠ CPL

OR segment is not a writable data segment OR DPL ≠ CPL

THEN #GP(selector);

FI;

IF segment not marked present THEN #SS(selector);

ELSE

POP—Pop a Value from the Stack(続き)

OR ((segment is a data or nonconforming code segment) AND (both RPL and CPL > DPL))

THEN #GP(selector);

IF segment not marked present THEN #NP(selector);

ELSE

SegmentRegister ← segment selector;

SegmentRegister ← segment descriptor;

FI;

FI;

IF DS, ES, FS, or GS is loaded with a null selector;

THEN

SegmentRegister ← segment selector;

SegmentRegister ← segment descriptor;

FI;

影響を受けるフラグ

なし。

保護モード例外

#GP(0) ヌル・セグメント・セレクタでSSレジスタをロードしようとした場

合。

デスティネーション・オペランドが書き込み不可能なセグメントにあ る場合。

メモリ・オペランドの実効アドレスがCS、DS、ES、FS、またはGS セグメントの範囲外の場合。

DS、ES、FS、またはGSレジスタを使用してメモリがアクセスされ、

レジスタの内容がヌル・セグメント・セレクタであった場合。

#GP(セレクタ) セグメント・セレクタ・インデックスがディスクリプタ・テーブルの

範囲外の場合。

SSレジスタがロードされ、セグメント・セレクタのRPLおよびセグ メント・ディスクリプタのDPLがCPLに等しくない場合。

SS レジスタがロードされ、指示先のセグメントが書き込み不可能な データ・セグメントである場合。

DS、ES、FS、またはGSレジスタがロードされ、指示先のセグメン トがデータ・セグメントまたは読み取り可能なコード・セグメントで ない場合。

DS、ES、FS、またはGSレジスタがロードされ、指示先のセグメン

トがデータ・セグメントまたは非コンフォーミング・コード・セグメ ントであるが、RPLおよびCPLの両方ともDPLより大きい場合。

POP—Pop a Value from the Stack(続き)

#SS(0) スタックの現在のトップがスタック・セグメント内にない場合。

メモリ・オペランドの実効アドレスがSSセグメントの範囲外の場合。

#SS(セレクタ) SS レジスタがロードされ、指示先のセグメントが存在しないとマー クされている場合。

#NP DS、ES、FS、またはGSレジスタがロードされ、指示先のセグメン

トが存在しないとマークされている場合。

#PF(フォルトコード) ページフォルトが発生した場合。

#AC(0) 現行特権レベルが3のときに、アライメント・チェックがイネーブル

にされていて、アライメントが合わないメモリ参照が行われた場合。

実アドレスモード例外

#GP メモリ・オペランドの実効アドレスがCS、DS、ES、FS、またはGS セグメントの範囲外の場合。

仮想8086モード例外

#GP(0) メモリ・オペランドの実効アドレスがCS、DS、ES、FS、またはGS セグメントの範囲外の場合。

#PF(フォルトコード) ページフォルトが発生した場合。

#AC(0) アライメント・チェックがイネーブルにされていて、アライメントが

合わないメモリ参照が行われた場合。

説明

ダブルワード(POPAD)またはワード(POPA)をスタックから汎用レジスタにポッ プする。レジスタがロードされる順番は、(オペランド・サイズ属性が32である場合 は)EDI、ESI、EBP、EBX、EDX、ECX、EAXであり、(オペランド・サイズ属性が 16である場合は)DI、SI、BP、BX、DX、CX、AXである。これらの命令は、PUSHA/PUSHAD 命令の逆の操作を実行する。ESPレジスタまたはSPレジスタのスタック上の値は無視 される。その代わりに、ESPレジスタまたはSPレジスタは、各レジスタがロードされ た後にインクリメントされる。

POPA(すべてをポップ)ニーモニックおよびPOPAD(すべてのダブルをポップ)ニー モニックは、同じオペコードを参照する。POPA命令は、オペランド・サイズ属性が 16であるときに使用するためのものであり、POPAD命令は、オペランド・サイズ属 性が32であるときに使用するためのものである。一部のアセンブラは、(必要な場合 にはオペランド・サイズ・オーバライド・プリフィックス[66H]を使用して)POPAが 使用されるときはオペランド・サイズを16に、POPADが使用されるときは32に強制 する。他のアセンブラは、これらのニーモニックをシノニム(POPA/POPAD)として 取り扱い、オペランド・サイズ属性の現在の設定を使用して、使用されているニーモ ニックに関係なく、スタックからポップする値のサイズを決定することができる。(現 在のコード・セグメントのセグメント・ディスクリプタのDフラグによって、オペラ ンド・サイズ属性が決まる。)

操作

IF OperandSize = 32 (* instruction = POPAD *) THEN

EDI ← Pop();

ESI ← Pop();

EBP ← Pop();

increment ESP by 4 (* skip next 4 bytes of stack *) EBX ← Pop();

EDX ← Pop();

ECX ← Pop();

EAX ← Pop();

オペコード 命令 説明

61 POPA DI、SI、BP、BX、DX、CX、AXをポップする。

61 POPAD EDI、ESI、EBP、EBX、EDX、ECX、EAXをポップする。