条件分岐
分岐命令は、実行制御を別のメモリアドレスに移します。
分岐を実行するためアセンブリではジャンプ命令がよく利用されます。
ジャンプには、無条件ジャンプと条件付きジャンプの2つがあります。
無条件ジャンプ
無条件ジャンプでは常にジャンプを行います。
JMP命令で示し、異なるメモリアドレスでコードを実行するようにCPUに指示します。
Cのgoto文に似ています。
JMP <jump address> ;ジャンプ先アドレスに実行制御が移動し、そこから
実行が開始されます。
条件付きジャンプ
条件付きジャンプでは、一定の条件に基づき指定されたメモリアドレスに処理が移動します。ジャンプを利用するには、フラグを変更できる命令が必要です。
その命令は算術演算やシフト演算で実行することができます。
x86では、ディスティネーションからソースを引き算し、ディスティネーションに結果を格納すること無くフラグを変更するCMP命令が提供されています。
cmp eax, 5 ;EAXから5を引き算する。結果がゼロになるためゼロ
フラグを設定するが、結果は格納されない。
もう一つの結果を格納せずにフラグを変更する命令は、TEST命令です。
TEST命令は、ビットごとにAND命令を実行し、フラグを設定します。
eax=0とする。
test eax, eax ;EAXがゼロであるため、ゼロフラグが設定される。
しかし、結果は格納されない。
通常、CMP命令とTEST命令は条件付きジャンプ命令と一緒に格納される。
条件付きジャンプには何種類かある。しかし、一般的な形は変わらない。
jcc <address>
上のccの部分は、条件を示します。
この表は覚える必要はないので眺める感じで見てみてください。
命令 | ジャンプ条件 | フラグ |
ja |
より上 | cf=0 & zf=0 |
jb | より下 | cf=1 |
jc | キャリーがある | cf=1 |
je | 等しい | zf=1 |
jge | より大きいか等しい | sd=of |
jle | より小さいか等しい | zf=1 | sf ! of |
jnae | より上でなく等しい | cf=1 |
jnbe | より下でなく等しい | cf=0 & zf=0 |
jne | 等しくない | zf=0 |
jnge | より大きくなく等しくない | sf ! of |
jnle | よる小さくなく等しくない | zf=0 & sf=of |
jnp | パリティがない | pf=1 |
jpo | パリティが基数 |
pf=0 |
jz | ゼロである | zf=1 |
jae | より上か等しくない | cf=0 |
jbe | より下か等しくない | cf=1 | zf=1 |
jcxz | CXレジスタが0 | |
jg | より大きい | zf=0 & sf=of |
jl | より小さい | sf ! of |
jna | より上でない | cf=1 | zf=1 |
jnb | より下でない | cf=0 |
jnc | キャリーがない | cf=0 |
jng | より大きくない | zf=1 | sf ! of |
jnl | より小さくない | sf=of |
jno | オーバーフローがない | of=0 |
jns | 符号がない | sf=0 |
jo | オーバーフローがある | pf=1 |
jpe |
パリティが偶数 |
pf=1 |
js | 符号がある | sf=1 |
if文
アセンブリにおいて、条件を確かめるプログラムの役割を担うのは上で書いたとおり、
条件付きジャンプで行います。
C言語との対応で見てみましょう。
if(x==0){
x=5;
}
x=2;
これをアセンブリで表そうとしたときに、(x==0)をどのように表せばいいか戸惑いますよね。しかし、ここは条件付きジャンプ命令をつかいます。
ここで(x==0)が表しているのは、xが0と等しいかということですよね。つまり、ゼロフラグzfが0であれば、x=5を。そうでない場合は、x=2とすればよいのです。
cmp dword ptr [x], 0
jne end_if
mov dword ptr [x], 5
end_if
mov dword ptr [x], 2
アセンブリでは、JNE命令(等しくない場合ジャンプ・等しければ処理を続ける)が利用されていることに注意してください。
ちょっとわかりにくくなってきましたよね。
しかし全部読むと割と分かってくるので、もう少しお付き合いください。
If-else文
C言語との対応で見ていくとわかりやすいので先程と同じやり方でいきます。
if(x==0){
x=5;
}
else{
x=2;
}
アセンブラで表すと、
cmp dword ptr [x],0
jne else
mv dword ptr [x],5
jmp end
else:
mov dword ptr [x],2
end:
どうですか。なんとなく分かってきましたよね。
cmpでフラグを立てて、異なる場合はジャンプする。
else文だったら、else部にジャンプする。
そして、そこでの処理を書く。
言葉で説明するよりコード見たほうが断然わかりやすいですよね笑
if-elseif-else文
C言語のコード
if(x==0){
x=5;
}
else if(x==1){
x=6;
}
else{
x=7;
}
これをアセンブリで表すと、
cmp dword ptr [x], 0
jne else_if
mov dword ptr [x], 5
jump short end
else_if:
cmp dword ptr [x], 1
jne else
mov dword ptr [x], 6
jump short end
else:
mov dword ptr [x], 7
end:
アセンブリのif文全般で気をつけないといけないこととしては、それぞれの処理の最後につくjump short end とかend:を書くことですかね。あと、判断(x==0)とかが高級言語とは反対なのもいやらしいです。
今回は、ここで終わりにします。
わかんないなってところは何回も見直すとなんとなくわかります。
最初はなんとなくでいいんです。ぼやっとでもわかれば。
自分も書いてるうちに分かってきたことも結構あります。
では、お疲れ様でした。
次回はwhile文についてやりたいと思います。