for(i=2;i<=3;i++)
s=s+f1(i);
printf(\"\
s=%ld\
\",s);
在程序中,函數f1和f2均為長整型,都在主函數之前定義,故不必再在主函數中對f1和f2加以說明。在主程序中,執行循環程序依次把i值作為實參調用函數f1求i2值。在f1中又發生對函數f2的調用,這時是把i2的值作為實參去調f2,在f2中完成求i2!的計算。f2執行完畢把C值(即i2!)返回給f1,再由f1返回主函數實現累加。至此,由函數的嵌套調用實現了題目的要求。由於數值很大,所以函數和一些變量的類型都說明為長整型,否則會造成計算錯誤。
函數調用的實際(彙編)實現
指針寄存器EBP和ESP
EBP是所謂的幀指針,指向當前活動記錄的上方(上一個活動記錄的最下方)
ESP是所謂的棧指針,指向當前活動記錄的最下方(下一個將要插入的活動記錄的最上方)
這兩個指針的值規定了當前活動記錄的位置
參數傳遞
將函數參數壓棧:moveax,dwordptr[n];(n為參數變元)
pusheax
函數調用分配空間
函數調用將執行如下操作:
將幀指針壓入棧中:pushebp
使得幀指針等於棧指針:movebp,esp
使棧指針自減,自減得到的內存地址應當能夠(足夠)用來存儲被調用函數的本地狀態:subesp,0CCh
注意:0CCh為0xCC,隨著具體函數的不同而不同。
傳入保存狀態
pushebx;保存ebx寄存器的值
pushesi;保存esi寄存器的值
pushedi;保存edi寄存器的值
裝入edi
leaedi,[ebp-0CCh];0cch是當前活動記錄的大小。
EDI是目的變址寄存器。
恢複傳入的保存狀態
00411417popedi
00411418popesi
popebx
棧指針上移,恢複空間
addesp,0CCh
請前往oop.tw閱讀本書最新內容
函數返回釋放空間
當函數返回時,編譯器和硬件將執行如下操作:
使棧指針等於幀指針:movesp,ebp
從棧中將舊的幀指針彈出:popebp
返回:ret
一個函數調用的實例
;voidfunction(intn)
;{
pushebp
movebp,esp
subesp,0CCh
pushebx
pushesi
pushedi
leaedi,[ebp-0CCh]
movecx,33h
moveax,0CCCCCCCCh
repstosdwordptres:[edi]
;chara=1;
movbyteptr[a],1
;if(n==0)return;
cmpdwordptr[n],0
jnefunction+2Ah(4113CAh)
jmpfunction+77h(411417h)
;printf(\"%d\\t(0x%08x)\
\",n,&n);
movesi,esp
leaeax,[n]
pusheax
movecx,dwordptr[n]
pushecx
pushoffsetstring\"%d\\t(0x%08x)\
\"(415750h)
])h8B2814(ftnirp__pmi__[rtpdrowdllac
hC0,psedda
pse,isepmc
)h631114()psEkcehC_CTR__(503+TLI@llac
;)1-n(noitcnuf;
]n[rtpdrowd,xaevom
1,xaebus
xaehsup
)h140114(noitcnufllac
4,psedda
\)x80%x0(t\\d%----"\(ftnirp;
;)n&,n,"\
pse,isevom
]n[,xaeael
xaehsup
]n[rtpdrowd,xcevom
xcehsup
\)x80%x0(t\\d%----"\gnirtstesffohsup
)hC37514("\
])h8B2814(ftnirp__pmi__[rtpdrowdllac
hC0,psedda
pse,isepmc
)h631114()psEkcehC_CTR__(503+TLI@llac
};
idepop
isepop
xbepop
hCC0,psedda
pse,pbepmc
)h631114()psEkcehC_CTR__(503+TLI@llac
pbe,psevom
pbepop
ter