3

最終的に SVC 呼び出しで実装される一連の関数があります。例えば:

void func(int arg) {
    asm volatile ("svc #123");
}

ご想像のとおり、SVC はおそらくレジスターにある「arg」で動作します。「noinline」属性を明示的に定義に追加すると、すべてが期待どおりに機能します。

しかし、関数がより高い最適化レベルでインライン展開された場合、'arg' をレジスタにロードするコードは省略されます。

「arg」自体の宣言に「used」属性を追加しようとしましたが、この場合、gcc は明らかに警告を生成します。

また、次のような「ダミー」の asm ステートメントを追加してみました

asm ("" : "=r"(arg));

しかし、これは一般的に機能しているようには見えませんでした。(ここでも揮発性と言う必要があるかもしれません???)

いずれにせよ、基本的に本体が 1 つの asm ステートメントで構成されるルーチンに対して、明示的な関数呼び出しがあるのは残念です。

4

2 に答える 2

4

関連するレシピは、GCC マニュアルのC 式オペランドを使用したアセンブラー命令のセクションにsysintあり、命令と同じ役割で使用されますsvc。アイデアは、指定されたレジスタを使用してローカル レジスタ変数を定義し、拡張asm構文を使用して入力と出力をインライン アセンブリ ブロックに追加することです。

次のコードをコンパイルしようとしました。

#include <stdint.h>

__attribute__((always_inline))
uint32_t func(uint32_t arg) {
    register uint32_t r0 asm("r0") = arg;
    register uint32_t result asm("r0");
    asm volatile ("svc #123":"=r" (result) : "0" (r0));
    return result;
}

uint32_t foo(void) {
    return func(2);
}

これは、コンパイルされた (-O2 フラグを使用) オブジェクト ファイルの逆アセンブリです。

00000000 <func>:
   0:   ef00007b        svc     0x0000007b
   4:   e12fff1e        bx      lr

00000008 <foo>:
   8:   e3a00002        mov     r0, #2
   c:   ef00007b        svc     0x0000007b
  10:   e12fff1e        bx      lr

funcインラインで展開され、引数がr0正しく配置されます。volatileサービス呼び出しの戻り値を使用しない場合、コンパイラはコードのアセンブリ部分が不要であると想定する可能性があるため、必要だと思います。

于 2012-11-14T19:18:25.827 に答える
1

単一の asm ブロックが必要です。特に指定がない限り、コンパイラは 2 つの asm ブロックを個別に自由に処理できます。つまり、2 番目の asm ブロックに設定された要件は、最初の asm ブロックには影響しません。

呼び出し規約のために、レジスタが適切な場所にあると想定しています。

このようなものはどうですか?(テストしていません)

void func(int arg) {
    asm volatile (
        "mov r0, %[code]\n\t"
        "svc #123"
        :
        : [code]"r" (code)
    );
}

詳細については、ARM GCC Inline Assembler Cookbookを参照してください。

于 2012-11-12T08:41:38.350 に答える