Renesas Synergy™

FAQ 106210 : TW32Rにおいて、アセンブラからCの関数を呼び出すにはどのようにすればよいでしょうか?

Q: 質問

TW32Rにおいて、アセンブラからCの関数を呼び出すにはどのようにすればよいでしょうか?


A: 回答

Cの関数の戻り値/引数の数/引数のデータ型に応じて、引数の一部をスタックに格納したり、レジスタの待避を行なうなどの対応が必要になる場合がありますが、TW32Rにおける基本的な関数の呼び出し手順は次の通りです。

  1. r0からr3のレジスタに、Cの関数の第一引数から順に引数をセットする。
  2. bl命令でCの関数をコールする。
  3. Cの関数からの戻り値は、r0レジスタを参照する。
    (Cの関数が戻り値を返す場合、r0にリターン値が返されます。戻り値を返さない場合、r0は不定値になります)

詳細な仕様については、以下の電子マニュアルにて確認ください。 TW32Rをインストール後に作成される、スタートメニューから参照できます。

[スタート] → [プログラム(P)] → [MITSUBISHI-TOOL] → [TW32R V.3.00 Release 1]→ [TW32R ドキュメント]

  1. M32R ABI - Application Binary Interface(英文)
    (1) Function Calling Sequence の項に仕様がまとめられています。
    (2) Coding Examples の項には、関数呼び出しのアセンブラとC言語との対比が例として記載されています。

  2. GNUツールリファレンス(和訳・参考)
    上記 1. の一部を和訳したものです。 「引数の設定規則」、「戻り値の設定規則」、「レジスタの使用規則」、「スタックフレームの構成」が関連する項目となります。

他に、実際にC言語で関数呼び出しのプログラムを作成し、-Sオプション付きでコンパイルすれば、対応するアセンブラのプログラムが得られますので、これを利用していただくという方法も有効です。

以下は、funccall.c という呼び出し側プログラムを、-S 付きでコンパイルした場合の例です。

funccall.c
extern int func(int, int, int, int);
int  result;
void call_func(void)
{
    result = func(0, 1, 2, 3);
}

DOSプロンプト上で、m32r-elf-gcc -S funccall.cを実行すると、下記のソースコード(funccall.s)が得られます。

[注意]

  • TW32R(gcc)のバージョンやオプション指定により、命令の並び方などの出力内容が若干変化する場合があります。
  • 関数呼び出しに関係のない行は省略しています。
  • 日本語のコメントは、説明用に追加したものです。

funccall.s

    .section  .text
    .balign 4
    .global   call_func
call_func:
    push  fp             ;  (1) フレームポインタfp(R13)の待避
    push  lr             ;  (2) リンクレジスタlr(R14)の待避
    mv    fp, sp         ;  (3) この関数のフレームを形成
    ldi   r0, #0  ; 0x0  ;  (4) 第1引数をR0にセット
    ldi   r1, #1  ; 0x1  ;  (5) 第2引数をR1にセット
    ldi   r2, #2  ; 0x2  ;  (6) 第3引数をR2にセット
    ldi   r3, #3  ; 0x3  ;  (7) 第4引数をR3にセット
    bl    func           ;  (8) 関数呼出し
    mv    r4, r0         ;  (9) 戻り値(r0)を 変数resultに格納
    ld24  r5, #result
    st    r4, @(r5)
    pop   lr             ; (10) リンクレジスタlr(R14)の復帰
    pop   fp             ; (11) フレームポインタfp(R13)の復帰
    jmp   lr             ; (12) この関数自身を終了
    .comm result,4,4     ; 変数resultの格納領域

上記のアセンブラ出力例において、(4)~(7)の引数の設定、(8)の分岐命令が関数呼出しの基本処理となります。(9)は、r0をリターン値として利用するための処理で、戻り値に意味がない(void型) 関数を呼び出す場合は不要です。

(2), (10)は、リンクレジスタ(R14)の待避です。M32Rファミリでサブルーチンコールに使われているbl命令は、サブルーチンから復帰するためのアドレスをスタックではなくレジスタに格納します。これはリンクレジスタと呼ばれ、R14が割り当てられています。通常、ほとんどのプログラムは、別のプログラムのサブルーチンになっています(上記プログラムも例外ではありません)。ですから、R14の値はその関数が終了 (上記の(12)) するまで保持する必要があります。(2),(10)はそのための処理です。

(1), (3),(11)は、スタックフレームを形成するための処理です。呼び出し側のプログラム内でスタックフレームを使用しないのであれば、省略できます。

 

適用製品

M32Rファミリ用クロスツールキット GNUツール版 [M3T-TW32R]
他にご質問がございましたら、リクエストを送信してください