第10回
制御構造と変数(6)~if、for、whileをアセンブリ言語で

値を調べ処理を切り替える

アセンブリ言語には、値を調べる命令と調べた結果によって次の処理を切り替える命令が備わっています。これらを使って、ifをアセンブリ言語で書いてみましょう。

CMP命令とジャンプ命令

まず、CMPという2つの値を比較するニモニックの働きを理解しましょう。CMPはcompare(比べる)の略で2つのオペランドを採り、それらを比較します。書式は以下のようになります。
CMP <op1>, <op2>
比較した結果はフラグレジスタというCPU内部のメモリに反映されます。フラグレジスタはビット単位で機能し、計算結果が0ならZF(ゼロフラグ)がON(1)、桁上がりが生じたらCF(キャリーフラグ)がON(1)……という具合に状態が変化します。

フラグレジスタの状態は表2に示すジャンプ系のニモニックによって取得でき、その状態によって指定した行へと移動(ジャンプ)します。

ラベルは識別名の後ろに:記号を付けた識別子で、移動先の目印として機能します。

表2:x86系CPUで用いられるジャンプ系ニモニック
ニモニック 書式 機能 備考
JMP JMP <ラベル> 無条件に<ラベル>で示す行へ移動  
JA JA <ラベル> (A > B)のとき<ラベル>で示す行へ移動 調べる値を符号付きと見なす場合はJGを使う
JAE JAE <ラベル> (A >= B)のとき<ラベル>で示す行へ移動 調べる値を符号付きと見なす場合はJGEを使う
JB JB <ラベル> (A < B)のとき<ラベル>で示す行へ移動 調べる値を符号付きと見なす場合はJLを使う
JBE JBE <ラベル> (A <= B)のとき<ラベル>で示す行へ移動 調べる値を符号付きと見なす場合はJLEを使う
JNZ JNZ <ラベル> (A != B)のとき<ラベル>で示す行へ移動  
JNE JNE <ラベル> (A != B)のとき<ラベル>で示す行へ移動 JNZとJNEのマシンコードは同じ
JZ JZ <ラベル> (A == B)のとき<ラベル>で示す行へ移動  
JE JE <ラベル> (A == B)のとき<ラベル>で示す行へ移動 JZとJEのマシンコードは同じ
LOOP LOOP <ラベル> CXレジスタの値が0のとき<ラベル>に移動 CXレジスタをカウンタとして使う

『等しい』と『ゼロ』は同じ?!

なお、JEとJZはまったく同じ命令で、機械語となった場合も同じコードです。これは、AとBとが同じである(E:Equal)ということが、AからBを減算した結果が0であること(A - B = 0)と本質的に同じ意味であることに依っています。

実際にCMP命令は、2つのオペランドを減算した結果が0なら(ZFがONなら)2つの値が等しい、そうでなければ(ZFがOFFなら)等しくない──という処理を行っています。

同様に、JNE(等しくなければジャンプ)とJNZ(ゼロでなければジャンプ)も同じマシンコードとなります。

ifをアセンブリ言語で書く

AXレジスタの値と定数の100を比較して、AXレジスタに保存された値の方が大きければ(AX > 100)ラベル“GREAT”へ、そうでなければ(AX <= 100)ラベル“LESS”へ移動する処理は、リスト1のように記述できます。図1も参考にしてください。

これでもう、ある程度理解できたのではないかと思います。リスト1はCのifに相当する構造です。Cで書けばリスト2のようになります。

リスト1:AXレジスタの値によって処理を切り替えるアセンブリ言語のソース
CMP AX, 100
JG  GREAT
JMP LESS
GREAT:
  : ---- (AX > 100 だったときの処理)
JMP EXIT
LESS:
  : ---- (AX <= 100 だったときの処理)
EXIT:
  :

リスト2:リスト1と同じ動作をするifを使ったCのソース
	if (A > 100) {
	      : ---- (A > 100 だったときの処理)
	} else {
	      : ---- (A <= 100 だったときの処理)
	}