Capture The Frog

かえるぴょこぴょこw

MENU

アセンブリ言語入門 その4

アセンブリ言語入門も4回目になりました。7回くらいでこのシリーズはおしまいかな。

というより、マルウェア解析のアセンブリ編をやるためにこのシリーズ始めたんだった。。やることは山積みだー。でも楽しいし、この長い夏休みにできて良かった。

では、さっそくやっていきましょー

 

条件分岐

 分岐命令は、実行制御を別のメモリアドレスに移します。

分岐を実行するためアセンブリではジャンプ命令がよく利用されます。

ジャンプには、無条件ジャンプと条件付きジャンプの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)とかが高級言語とは反対なのもいやらしいですね笑。でもコツさえつかめばなんとかなりそうです。

ああー。高級言語が恋しい。

 

 

今回は、ここで終わりにします。

いやー、if文結構クセありましたね。フラグとか最初に聞いたときは,は?なんじゃそりゃ?って思いました。ジャンプとかもね。

わかんないなってところは何回も見直すとなんとなくわかりますよ。

最初はなんとなくでいいんです。ぼやっとでもわかれば。

自分も書いてるうちに分かってきたことも結構あります。

では、お疲れ様でした。

次回は、for文についてやりたいと思います。