デスティネーション・オペランドがセグメント・レジスタ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
では、STIも1命令の間割り込みをディレイさせるので、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をポップする。