アセンブラコードをCから呼び出す
アセンブラコードはマイコンの動作を理解するために、さけて通れない道。
さて、手持ちのfrdmk64fでどう学習すればよいのか。
インラインアセンブラというのは、どこかでチラっと読んだ気がするが、
gccによるアセンブルの結果であって、armasmによる純粋なアセンブラコード(*.s)の動作とは異なるものらしい。
それも気になるが、:[xx] "=r" (xx)の構文をそもそも避けたい事情がある。
というのも、IAR EWARMの逆アセンブル結果をみると、グローバル変数が
位置するアドレスを一時的にR0なり、R1なりに突っ込んで動作している事があって、インラインアセンブラでコーディングしているR0, R1の実装を汚染してしまう。
それなら、素直に*.sで用意したらどうだろう、と思った次第。
しかしたぶん、これ、大変だと思う。IAR EWARM以外のfrdmk64fのプログラムダウンロード以外の方法を知らないので、正しいアプローチでないかもだけど、
まずはIARのサンプルとARMのヘルプセンターの情報をもとに、strcopy的な*.sを
IAR EWARMプロジェクトに追加してみた。コードは以下。
PUBLIC strcopy
SECTION .text:CODE:ROOT(2)
//ARM
strcopy:
LDRB R2, [R1], #1
STRB R2, [R0], #1
CMP R2, #0
BNE strcopy
BX lr
END
//ARMとあるのは、Cortex-M系ではそもそもARM32ビット命令をサポートしていない?ので、アセンブラに怒られてコメントアウトしたものである。
IARのサンプルは cp15.sという cortex-A系のコプロセッサを制御するサンプルだった
ので、さもありなんとゆーことか。
ちなみに、ARMのヘルプセンターには
PRESERVE8 AREA SCopy, CODE, READONLY EXPORT strcopy strcopy ; R0 はデスティネーション文字列を指す ; R1 はソース文字列を指す LDRB R2, [R1],#1 ; バイトをロードし、アドレスを更新する STRB R2, [R0],#1 ; バイトを格納し、アドレスを更新する CMP R2, #0 ; NULL 終端文字をチェックする BNE strcopy ; NULL でない場合は続行する BX lr ; 復帰 END
のように、「Cからのアセンブリ言語の呼び出し」には書いてあったけど、そうか、これ、
ARM Compiler 4 and 5 => Version 4.1 日本語版 => ARMコンパイラツールチェーン ARMプロセッサをターゲットとしたソフトウェア開発 => C、C++、およびアセンブリ言語の混用 => Cからのアセンブリ言語の呼び出し
に乗っていた情報であり、ver4系は古いのか?
そのせいか、IARのビルドでは「Bad instruction」が出てエラーとなっていた。
いや違うな、ver5でも、上記と同じサンプルが記載されている。
IARが独自でアセンブラ ディレクティブを削除した、とゆーことか。
呼び出し側は(当然ながら)ver4だろうが、C側なんで問題なく、
extern void strcopy(char* d, const char *s);
const char *srcstr = "First sring - source ";
char dststr[] = "Second string - destination ";
strcopy(dststr, srcstr);
PRINTF(" dst = %s\n", dststr);
でフツーに動いた、やった!!
ちなみにcのグローバル変数には以下のようにアクセスできた。
PUBLIC strcopy
SECTION .text:CODE:ROOT(2)
IMPORT q_ready
//ARM
strcopy:
MOV R3, #1
LDR R0, =q_ready
STR R3, [R0, #0]
BX lr
END
さて、SECTIONについても、IARアセンブラリファレンスガイドを調べてみた。
(くそ、なんで、ARMインフォメーションセンターだけで済まないんだ)
ROOT、NOROOT ROOT(デフォルトモード)は、セクション フラグメントを破 棄してはならないことを示します。 NOROOT は、このセクション フラグメント内のシンボルが参 照されない場合、セクション フラグメントがリンカによ り破棄されることを意味します。通常、起動コードと割 込みベクタを除くすべてのセクション フラグメントで、 このフラグを設定する必要があります。
なるほど、NOROOT(2)に変えておいた。数字はアライン指定らしい。しかしなんで2なんだろう? CprtexM系は32ビットマイコンなのに・・Thumb命令だから?