keil 里有这样一个特性:
函数在调用前定义与在调用后定义产生的代码是有很大差别的(特别是在优化级别大于3级时)。(本人也不太清楚为什么,大概因为在调用前定义则调用函数已经知道被调用函数对寄存器的使用情况,则可对函数本身进行优化;而在调用后进行定义则函数不知被调用函数对寄存器的使用情况,它默认被调用函数对寄存器(ACC、 B、 DPH、 DPL、 PSW、 R0、 R1、 R2、 R3、R 4、 R5、, R6、 R7)都已经改变,因此不在这些寄存器中存入有效的数据)
举例:
void fun2(void)
{
}
void fun1(unsigned char i)
{
fun2();
while(i--);
}
它的汇编代码如下:
; void fun2(void)
RSEG ?PR?fun2?TEST
fun2:
; SOURCE LINE # 12
; {
; SOURCE LINE # 13
; }
; SOURCE LINE # 14
RET
; END OF fun2
;
; void fun1(unsigned char i)
RSEG ?PR?_fun1?TEST
_fun1:
USING 0
; SOURCE LINE # 16
;---- Variable 'i?240' assigned to Register 'R7' ----
; {
; SOURCE LINE # 17
; fun2();
; SOURCE LINE # 18
LCALL fun2
?C0003:
; while(i--);
; SOURCE LINE # 19
MOV R6,AR7
DEC R7
MOV A,R6
JNZ ?C0003
; }
; SOURCE LINE # 20
?C0005:
RET
; END OF _fun1
从中可以看到fun2()在fun1()前先定义,fun1()知道fun2()对寄存器的使用情况,知道R7没有改变,而参数i存于R7中,即i既是R7。(;---- Variable 'i?140' assigned to Register 'R7' ----)
这样就引出一个问题:当使用模块化编程时,因为是把程序分成很多C文件和.h文件,当需要在某个地方用时当前的C文件开始会用#include包含进来,这样就相当是在函数调用后定义的,当KEIL编译后,看反汇编文件会发现传过来的参数都传到了固定地址上(寄存器还没用完),请教各位怎么解决这个问题既能模块化编程有让其传过来的参数不用固定地址接受,让寄存器接受!!! |