強火で進め

このブログではプログラム関連の記事を中心に書いてます。

iPhoneでインラインアセンブラを使う(プログラム編[2] 四則演算)

2回目のプログラム編です。今回は四則演算を中心に解説します。

加算

まずは加算、足し算の処理です。プログラムはこの様になります。
前回の解説を参考に applicationDidFinishLaunching: などに記述して下さい。

    int val1 = 5;
    NSLog(@"%d", val1);
    __asm__ volatile (
                      "add        %0, %0, #10 \n\t"
                      : "+r" (val1) 
                      : 
                      );
    NSLog(@"%d", val1);

ARMアーキテクチャリファレンスマニュアル」で確認しながらこの記事を読んでる方は

ADD %0, #10

となるのでは?と思う方もいるかもしれませんがこちらはThumb命令の時のルールとなります。
ARM命令での記述方法は該当の命令の最後の「等価なARM構文とエンコード」の項目を確認することになります。

読み進めると記述方法は

ADD , ,

とあるためこの様な記述となります。

また、少し戻った「動作」の項目を見ると

Rd = Rd + Rm

とあります。そのため今回の命令についても徐々にC言語に切り替えて行くと実際に行われる処理はこのような感じになります。

add %0, %0, #10

これが実際の変数を割り当てるとこうなり

add val1, val1, #10

C言語になるとこうなります。

val1 = val1 + 10

後、今回はデータの特性を指定する部分が前回の "=r" と異なり "+r" になってます。
前回は「出力オペランド」でのみであるので = 、つまり「書き込み専用」の指定をしました。

今回はC言語での記述で見たときに分かる様に「val1 = val1 + 10」と val1 が式の右側、つまり「入力オペランド」にも存在するため「読み書き可能」という設定を行う必要があります。

前回も参照した以下のサイトで確認したところインラインアセンブラではサポートしてないと記述されてますが他の方が書かれたインラインアセンブラでは使用されており、少なくとも現在のgccでは問題なく使えるようです。

ARM GCC Inline Assembler Cookbook
http://www.ethernut.de/en/documents/arm-inline-asm.html

命令記述の大文字、小文字について

ちなみにドキュメントについては add は ADD などと大文字で書いてありますが今までのサンプルではすべて小文字で書いてきました。もちろん大文字、小文字どちらで記述しても同様に動作するので問題ありません。

昔からアセンブラをやってる人は大文字で記述してる人が多いらしいのですがC言語世代の人はCの影響からか小文字で書く人が多いと聞いたことがあります。自分も取りあえずインラインアセンブラは小文字派です。

加算(両方のパラメータにC側の変数を使う)

先ほどは加算のパラメータの一つを即値(数値)にしましたがこちらもCで定義した変数する場合は以下の様に記述します。

    int val1 = 5;
    int val2 = 10;
    NSLog(@"%d %d", val1, val2);
    __asm__ volatile (
                      "add        %0, %0, %1 \n\t"
                      : "+r" (val1) 
                      : "r" (val2) 
                      );
    NSLog(@"%d %d", val1, val2);

この記述をCで表すと

add %0, %0, %1

この様になります。

val1 = val1 + val2

前回解説した様にアセンブリの記述部分である "" のブロックが終わった後の部分は

:(出力オペランドに対応するデータ)
:(入力オペランドに対応するデータ)

となっています。今回、val1は入力オペランドと出力オペランドの両方で使用されるので「出力オペランドに対応するデータ」の方に記述していますが「入力オペランドに対応するデータ」は本来は2つ目の : の後に記述する事になります。そのため val2 についてはその位置に記述してあります。また「書き込み専用」では無いのでデータの特性は =r ではなく r を指定しています。

減算

減算は sub を使い、以下の様に記述します。

    int val1 = 5;
    int val2 = 10;
    NSLog(@"%d %d", val1, val2);
    __asm__ volatile (
                      "sub        %0, %0, %1 \n\t"
                      : "+r" (val1) 
                      : "r" (val2) 
                      );
    NSLog(@"%d %d", val1, val2);

Cで表すとこうなります。

val1 = val1 - val2

乗算

乗算は mul を使い、以下の様に記述します。

    int val1 = 5;
    int val2 = 10;
    NSLog(@"%d %d", val1, val2);
    __asm__ volatile (
                      "mul        %0, %0, %1 \n\t"
                      : "+r" (val1) 
                      : "r" (val2) 
                      );
    NSLog(@"%d %d", val1, val2);

Cで表すとこうなります。

val1 = val1 * val2

除算

ARMには除算の命令は有りません。
※正確には整数に対する除算は有りません。

まとめ

以上が四則演算の命令となります。なお今回解説した命令は全て、整数(int)のデータの加減乗除についての命令となります。浮動小数点であるfloatやdouble型のデータについては FADDS や FADDD などの別の命令が必要になります。また除算の命令も存在します。

iPhoneインラインアセンブラを使うの記事一覧はこちら