SSブログ

ColdFire でアセンブラ (2) - レジスタを使ってくれ [ColdFire (ColdeFire) V1]このエントリーを含むはてなブックマーク#

前回は一部だけをアセンブラで書いた関数を作りました。 今回は、全てをアセンブラで記述します。

関数ごとアセンブラにする

関数ごとアセンブラで記述するには、関数に"__asm""指示子をつけます。

__asm dword func2(dword a, dword b) {
  dword x;
  move    a,x  // x = a
  add     b,x  // x *= b
  move    x,d0 // return value
  rts
}

前回と同じように二つの引数の和を返す関数です。 作業領域として使用している変数xを使って、 直接加算操作を行っています。 コンパイルすると、このようになります。

;   29: __asm dword func2(dword a, dword b) { 
;   30:   dword x; 
;   31:   move    a,x  // x = a 
0x00000000                    _func2:
;                             func2:
0x00000000  0x2E80                   move.l   d0,(a7)
;
;   32:   add     b,x  // x *= b 
0x00000002  0xD397                   add.l    d1,(a7)
;
;   33:   move    x,d0 // return value 
0x00000004  0x2017                   move.l   (a7),d0
;
;   34:   rts 
0x00000006  0x4E75                   rts      

一見、うまくできたように見えますが、 作業領域として使用している(a7)には、 リターン・アドレスが入っているため、 関数から戻るときに暴走してしまいます。

作業領域を安全に確保する

先のプログラムでは、作業領域が確保されませんでした。 作業領域を確実に確保するために、 frallocfrfreeという 擬似命令が用意されています。

__asm dword func3(dword a, dword b) {
  dword x;
  fralloc
  move    a,x  // x = a
  add     b,x  // x *= b
  move    x,d0 // return value
  frfree
  rts
}

アセンブラの記述の前後にfrallocfrfreeを 入れるだけです。

;   23: __asm dword func3(dword a, dword b) { 
;   23:                                     { 
;   24:                                       dword x; 
;   25:                                       fralloc 
0x00000000                    _func3:
;                             func3:
0x00000000  0x4E560000               link     a6,#0
;
;   26:   move    a,x  // x = a 
0x00000004  0x2400                   move.l   d0,d2
;
;   27:   add     b,x  // x *= b 
0x00000006  0xD481                   add.l    d1,d2
;
;   28:   move    x,d0 // return value 
0x00000008  0x2002                   move.l   d2,d0
;
;   29:   frfree 
0x0000000A  0x4E5E                   unlk     a6
;
;   30:   rts 
0x0000000C  0x4E75                   rts      
0x0000000E  0x51FC                   trapf    

frallocは、レジスタに優先的に作業領域を割り当てます。 このため、変数xもレジスタに割り当てられました。

局所変数が多くなったらどうなる

上の例では、レジスタですべての作業領域をまかなうことができました。 それでは、レジスタでまかなえないほど多くの局所変数が定義されたらどうなるでしょうか。

__asm dword func4(dword a, dword b) {
  dword x, w1, w2, w3, w4;
  fralloc
  move    a,x  // x = a
  add     b,x  // x *= b
  add     x,w1
  add     x,w2
  add     x,w3
  add     x,w4
  move    x,d0 // return value
  frfree
  rts
}

局所変数w1からw4が、 新たに使用されています。 もちろん、このプログラムに深い意味はありません。 コンパイルすると、このようになります。

;   33: __asm dword func4(dword a, dword b) { 
;   33:                                     { 
;   34:                                       dword x, w1,w2,w3,w4; 
;   35:                                       fralloc 
0x00000000                    _func4:
;                             func4:
0x00000000  0x4E560000               link     a6,#0
0x00000004  0x4FEFFFF4               lea      -12(a7),a7
0x00000008  0x48D700E0               movem.l  d5-d7,(a7)
;
;   36:   move    a,x  // x = a 
0x0000000C  0x2400                   move.l   d0,d2
;
;   37:   add     b,x  // x *= b 
0x0000000E  0xD481                   add.l    d1,d2
;
;   38:   add     x,w1 
0x00000010  0xDE82                   add.l    d2,d7
;
;   39:   add     x,w2 
0x00000012  0xDC82                   add.l    d2,d6
;
;   40:   add     x,w3 
0x00000014  0xDA82                   add.l    d2,d5
;
;   41:   add     x,w4 
0x00000016  0xD282                   add.l    d2,d1
;
;   42:   move    x,d0 // return value 
0x00000018  0x2002                   move.l   d2,d0
;
;   43:   frfree 
0x0000001A  0x4CD700E0               movem.l  (a7),d5-d7
0x0000001E  0x4E5E                   unlk     a6
;
;   44:   rts 
0x00000020  0x4E75                   rts      
0x00000022  0x51FC                   trapf    

関数の最初の部分で、 スタックに12バイトのエリアを確保して、そこにD5-D7のレジスタを退避させています。 これで、多くの作業領域を使用することができるようになりました。


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

nice! 0

コメント 2

hamayan

なるほど!、このCソースにアセンブラコードを容易に埋め込める機能は便利ですが、挙動を理解して使わないとあれですね。
特に先頭の例題なんか、リストを出力するなり逆アセンブルするまで嵌っていそう。
by hamayan (2008-01-20 22:14) 

noritan

基本的に、コンパイラを信用していないので、すっかり Disassembler とお友達です。
他にも理解しがたい現象(ミスアセンブル?)も見つけちゃったので、後ほど書きます。
by noritan (2008-01-21 08:09) 

コメントを書く

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

トラックバック 0

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

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