日本語訳版はこちら

Application Note
アトメル AT1886: AVRGCC上でアセンブリ言語とC言語の混在
8-bit Atmel Microcontrollers
概要
Atmel Studio 6上でのCおよびアセンブリのソースを簡単に混在させる
•
• Cはアセンブリルーチンをコール
• アセンブリはCをコール
•
Cとアセンブリの間で変数とポインターの受け渡し
•
グローバル変数としてCおよびアセンブリが共有
はじめに
このアプリケーションノートではStudio6 の統合化環境(IDE)を用いてAVRGCCプロジ
ェクトにCとアセンブリコードの両方を混在させる方法を述べます。このアプリケーション
ノートは以下の観点で書かれています。Cはここで選ばれた言語であり、アセンブリ言語で
無いとプログラムが困難であるか、使うことでより便利である状況を含んでいます。
Studio6(およびこれ以前のバージョン)は同じプロジェクト上にアセンブリ言語およびC
ファイルの両方を操作させることを可能にしています。問題はソフトウェアエンジニアがど
のようにアセンブリコードとCコードを一つまとめるかにあります。アセンブリコードとC
コードの間でパラメータ、変数を同じようにパスするにはどのように行うのかを示します。
1
42055B-AVR-11/2012 (日本語版MCMジャパン訳)
目次
1. 必要条件
2. プロジェクトの構成
3. ファンクション可視性
4. 変数
5. レジスターの使用法
6. パラメータ受け渡し
7. ビルド方法とデモプログラムの走らせ方
8. 要求されるハードウェア
9. ハードウェアセットアップ
10. 手続き
11. リファレンス
12. 履歴
Atmel AT1886: Mixing Assembly and C with AVRGCC [APPLICATION NOTE]
42055B-AVR-11/2012 (MCM ジャパン訳)
2
1. 必要条件
このノートを読む上において能力と技術力において以下の基本に精通している必要があります。11章に示したリ
ファレンスでより深く学んでください。
•
Atmel Studio 6
•
Atmel debagger JTAGICE mkII または JTAGICE 3
•
Atemel STK600 Starter Kit
2. プロジェクトの構成
プロジェクトを構成するために特別な要求はありません。ファイルはCコードまたはアセンブリコードにあるヘ
ッダーファイルで特定され、プロジェクトのヘッダーファイルフォルダーに置かれます。ソースとして特定される
ファイルはプロジェクトのソースファイルフォルダーへ置かれます。
厳格に要求される訳ではないのですが、すべてのアセンブリ言語ソースファイルは、 .S 拡張子を持たなくては
なりません。このことによりまずC言語コンパイラーは自動的にアセンブラーと必要なリンカーを呼び出すこと
ができます。さらに、Cプリプロセッサーはユーザーのシンボリックコンスタントを自動的に呼び出します。
ソースファイルの一つは、リンカーがアプリケーションのどこからスタートするかを知るようにする、 main モ
ジュールを生成する必要があります。Cコードで最もよく使われるのは、 main と呼ばれるファンクションで
す。しかし main と名前が付けられ、グローバル宣言( global ディレクティブを用いる)されたアセンブリフ
ァイルのサブルーチンも main と名付けられたモジュールを生成します。
Cとアセンブリが組み合わされた一つのプロジェクトではアプリケーションの要求に依存する幾つかの疑問が浮
かび上がります。次のような疑問かもしれません:
•
Cファンクションがアセンブリルーチンをコールすることができるように、Cコンパイラーはどのように
してアセンブリルーチンを参照することができるのですか?
•
同様にアセンブリルーチンがCファンクションをコールすることができるように、Cファンクションが
どのようにしてアセンブリルーチンを参照することができるのですか?
•
どのように変数はアセンブリに渡されるのですか?
•
どのように変数はCファンクションに渡されるのですか?
•
アセンブリコードおよびCは同じグローバル変数として使えるのですか
3. ファンクションの可視性
C言語ファンクションはアセンブラーから参照されるためにはでexternalとして宣言される必要があります:
.extern my_c_function
アセンブリ言語ルーチンはCコンパイラーから参照できるようにするためにアセンブリコードの中でグローバル
宣言される必要があります。これは global ディレクティブを使うことでなされます:
.global my_assembly_fct
加えて、アセンブリ言語ルーチンが呼び出されるためのCファイルはアセンブリ言語ルーチンがexternalである
とするファンクションプロトタイプ宣言が必要です:
.extern unsigned char my_assmbly_fct (unsigned char, unsigned int);
Atmel AT1886: Mixing Assembly and C with AVRGCC [APPLICATION NOTE]
42055B-AVR-11/2012 (MCM ジャパン訳)
3
4. 変数
Cコードおよびアセンブリコードのいずれもが変数に自由にアクセスすることができます。実際の事実としてCコ
ードはアセンブリコードへ値ごとあるいはリファレンスごとに変数とパスパラメータを管理させることを薦めま
す。5章のレジスターの使用法、と6章パラメーター受け渡しでC言語でいかにレジスターセットが使われるか、
いかにパラメーターが受け渡されているかを述べます。
アセンブリおよびCの両方で同じグローバル変数をアクセスすることができます。そのような変数はCコード中で
global変数、アセンブリコード中でexternal として宣言される必要があります。変数 my_value がglobalとする
ことを考えます。Cコード中ではその他の変数のように、ファンクションの外で宣言されています。
unsigned char my_value;
アセンブリの中では次のようにコード化されます:
.extern my_value
5. レジスターの使用法
アセンブリ言語ルーチンをCコードと混合して書くにはいかにコンパイラーがレジスターを使っているかの知識
が要求されます:
• r0はテンポラリレジスタであり、コンパイラーが生成したコードによって使われる。もしこのレジスターを
使いCファンクションをコールしたアセンブリコードを書いたならコンパイラーがそれを使うかも知れない
から、このレジスターをセーブしリストアする必要があることになります。
• r1はコンパイラーにより常に0となっています。アセンブリコードでこのレジスターを使うならリターンす
る前にあるいはコンパイラーをコード生成するために呼ぶ前にレジスターをクリアしておかなくてはなりま
せん。
• r2-r17、r28、r29はCファンクションでは変更しないでおく call-saved レジスターです。Cで呼び出され
たアセンブリ言語ルーチンがこれらのレジスターを使った場合、レジスターの内容をセーブおよびリストア
する必要があります。
• r18-r27、r30、r31はどのコードでも使えるレジスターで、 call-used レジスターです。Cファンクション
をコールしたアセンブリコードはアセンブリコードで使用したこれらのレジスターをセーブする必要があり
ます。なぜならコンパイラーが生成したコードはセーブされていないからです。
Table 5-1 Cとアセンブリの間でのレジスターインターフェースサマリー
レジスタ­
説明
Cから呼ばれるアセンブリコード
Cコードを呼ぶアセンブリコード
r0
一時的
使われるときセーブおよびリストア
使われるときセーブおよびリストア
r1
いつでもゼロ
リターンする前にクリア
リターンする前にクリア
call-saved
使われるときセーブおよびリストア
自由に使用
call-used
自由に使用
使われるときセーブおよびリストア
r2-r17
r28
r29
r8-r27
r30
r31
Atmel AT1886: Mixing Assembly and C with AVRGCC [APPLICATION NOTE]
42055B-AVR-11/2012 (MCM ジャパン訳)
4
6. パラメータ受け渡し
固定された引数リストの引数は、(オペランドの)左から右へ、r8 からレジスターr25 (で番号の大きい方の
レジスターから順に)に割り当てられます。全引数はレジスターの偶数番が使われます。このことはキャラクタ
ー引数は2つのレジスターが使われることになります。レジスターに入る数を超えた追加のレジスターはスタッ
クに渡されます。
変数の引数リストの引数は右から左の順にスタックへプッシュされます。キャラクター引数は2バイト消費され
ます。戻り値は戻り値のサイズに応じてr25からr18が使用されます。レジスターとバイトの順の間の関係は表
6-1に示されます。
Table 6-1 レジスターとバイトの順序の関係
レジスター
バイトの順序
r19
r18
r21
r20
r23
r22
r25
r24
b7
b6
b5
b4
b3
b2
b1
b0
7. ビルド方法とデモプログラムの走らせ方
デモコードはC言語の中からアセンブリ語ルーチンを呼び出し、2つの言語の間でパラメータをパスすることを
説明する単純なファンクションを含んでいます。加えて、アセンブリ語には割り込みサービスルーチンが含まれ
ています。
コードはクロックのプリスケーラを新しいプリスケーラルーチンの値へ変更するアセンブリ語の
chenge_clock ルーチンを呼び出すことで始まります。
その後コードは渡された2つのパラメータを加えられてセンブリ語が呼ばれ、結果が加えられてCへ戻されま
す。
そしてコードはタイマー0を初期化し、周期的割り込みを生成、さらに while ループに入りとどまります。アセ
ンブリ語の割り込みサービスルーチンは割り込み時、ポートDビット0をトグルします。
8. 要求されるハードウェア
•
ATMEL STK600 スターターキット
•
STK600-ATmega2560 カード(STK600に同梱されています。)
•
アトメルデバッガー(JTAGICE-mkII、JTAGICE 3、Atmel AVR DragonTM、etc.)
•
Atmel studio 6
•
10-pin IDC リボンケーブル(STK600に同梱)
9. ハードウェアセットアップ
STK600ボードに以下の接続を行います。
• STK600にSTK600-ATmega2560 カードを取り付けます。
• PORTDとLEDヘッダー間を10-pin リボンケーブルで接続します。
• STK600のJTAGのデバイスのデバッガーヘッダーとデバッガーのケーブルを接続します。
Atmel AT1886: Mixing Assembly and C with AVRGCC [APPLICATION NOTE]
42055B-AVR-11/2012 (MCM ジャパン訳)
5
10.
手続き
1. www.atmel.com からAT1886.zip をダウンロードします。
2. そのファイルをワーキングディレクトリへアンパックします。
3. Atmel Studio 6でAVR1886.atsln プロジェクトをオープン(ダブルクリック)します。
4. Studioのボックス(Project→AVRxxxxProject、Toolsタブから)でdebugger Toolを選択します。
5. (Deviceタブから)ターゲットデバイスとしてATmega2560を特定します。
6. プロジェクトをビルドします。
7. デバッグモードに入ります。
8. アプリケーションを走らせます。
9. ウオッチウインドウへ val_1 、 val_2 、 val_3 を加えます。
10. mainのアサインメントに val_1= 上にブレークポイントをセットします。
11. 右のProcessorタブの中で、レジスタービユーを広げます。 12. runボタンをクリックします。コードは change_clock ファンクションを実行し、ブレークされます。
13. step through the next instruction シングルステップファンクションを用いて init_tomer_0 ファンクショ
ンコールに着くまで実行します。Cからアセンブリルーチン add_two へレジスターを通してパラメーターを
ゲットすることを観測できます。 14. 一度 init_timer_0 ファンクションに到達したら、runボタンをクリックします。Cを用いてタイマーが初期
化され、タイマーからの周期的割り込みが作動されます。PD0のLEDがブリンクするのを確認できます。
11.
リファレンス
1. Atmel Studio 6 ‒ www.atmel.com
2. Atmel AVR JTAGICE mkll ‒ www.atmel.com
3. Atmel JTAGICE 3 ‒ www.atmel.com
5. Atmel STK600 - www.atmel.com
12.
履歴
注意1:訳にあたりサンプルプログラムの動作を含め注意深く携わったつもりですが、不備もあると思われます。も
しおかしな点等ございましたらアトメル社ホームページのアプリケーションノートを参照いただいた上でMCMジャ
パン(株)SED アトメルグループへご連絡ください。
注意2: 記載のロゴ、社名は各社の商標または登録商標です
Atmel AT1886: Mixing Assembly and C with AVRGCC [APPLICATION NOTE]
42055B-AVR-11/2012 (MCM ジャパン訳)
6