SSブログ

ColdFire でアセンブラ (6) - そんなに最適化するなよ [ColdFire (ColdeFire) V1]このエントリーを含むはてなブックマーク#

某所で 使われていた「TRAP命令に引数を渡す」プログラムを見て、 もしかしたら危ないかも知れないと思い実験してみました。

元のコード

もともとのコードはこんなものでした。 型宣言と定数宣言は適当に追加しています。

typedef byte  UB;
typedef int   TMO;

const UB FC_TSLP_TSK    = 129;
const UB FC_SLP_TSK     = 130;
const TMO TMO_FEVR      = -1;

#define  tslp_tsk( tmout )  __slp_tsk( (UB)FC_TSLP_TSK, (TMO)tmout )
#define  slp_tsk()          __slp_tsk( (UB)FC_SLP_TSK, TMO_FEVR )

void __slp_tsk(
  UB fc,		/*機能コード*/
  TMO tmout		/*タイムアウト時間*/
  )
{
  __asm {
    trap #0;
  };
}

で、この関数を呼び出すために作ったサンプルがこれです。

void main(void) {
  for(;;) {
    tslp_tsk(100);
    slp_tsk();
    tslp_tsk(200);
    slp_tsk();
  } /* loop forever */
  /* please make sure that you never leave main */
}

二つの擬似タスクを延々と呼び出します。 コンパイルすると、__slp_tsk関数の引数fcが 使われていないと文句(Warning)を言われます。 コンパイルの結果がこれです。

;   35:                   for(;;) { 
;   36:     tslp_tsk(100); 
;
0x00000000                    _main:
;                             main:
0x00000000  0x4E40                   trap     #0
;
;   37:     slp_tsk(); 
;
0x00000002  0x4E40                   trap     #0
;
;   38:     tslp_tsk(200); 
;
0x00000004  0x4E40                   trap     #0
;
;   39:     slp_tsk(); 
;
0x00000006  0x4E40                   trap     #0
;
;   40:   } /* loop forever */ 
;
0x00000008  0x60F6                   bra.s    *-8                   ; 0x00000000
0x0000000A  0x51FC                   trapf    

関数がインライン展開された上に 使われない引数が省略されています。 これでは、当初の目的を果たしません。

関数ごとアセンブラで記述する

そこで、策を考えました。 関数ごとアセンブラで記述してしまいます。

void __asm __slp_tsk_1(
  UB fc,		/*機能コード*/
  TMO tmout		/*タイムアウト時間*/
  )
{
    trap #0
    rts
}

すると、こんどは律儀にサブルーチン呼び出しをしてくれるようになります。

;   28: { 
;   29:     trap #0 
;
0x00000000                    ___slp_tsk_1:
;                             __slp_tsk_1:
0x00000000  0x4E40                   trap     #0
;
;   30:     rts 
;
0x00000002  0x4E75                   rts      
;   35:                   for(;;) { 
;   36:     tslp_tsk(100); 
;
0x00000000                    _main:
;                             main:
0x00000000  0x7264                   moveq    #100,d1
0x00000002  0x717C0081               mvs.w    #129,d0
0x00000006  0x4EBA0000               jsr      ___slp_tsk_1
;
;   37:     slp_tsk(); 
;
0x0000000A  0xA141                   mov3q    #-1,d1
0x0000000C  0x717C0082               mvs.w    #130,d0
0x00000010  0x4EBA0000               jsr      ___slp_tsk_1
;
;   38:     tslp_tsk(200); 
;
0x00000014  0x737C00C8               mvs.w    #200,d1
0x00000018  0x717C0081               mvs.w    #129,d0
0x0000001C  0x4EBA0000               jsr      ___slp_tsk_1
;
;   39:     slp_tsk(); 
;
0x00000020  0xA141                   mov3q    #-1,d1
0x00000022  0x717C0082               mvs.w    #130,d0
0x00000026  0x4EBA0000               jsr      ___slp_tsk_1
;
;   40:   } /* loop forever */ 
;
0x0000002A  0x60D4                   bra.s    *-42                  ; 0x00000000

何とか、このままインライン関数にしてくれないかなあ。

volatileという「おまじない」

次は、魔法のおまじない「volatile」をためしてみます。

void __slp_tsk_2(
  volatile UB fc,		/*機能コード*/
  volatile TMO tmout		/*タイムアウト時間*/
  )
{
  __asm {
    trap #0
  };
}
;   46:                   for(;;) { 
;
0x00000000                    _main:
;                             main:
0x00000000  0x4FEFFFEC               lea      -20(a7),a7
;
;   47:     tslp_tsk(100); 
;
0x00000004  0x7064                   moveq    #100,d0
0x00000006  0x2F400008               move.l   d0,8(a7)
0x0000000A  0x1EBC0081               move.b   #-127,(a7)            ; '.'
0x0000000E  0x4E40                   trap     #0
;
;   48:     slp_tsk(); 
;
0x00000010  0xA16F000C               mov3q    #-1,12(a7)
0x00000014  0x1F7C00820001           move.b   #-126,1(a7)           ; '.'
0x0000001A  0x4E40                   trap     #0
;
;   49:     tslp_tsk(200); 
;
0x0000001C  0x717C00C8               mvs.w    #200,d0
0x00000020  0x2F400004               move.l   d0,4(a7)
0x00000024  0x1F7C00810002           move.b   #-127,2(a7)           ; '.'
0x0000002A  0x4E40                   trap     #0
;
;   50:     slp_tsk(); 
;
0x0000002C  0xA16F0010               mov3q    #-1,16(a7)
0x00000030  0x1F7C00820003           move.b   #-126,3(a7)           ; '.'
0x00000036  0x4E40                   trap     #0
;
;   51:   } /* loop forever */ 
;
0x00000038  0x60CA                   bra.s    *-52                  ; 0x00000004
0x0000003A  0x51FC                   trapf    

揮発しないように、スタックに積んでくれました。 それをレジスタ渡しにして欲しいんだけど。

屋上屋を重ねる

つまり、明示的にレジスタに引数を入れればいいのだな。

void __slp_tsk_3(
  UB fc,		/*機能コード*/
  TMO tmout		/*タイムアウト時間*/
  )
{
  __asm {
    move fc,d0
    move tmout,d1
    trap #0
  };
}
;   57:                   for(;;) { 
;
0x00000000                    _main:
;                             main:
0x00000000  0x4FEFFFEC               lea      -20(a7),a7
;
;   58:     tslp_tsk(100); 
;
0x00000004  0x7464                   moveq    #100,d2
0x00000006  0x2F420008               move.l   d2,8(a7)
0x0000000A  0x1EBC0081               move.b   #-127,(a7)            ; '.'
0x0000000E  0x2017                   move.l   (a7),d0
0x00000010  0x222F0008               move.l   8(a7),d1
0x00000014  0x4E40                   trap     #0
;
;   59:     slp_tsk(); 
;
0x00000016  0xA16F000C               mov3q    #-1,12(a7)
0x0000001A  0x1F7C00820001           move.b   #-126,1(a7)           ; '.'
0x00000020  0x202F0001               move.l   1(a7),d0
0x00000024  0x222F000C               move.l   12(a7),d1
0x00000028  0x4E40                   trap     #0
;
;   60:     tslp_tsk(200); 
;
0x0000002A  0x757C00C8               mvs.w    #200,d2
0x0000002E  0x2F420004               move.l   d2,4(a7)
0x00000032  0x1F7C00810002           move.b   #-127,2(a7)           ; '.'
0x00000038  0x202F0002               move.l   2(a7),d0
0x0000003C  0x222F0004               move.l   4(a7),d1
0x00000040  0x4E40                   trap     #0
;
;   61:     slp_tsk(); 
;
0x00000042  0xA16F0010               mov3q    #-1,16(a7)
0x00000046  0x1F7C00820003           move.b   #-126,3(a7)           ; '.'
0x0000004C  0x202F0003               move.l   3(a7),d0
0x00000050  0x222F0010               move.l   16(a7),d1
0x00000054  0x4E40                   trap     #0
;
;   62:   } /* loop forever */ 
;
0x00000056  0x60AC                   bra.s    *-82                  ; 0x00000004

何でわざわざスタックを使うかなあ。 しかも「move.l 1(a7),d0」ってのは、おかしいだろう。


さて、次はどんな書き方をしてやろうか。

続く…かも


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

nice! 1

コメント 3

hamayan

ナルホド、つまりサービスコールのフロントエンドはアセンブラで書け!という事ですね。
直しとこう。
by hamayan (2008-02-19 09:20) 

noritan

もし、"__slp_tsk"が別オブジェクト・ファイルに入っているのだったら、さすがにインライン展開はされないと思います。これも試しておかなくては。

だとすると、問題が出るのは、オペレーティング・システムの中味の方ですね。
とにかく、Disassemblerは手放せないようで。
by noritan (2008-02-19 14:09) 

hamayan

> とにかく、Disassemblerは手放せないようで

その前に、さんざん警告が出ているのに無視した私が間抜けでした。
by hamayan (2008-02-19 14:39) 

コメントを書く

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

トラックバック 0

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

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