Linuxでx86アセンブラ（条件分岐編）

# \:large_blue_diamond:この記事について
Linuxでx86アセンブラ、第8回目．今回はアセンブラでの条件分岐について書いていきます．条件分岐とは条件にしたがって行う処理を切り替えることです．Cなどの高級言語では、```if```、```switch```などで行っています．アセンブラでの条件分岐はCなどの条件分岐と比べて少し複雑です．なぜなら、条件判定と分岐が分かれているからです．
どのように条件分岐をしているかというと、まず```cmp```、```test```などのニーモニックで分岐するかを始めに判定しステータスフラグをセットします．ステータスフラグは計算結果の状態を真または偽で保持する特殊なレジスタです．そのステータスフラグに基づいてジャンプ（指定された命令の位置へ移動すること．）するかどうかを判定しジャンプします．
それでは、ステータスフラグ、ジャンプ、分岐判定の順に説明していきます．

# \:large_blue_diamond:ステータスフラグ
主なステータスフラグにはSF、ZF、CF、AF、PFがあります．
SF(Sign Flag)は計算結果が正の時1、負の時は0になります．
ZF(Zero Flag)は計算結果が0の時1、負の時は0になります．
OF(Overflow Flag)は符号あり整数の桁溢れが発生した際に真になります．
CF(Carry Flag)は符号なし整数の桁溢れが生じた際に1になります．
AF(Auxiliary Flag)は上位の4ビットと下位4ビットの間で桁上げか桁下げが起きた時に1になります．
PF(Parity Flag)は1であるビット数が偶数の時に1になります．

# \:large_blue_diamond:ジャンプ
ジャンプとは今いる命令のアドレスから、指定されたアドレスの命令のアドレスに移動することです．
無条件でジャンプするには```jmp```ニーモニックを使います．

```
jmp <命令のアドレス or ラベル>
```

条件付きのジャンプには```jz```、```jc```、```jo```、```js```、```jp```があります．

* ゼロでジャンプ
```jz```はjump if zeroで、ZFが1の時ジャンプします．対になる命令で```jnz```があります．こちらはZFが0の時ジャンプします．

* キャリー発生でジャンプ
```jc```はjump if carryで、CFが1の時ジャンプします．```jz```と同様に```jnc```があり、こちらはCFが0の時ジャンプします．


* オーバフローでジャンプ
```jo```はjump if overflowでOFが1の時ジャンプします．これも、```jno```があります．

* 負の計算結果でジャンプ
```js```はjump if negative signの略でSFが1の時ジャンプします．
正の時にジャンプしたい場合は```jns```を使います．


# \:large_blue_diamond:条件判定
```cmp```、```test``` ニーモニックはオペランドを比較してフラグをセットします．  

* 整数値の比較  
整数値の比較には```cmp```ニーモニックを使います．

```
cmp <レジスタ・メモリ>, <レジスタ・メモリ・即値>
```

```cmp``` は第一オペランドと第二オペランドの引き算を実行します．
その結果に基づきフラグをセットします．計算結果の値は破棄され、どのレジスタメモリにも保存されません．なので、オペランドの値はこの命令によって変更を受けることはありません．

* ビット列の比較
ビット列の比較には```test``` ニーモニックを使用します．

```
test <レジスタ・メモリ>, <レジスタ・メモリ・即値>
```

```test```は２つのオペランドのAND計算を実行し、計算結果に基づきフラグをセットします．```cmp``` の時と同様に計算結果は破棄され、オペランドのレジスタ・メモリは変更を受けません．

# \:large_blue_diamond:デモコード
この記事で扱った命令の使い方を説明するデモコードです．

``` control_flow.asm
section .data

section .bss

section .text

global main

main:
   enter 0,0
   nop

   jmp .compare

.equal:
    mov ebx, 5
    cmp ebx, 8
    jns .greater
    cmp ebx, 7
    jns .greater
    cmp ebx, 6
    jns .greater
    cmp ebx, 5
    jns .greater
    cmp ebx, 4
    jns .greater

.final:
    mov eax, 0
    leave
    ret

.greater:
    xor eax, eax
    xor ebx, ebx
    jmp .final

.compare:
    mov eax, 3
    cmp eax, 2
    jz .equal
    cmp eax, 5
    jz .equal
    cmp eax, 3
    jz .equal

```
コンパイルしてgdb上で実行してみてください．
gdbでフラグの状態を表示するには```display $ps``` コマンドを利用してください．

# 参考文献
* NASM development team site:   
http://www.nasm.us/
* GDB: The GNU Project Debugger site:   
https://www.gnu.org/software/gdb/
* Assembly Language Step-by-Step: Programming with Linux:   
http://www.amazon.co.jp/Assembly-Language-Step---Step-Programming/dp/0470497025/ref=sr_1_1?ie=UTF8&qid=1446704607&sr=8-1&keywords=assembly+language+step+by+step
* Stack Analysis with GDB:    
http://resources.infosecinstitute.com/stack-analysis-with-gdb/

↓↓\:bowtie:過去の投稿もよろしくね\:bowtie:↓↓

* Linuxでx86アセンブラ（マクロ編） 
http://qiita.com/MoriokaReimen/items/45abbb6c2938abd505ff

* Linuxでx86アセンブラ（スタック編）
http://qiita.com/MoriokaReimen/items/31a8f8ce4a46ba0f3590

* Linuxでx86アセンブラ（基本的なコードの構造編）
http://qiita.com/MoriokaReimen/items/b320e6cc82c8873a602f

* Linuxでx86アセンブラ（論理演算編） 
http://qiita.com/MoriokaReimen/items/bf863585616ad0a0a969

* Linuxでx86アセンブラ(四則演算編)
http://qiita.com/MoriokaReimen/items/4853587dcb9eb96fab62

* Linuxでx86アセンブラ(Cとの連携編)
http://qiita.com/MoriokaReimen/items/590a4ddb3de15bfacb4b

* Linuxでx86アセンブラ(道具編)
http://qiita.com/MoriokaReimen/items/b316a68d76c1eafa18f8

* tmuxの使い方
http://qiita.com/MoriokaReimen/items/d7d5b158cb412dd65a60



↓↓\:bowtie:コメントをいただけたら励みになります\:bowtie:↓↓