army
シミュレータはC++言語により記述されており、構造が単純であるため全体の
構造を短期間に理解可能である。
そのため、シミュレータの改造や機能拡張が容易である。
C言語あるいはARMアセンブリ言語で記述したプログラムソースファイルを
クロスコンパイラおよびクロスアセンブラで実行可能バイナリコードを生成し、
生成したバイナリコードを16進表現でダンプしたテキストファイル(正式には
「モトローラSレコード形式」)をシミュレータの入力として読み込み、実行する。
(現在のところ)ライブラリが要求するシステムコールを実装していないため、
printf()
などの標準Cライブラリは使用できないが、
入出力の代替手段として簡単なサービスコール機能を備えており、これにより
整数型データや文字列データなどの入出力やプログラムの終了などを行うことが
できる。
armyは以下のファイルから構成される。
上記ソースファイルをまとめたZIPファイルを
ここに置いておくので
一括してファイルを取得した場合に利用するとよい。
※Makefileを同梱しているので、
cygwin環境では makeを実行すればシミュレータをビルドできる。
参考資料
各命令の動作内容の詳細については
ARMアーキテクチャリファレンスマニュアル(日本語版)あるいは
ARM7TDMI Data Sheet Chapter 4を参照。
SWI命令を使ったサービスコールを行うことで、 データの入出力やプログラムの終了などの機能を実現することができる。
SWI命令を実行する。 サービスコールの返値はレジスタ0番にセットされる。
現在、以下の機能を使うことができる。
armyソースコードの
armクラスの メンバ関数
do_swi()内を調べるとよい。
以下はサービスコールの使い方を示した例である。
li $4,123 /* 表示する値をレジスタ4番にセット */ li $2,0x21 /* 整数型データ出力の機能コード(== 0x21)を レジスタ2番にセット */ break /* break命令を実行 レジスタ4番にセットした値が画面に表示される */ la $4,SBUF_LABEL /* 文字列入力用のバッファの先頭アドレスを レジスタ4番にセット */ li $2,0x13 /* 文字列データ入力の機能コード(== 0x13)を レジスタ2番にセット */ break /* break命令を実行 レジスタ4番で指定したアドレスに文字列データが 読み込まれる */
インラインアセンブラを使うことで、
C言語からもサービスコールを使うことができる。
int v = 123; char strbuf[2048]; ... (中略) ... /* 整数型データ出力 */ asm ("move $4,%0" : : "r" (v)); asm ("li $2,0x21"); asm ("break"); /* 文字列データ入力 */ asm ("move $4,%0" : : "r" (strbuf)); asm ("li $2,0x13"); asm ("break");
C言語でインラインアセンブラ記述が続くとソースコードが読みにくくなる&
間違ったコードが入りやすくなるため、C言語のマクロとして定義しておくと
便利である。
ここにマクロ定義したヘッダファイル
army.h
が置いてあるので自由に使ってよい。
このヘッダファイルを使ってサービスコールを使った例を以下に示す。
#include "army.h" int main() { int v; char c; char tmpbuf[512]; PRINT_INT(123456789); PRINT_CHAR('X'); PRINT_STRING("FIZZ BUZZ"); READ_INT(v); READ_CHAR(c); READ_STRING(tmpbuf); PRINT_INT(v); PRINT_CHAR(c); PRINT_STRING(tmpbuf); EXIT(0); /* control does not reach here */ return 0; }
army用プログラムの記述
printf()などの標準Cライブラリ関数を使うことは出来ない。 そのため、これらの関数を使わずに記述する必要がある。
main関数の最後で特にプログラムの終了 を指示しなくても問題はなかったが、
army用のプログラムでは プログラム終了を明示的に記述する必要がある。
army.hを 使用してプログラムの記述を省力化している。 もし自分で作るプログラムで
army.hを 使用する場合は、プログラムのソースファイルと同じフォルダに
army.hを忘れずに置くこと。
Cソースファイル/ 逆アセンブルリスト/ ダンプテキストファイル#include "army.h" int fact(int n) { if (n <= 1) return 1; else return n * fact(n - 1); } int main() { int i; for (i = 0; i < 10; i++) { int v = fact(i); PRINT_INT(v); } EXIT(0); /* program ends here */ /* control never reaches here */ return 0; }
ソースプログラムの記述には自分の使い慣れたテキストエディタを使えばよい。
(例えば、
TeraPadなど)
armyでのプログラムの実行方法
./army program_file_name.srec 例: ./army fact.srec