アンティーク・アセンブラ~Antique Assembler

第3回 もしも“if”なら

この記事を読むのに必要な時間:およそ 10.5 分

論理積/論理和

実際の条件分岐で指定される条件は,必ずしも前節で述べたような単純な形式ではありません。

たとえば,以下のような条件判定の実装は珍しいものではありません:

リスト6 論理積

if(a && b && c){
    x = 1;
}

上記のような論理積(logical multiplication)を実現する場合,Cコンパイラが生成するアセンブラプログラムは以下のようになります。

リスト7 論理積の実装

    # 変数 a 領域の格納値から 0 を引く
    cmpl    $0, a
    # 演算結果が 0 であったら notmatched に遷移
    # ⇒ 変数 a が 0 なら notmatched に遷移
    je      notmatched

    # 変数 b 領域の格納値から 0 を引く
    cmpl    $0, b
    # 演算結果が 0 であったら notmatched に遷移
    je      notmatched

    # 変数 c 領域の格納値から 0 を引く
    cmpl    $0, c
    # 演算結果が 0 であったら notmatched に遷移
    je      notmatched

    # a && b && c だったので,"x = 1" を実施
    movl    $1, x

notmatched:
    # 以下,if 文以後の処理が記述される

また

リスト8 論理和

if(a || b || c){
    x = 1;
}

上記の様な論理和(logical addition)を実現する場合,Cコンパイラが生成するアセンブラプログラムは以下のようになります。

リスト9 論理和の実装

    # 変数 a 領域の格納値から 0 を引く
    cmpl    $0, a
    # 演算結果が非 0 であったら matched に遷移
    # ⇒ 変数 a が非 0 であったら matched に遷移
    jne     matched

    # 変数 b 領域の格納値から 0 を引く
    cmpl    $0, b
    # 演算結果が非 0 であったら matched に遷移
    jne     matched

    # 変数 c 領域の格納値から 0 を引く
    cmpl    $0, c
    # 演算結果が非 0 であったら matched に遷移
    jne     matched

    # a || b || c が成立しないので notmatched に遷移
    jmp     notmatched

matched:
    # a || b || c が成立したので,"x = 1" を実施
    movl    $1, x

notmatched:
    # 以下,if 文以後の処理が記述される

以上のことを踏まえた上でC言語の言語仕様を読めば

  • 論理積/論理和による結合は,常に全ての条件が確認されるわけではない
  • 論理積による結合は,成立しない条件があった時点で中断され得る
  • 論理積による結合は,成立する条件があった時点で中断され得る

という仕様も理解しやすいのではないでしょうか?

リスト9のようなケースの場合,コンパイラによっては,3つ目のjne matchedje notmatchedとすることで,matched直前のjmp notmatchedを不要にするような最適化を行うかもしれません。

著者プロフィール

藤原克則(ふじわらかつのり)

Mercurial三昧の日々が嵩じて, いつの間にやら『入門Mercurial Linux/Windows対応』を上梓。凝り性なのが災いして,年がら年中アップアップな一介の実装屋。最近は仕事の縁が元で,OpenSolarisに入れ込む毎日。