IF とか EFLAGS とかを操作する命令たち

ia32 なプロセッサにおいてはマスク可能割り込みの制御のために EFLAGS レジスタというレジスタに IF (Interrupt Enable Flag) というフィールド (ってかビット) が用意されており、このフィールドの値でマスク可能ハードウェア割り込み要求に対する CPU の応答を制御しているとの事。
この EFLAGS というレジスタは限られた命令でしかレジスタ内の値を操作できないとの事で、以下に IF ビットの操作に関連する命令セットに限定して列挙。

  • popf
    スタックから pop した値を EFLAGS に設定
  • pushf
    EFLAGS の値をスタックに push
  • sti
    IF の値を 1 に設定 (割り込み可能フラグを設定)
  • cli
    IF の値を 0 に設定 (割り込み可能フラグをクリア)
  • iret
    EIP、CS、EFLAGS (場合によっては SP、SS) レジスタをスタックから復帰し、割り込まれたプログラムの実行に戻る

これらの命令はamazon:Linuxカーネル解析入門の3章「同期と排他」において紹介されているマクロにて使用されている。

include/asm-i386/system.h より抜粋 (一部整形)

#define local_irq_restore(x) 	do { typecheck(unsigned long,x); \
    __asm__ __volatile__("pushl %0 ; popfl" \
                         : /* no output */  \
			 :"g" (x)           \
			 :"memory", "cc");  \
} while (0)
#define local_irq_disable() 	__asm__ __volatile__("cli": : :"memory")
#define local_irq_enable()	__asm__ __volatile__("sti": : :"memory")
#define local_irq_save(x)	\
    __asm__ __volatile__("pushfl ; popl %0 ; cli" \
                         :"=g" (x)                \
                         : /* no input */         \
                         :"memory")

typecheck マクロについては略。
又、iret 命令については割り込み処理の現時点で分かっている部分のまとめなエントリを入れようと思っておりますのでそちらで可能な限りのフォローを入れてみたいと。

追記

IA-32 インテル®アーキテクチャ ソフトウェア・デベロッパーズ・マニュアル下巻 5.8.1.マスク可能ハードウェア割り込みのマスキングの項に STI および CLI 以外で IF フラグが影響を受ける操作が箇条書きにされている。以下に引用。

  • PUSHF 命令はすべてのフラグをスタック上にストアする。ここではフラグを検査したり変更できる。POPF 命令を使用すると、変更されたフラグを元の EFLAGS レジスタへロードできる。
  • タスクスイッチおよび POPF と IRET 命令は、EFLAGS レジスタをロードする。したがって、これらを使用して IF フラグの設定値を変更できる。
  • 割り込みが割り込みゲートを介して処理される場合、IF フラグは自動的にクリアされ、したがってマスク可能ハードウェア割り込みはディスエーブルされる。(割り込みがトラップゲートを介して処理される場合は、IF フラグはクリアされない。)

IA-32 インテル®アーキテクチャ ソフトウェア・デベロッパーズ・マニュアル下巻より引用