asmlinkageってなに?


Rev.1を表示中。最新版はこちら

asmlinkageというマクロは下記のように定義されています。CPP_ASMLINKAGEはC++でコンパイルした時の関数名をC表記とする宣言です。asmlinkageはregparmと展開されています。regparmは指定する数値分のパラメータの引数をレジスタ渡しとすることです。なお、カーネルソースでasmlinkageで宣言している関数をみると、引数はありません。regparmは0として展開しています。で、これって意味あるのでしょうか?
#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))

ifdef __cplusplus
#define CPP_ASMLINKAGE extern "C"
#else
#define CPP_ASMLINKAGE
#endif
まず、実際regparmがどのように展開されるか見てみようと思います。
#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(2)))
int _a, _b;
asmlinkage void asmlinkage_test(int a, int b)
{
   _a = a;
   _b = b;
}

calltest()
{
    asmlinkage_test(1, 2);
}

 <asmlinkage_test>:
       55                      push   %ebp
       89 e5                   mov    %esp,%ebp
       83 ec 08                sub    $0x8,%esp
       89 45 fc                mov    %eax,-0x4(%ebp) <- 第1引数をスタックへ
       89 55 f8                mov    %edx,-0x8(%ebp) <- 第2引数をスタックへ
       8b 45 fc                mov    -0x4(%ebp),%eax <- スタック上引数をAXへ
       a3 2c 96 04 08          mov    %eax,0x804962c
       8b 45 f8                mov    -0x8(%ebp),%eax <- スタック上引数をAXへ
       a3 28 96 04 08          mov    %eax,0x8049628
       c9                      leave
       c3                      ret

 <calltest>:
       55                      push   %ebp
       89 e5                   mov    %esp,%ebp
       83 ec 04                sub    $0x4,%esp
       ba 02 00 00 00          mov    $0x2,%edx <- 第2引数
       b8 01 00 00 00          mov    $0x1,%eax <- 第一引数
       e8 cd ff ff ff          call   8048394 <asmlinkage_test>
       c9                      leave
       c3                      ret
呼び出し元の第1引数をAXに、第二引数をDXにセットし、asmlinkage_testを呼んでいます(本来はスタック)。受け取り側は、引数が設定されているレジスターをわざわざスタックに戻して、いかにも通常のスタックで渡された物として処理しています(引数の数とregparamの数値が異なっても、柔軟に対応するためだと思います。)。ともかく、呼び出し側では、確かにレジスターで引数を渡せばいいようです。

では、カーネルでの使われ方を見てみようと思いますが・・・。あえて言うなら、regparmは引数にかかる処理をコントロールするもので、引数のない関数に適用しても意味のないのは明白です。ひょっといたらアーキテクチャーで違うのかもしれませんが、少なくともIA-32では意味がない。と言えそうですが・・・。
#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))

int _a, _b;
asmlinkage void asmlinkage_test(void)
{
  _a = 1;
}

calltest()
{
   asmlinkage_test();
}

 <asmlinkage_test>:
       55                      push   %ebp
       89 e5                   mov    %esp,%ebp
       c7 05 0c 96 04 08 01    movl   $0x1,0x804960c
       00 00 00
       5d                      pop    %ebp
       c3                      ret

 <calltest>:
       55                      push   %ebp
       89 e5                   mov    %esp,%ebp
       83 ec 04                sub    $0x4,%esp
       e8 e6 ff ff ff          call   8048394 <asmlinkage_test>
       c9                      leave
       c3                      ret
関数引数が2つでregparmの設定が1の時どうなるか見てみました。
#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(1)))

int _a, _b;
asmlinkage void asmlinkage_test(int a, int b)
{
   _a = a;
   _b = b;
}

calltest()
{
   asmlinkage_test(1, 2);
}

 <asmlinkage_test>:
       55                      push   %ebp
       89 e5                   mov    %esp,%ebp
       83 ec 04                sub    $0x4,%esp
       89 45 fc                mov    %eax,-0x4(%ebp)<- 第一引数をスタックへ
       8b 45 fc                mov    -0x4(%ebp),%eax<- 第一引数の取り出し
       a3 2c 96 04 08          mov    %eax,0x804962c
       8b 45 08                mov    0x8(%ebp),%eax <- 第二引数の取り出し
       a3 28 96 04 08          mov    %eax,0x8049628
       c9                      leave
       c3                      ret

 <calltest>:
       55                      push   %ebp
       89 e5                   mov    %esp,%ebp
       83 ec 08                sub    $0x8,%esp
       c7 04 24 02 00 00 00    movl   $0x2,(%esp) <- 第二引数はスタック
       b8 01 00 00 00          mov    $0x1,%eax   <- 第一引数はAX
       e8 ce ff ff ff          call   8048394 <asmlinkage_test>
       c9                      leave
       c3                      ret
引数1はAXに、引数2はスタックで渡しています。受け取り側では、AXをスタックに設定しなおして、スタックから引数1と引数2を取り出しています。受け取り側でわざわざスタックに戻して、処理をおこなうのは、このようなケースでも柔軟に対応する仕組みだったんですね。

補足
呼び出し側の引数はpushでスタックされるものと思ってましたが、関数入り口で引数も考慮した形でスタックを確保(SPの減算)し、movで直接スタックにセットしているのは意外でした。

最終更新 2010/03/05 15:06:23 - north
(2010/03/05 15:06:23 作成)


検索

アクセス数
3689577
最近のコメント
コアダンプファイル - sakaia
list_head構造体 - yocto_no_yomikata
勧告ロックと強制ロック - wataash
LKMからのファイル出力 - 重松 宏昌
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
Adsense
広告情報が設定されていません。