SSブログ

ユーザ・ドライバに複数の引数を与える方法 [ColdFire V2]このエントリーを含むはてなブックマーク#

1990557

おおやけには、ユーザ・ドライバには、引数を一つしか渡すことが出来ないとされています。 何とか複数の引数を渡す方法は無いでしょうか。

スタック・フレームと引数構造体

CodeWarrior のコンパイラが生成するコードは、 A6 レジスタを使用して、スタック・フレームの管理を行っています。 たとえば、ユーザが記述したユーザ・ドライバ "uint32 driver(uint32 arg)" が呼び出されると、 "driver" 関数に与えられた引数とそこで使用される局所変数へは、 A6 レジスタを介してアクセスすることができます。

UserDriverStackFrame.png

また、スタック・フレームには、呼び出し元のスタック・フレームへのポインタも含まれています。 そのため、スタック・フレームをさかのぼると、次々と呼び出し元の関数のスタック・フレームにアクセスすることが出来ます。

また、 SilentC は、インタプリタなので、字句解析を行ったのち、該当する関数に相当するコンパイル済み関数を呼び出します。 たとえば、 "UserDriver" 関数の場合には、 "UserDriverSub" という関数が呼び出されます。 この呼び出しの際には、 SilentC の引数を表現した引数構造体へのポインタが渡されます。 そこで、この構造体を介して、ユーザ・ドライバに複数の引数を渡すことが出来ます。

UserDriver 関数の引数をコピーするプログラム

さっそく、プログラムを作って試してみます。 このプログラムは、 UserDriver 関数に与えられた引数構造体を 0x20007F80 からの空きエリアに単純にコピーするプログラムです。

#include "support_common.h" /* include peripheral declarations and more */
#include "silentmoon.h"

//
// Stack frame structure
//
struct stack_frame {
  struct stack_frame *invoker;
  void *return_value;
  uint32 args[0];
};

//
// SilentC's argument structure
//
struct arguments {
  uint32 mode;
  uint32 args[0];
};

//
// VECTOR #0 : main
//
uint32 main(uint32 arg) {
  #pragma unused(arg)
  struct stack_frame *this_frame;
  struct stack_frame *invoker_frame;
  struct arguments *silentc_args;
  uint32 *table = (uint32 *)0x20007f80;
  
  asm {
    move a6,this_frame
  }
  invoker_frame = this_frame->invoker;
  silentc_args = (struct arguments *)invoker_frame->args[0];
  BufCopy(table, silentc_args, 64);
  return (uint32)0;
}

//
//  Jump table for vectors
//
__declspec(jump_table)
asm void jump_table(void) {
  jmp main      // Driver #0   
}

書き込んで実行してみます。 9個の引数が、 0x20007F88 から 0x20007FA7 まで並んでいるのがわかります。

OK
UserDriver(0,1,2,3,4,5,6,7,8)

OK
m::d(0x20007f80)
20007f80  41 00 00 09 00 00 00 00  A.......
20007f88  00 00 00 01 00 00 00 02  ........
20007f90  00 00 00 03 00 00 00 04  ........
20007f98  00 00 00 05 00 00 00 06  ........
20007fa0  00 00 00 07 00 00 00 08  ........
20007fa8  00 00 6e e8 00 00 65 c0  ..n...e.
20007fb0  02 00 00 00 00 02 00 00  ........
20007fb8  00 00 00 00 00 00 00 00  ........

違う引数を与えると、こうなりました。 7個の引数が、 0x20007F88 から 0x20007F9F まで並んでいるのがわかります。

OK
UserDriver(0,256,257,258,259,260,261)

OK
m::d(0x20007f80)
20007f80  41 00 00 07 00 00 00 00  A.......
20007f88  00 00 01 00 00 00 01 01  ........
20007f90  00 00 01 02 00 00 01 03  ........
20007f98  00 00 01 04 00 00 01 05  ........
20007fa0  00 00 01 00 00 00 01 01  ........
20007fa8  00 00 01 02 00 00 01 03  ........
20007fb0  00 1d 00 07 00 00 00 06  ........
20007fb8  00 00 00 00 00 00 01 00  ........

この結果から、 "UserDriver" 関数の第二引数が args[1] に格納され、第三引数が args[2] に格納され、以下、順に格納されていることがわかります。 また、 mode の下8ビット、ダンプ・リストでいう所の 0x20007f83 番地には、 "UserDriver" 関数に与えられた引数の数も保存されています。 この仕掛けを使えば、可変長の引数をユーザ・ドライバに渡すことも出来ますね。

プロジェクト・アーカイブ

ユーザ・ドライバのプロジェクトは、これを CFCQ06.zip という名前で保存すると再現できます。

参考文献

Interface (インターフェース) 2008年 12月号 [雑誌]

Interface (インターフェース) 2008年 12月号 [雑誌]

  • 作者:
  • 出版社/メーカー: CQ出版
  • 発売日: 2008/10/25
  • メディア: 雑誌
Interface (インターフェース) 2008年 09月号 [雑誌]

Interface (インターフェース) 2008年 09月号 [雑誌]

  • 作者:
  • 出版社/メーカー: CQ出版
  • 発売日: 2008/07/25
  • メディア: 雑誌

nice!(0)  コメント(0)  トラックバック(0)  このエントリーを含むはてなブックマーク#

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

トラックバックの受付は締め切りました

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。