- ローカル変数の宣言を可能にして、スタック内がどうなっているか、コンパイラに管理してもらえるようにしました。
void main()
{
params(1); // このmain内で行われる関数呼び出しは、引数が最大で1つだという意味(もしインラインアセンブラ内で関数呼び出ししないなら、この記述はいらない).
asm {
MovRI(R0,46); StoRMd(R0,SP,0); CalII($fib,@lb0:); // R0 = fib(46);
return R0;
}
}
int fib(int i)
{
int tmp;
params(1);
asm {
LodRMd(R0,SP,$i); CmpJleRII(R0,1,@skip); // if (i <= 1) goto skip;
SubRI(R0,2); StoRMd(R0,SP,0); CalII($fib,@lb0:); StoRMd(R0,SP,$tmp); // tmp = fib(i-2);
LodRMd(R0,SP,$i); SubRI(R0,1); StoRMd(R0,SP,0); CalII($fib,@lb1:); // R0 = fib(i-1);
LodRMd(R1,SP,$tmp); AddRR(R0,R1); // R0 += tmp;
LbI(@skip:);
}
}
- このfib()部分のコンパイル結果はこうなります。
LbI(4); // fib()
SubAI(SP,16);
StoAMd(RP,SP,12);
LodRMd(R0,SP,16); CmpJleRII(R0,1,7); // if (i <= 1) goto skip;
SubRI(R0,2); StoRMd(R0,SP,0); CalII(4,5); StoRMd(R0,SP,8); // tmp = fib(i-2);
LodRMd(R0,SP,16); SubRI(R0,1); StoRMd(R0,SP,0); CalII(4,6); // R0 = fib(i-1);
LodRMd(R1,SP,8); AddRR(R0,R1); // R0 += tmp;
LbI(7); // skip:
LodAMd(RP,SP,12);
AddAI(SP,16);
Ret();
- 変数オフセットやラベルなどがすべて無事に数値化できています。
- スタックはこんな感じになっています。
{ [SP+0:引数用の領域8バイト] [SP+8:変数tmp] [SP+12:RP保存領域] } [SP+16:引数i]