ARMインラインアセンブラ

IAR EWARMで動作確認。GCCインラインアセンブラ構文を採用しており、他でもだいたい同じっぽい。VC++でのx86のインラインアセンブラに比べるとちょっとC言語の変数にアクセスする記法が分かりにくいかも。

基本

VC++と同様に__asmキーワードを用いてインラインアセンブラのコードを書くことができる。ただし、記法は少し異なる。(括弧とか引用符とかセミコロンとか)

    __asm ("add r0, r1, r2");

volatile

volatile修飾子をつけると、コンパイラに最適化されずに書いた通りのコードになる。

    __asm volatile ("add r0, r1, r2");

C言語の変数へのアクセス

VC++では何気なく記述することができたが、GCCインラインアセンブラ構文の場合は出力リスト、入力リストで明示しなければならない。

__asm volatile(
    "add %[result], %[input1], %[input2]"
    : [result] "=r" (c)                   // 出力リスト
    : [input1] "r" (a), [input2] "r" (b)  // 入力リスト
    : // 破壊レジスタリスト
);

上の例で、

  • %[result], %[input1], %[input2] はテンプレート。その下の出力リスト、入力リストでC言語の変数が指定される。
  • 出力リスト、入力リストは、[シンボル名] "制約子" (C言語変数名) の形式で、コンマ区切り。
  • シンボル名は適当な名前を自由に付ける。
  • シンボル名を省略した場合は、%1,%2,%3...のようになる。
  • 制約子はアクセスの制約を指定する。
  • 制約子の"="は書き込み専用を示す。"+"なら読み書き両用。
  • 制約子の"r"は汎用レジスタを示す。
  • 破壊レジスタリストは、破壊してしまうレジスタ名を列挙する。
  • 破壊レジスタリストは、: "r0", "r1" のように、""囲み、コンマ区切りで書く。
  • 破壊レジスタリストで、”cc”は条件レジスタの破壊を示す。
  • 破壊レジスタリストで、”memory”は未知のメモリの破壊を示す。

足し算のコード

x86インラインアセンブラ - 滴了庵日録の記事で書いたサンプルと同等の内容のコード。

#include<stdio.h>

int main(void)
{
    int a, b, c;
    a = 10;
    b = 20;
    
    // c = a + b
    __asm volatile(
        "add %[result], %[input1], %[input2]"
        : [result] "=r" (c)
        : [input1] "r" (a), [input2] "r" (b)
    );
    
    printf("c = %d\n", c);
    
    while(1){;}
    
    return 0;
}