この記事について
Linuxでx86アセンブラ、第8回目.今回はアセンブラでの条件分岐について書いていきます.条件分岐とは条件にしたがって行う処理を切り替えることです.Cなどの高級言語では、if
、switch
などで行っています.アセンブラでの条件分岐はCなどの条件分岐と比べて少し複雑です.なぜなら、条件判定と分岐が分かれているからです.
どのように条件分岐をしているかというと、まずcmp
、test
などのニーモニックで分岐するかを始めに判定しステータスフラグをセットします.ステータスフラグは計算結果の状態を真または偽で保持する特殊なレジスタです.そのステータスフラグに基づいてジャンプ(指定された命令の位置へ移動すること.)するかどうかを判定しジャンプします.
それでは、ステータスフラグ、ジャンプ、分岐判定の順に説明していきます.
ステータスフラグ
主なステータスフラグには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になります.
ジャンプ
ジャンプとは今いる命令のアドレスから、指定されたアドレスの命令のアドレスに移動することです.
無条件でジャンプするには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
を使います.
条件判定
cmp
、test
ニーモニックはオペランドを比較してフラグをセットします.
- 整数値の比較
整数値の比較にはcmp
ニーモニックを使います.
cmp <レジスタ・メモリ>, <レジスタ・メモリ・即値>
cmp
は第一オペランドと第二オペランドの引き算を実行します.
その結果に基づきフラグをセットします.計算結果の値は破棄され、どのレジスタメモリにも保存されません.なので、オペランドの値はこの命令によって変更を受けることはありません.
- ビット列の比較
ビット列の比較には
test
ニーモニックを使用します.
test <レジスタ・メモリ>, <レジスタ・メモリ・即値>
test
は2つのオペランドのAND計算を実行し、計算結果に基づきフラグをセットします.cmp
の時と同様に計算結果は破棄され、オペランドのレジスタ・メモリは変更を受けません.
デモコード
この記事で扱った命令の使い方を説明するデモコードです.
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/
↓↓過去の投稿もよろしくね↓↓
Linuxでx86アセンブラ(マクロ編)
http://qiita.com/MoriokaReimen/items/45abbb6c2938abd505ffLinuxでx86アセンブラ(スタック編)
http://qiita.com/MoriokaReimen/items/31a8f8ce4a46ba0f3590Linuxでx86アセンブラ(基本的なコードの構造編)
http://qiita.com/MoriokaReimen/items/b320e6cc82c8873a602fLinuxでx86アセンブラ(論理演算編)
http://qiita.com/MoriokaReimen/items/bf863585616ad0a0a969Linuxでx86アセンブラ(四則演算編)
http://qiita.com/MoriokaReimen/items/4853587dcb9eb96fab62Linuxでx86アセンブラ(Cとの連携編)
http://qiita.com/MoriokaReimen/items/590a4ddb3de15bfacb4bLinuxでx86アセンブラ(道具編)
http://qiita.com/MoriokaReimen/items/b316a68d76c1eafa18f8tmuxの使い方
http://qiita.com/MoriokaReimen/items/d7d5b158cb412dd65a60
↓↓コメントをいただけたら励みになります↓↓