打印

请教:keil 里函数的局部变量被分配到固定地址的问题

[复制链接]
4750|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
dolin_wu|  楼主 | 2010-11-14 13:34 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
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编译后,看反汇编文件会发现传过来的参数都传到了固定地址上(寄存器还没用完),请教各位怎么解决这个问题既能模块化编程有让其传过来的参数不用固定地址接受,让寄存器接受!!!

相关帖子

沙发
ayb_ice| | 2010-11-14 14:19 | 只看该作者
没有这回事
使能全局寄存器优化即可

使用特权

评论回复
板凳
dolin_wu|  楼主 | 2010-11-14 15:37 | 只看该作者
本帖最后由 dolin_wu 于 2010-11-14 15:39 编辑

谢谢aye_ice热心的帮助,如果是模块化编程使用多个C文件使用全局寄存器优化确实可以解决这个问题。

但是如果在单个C文件中,若函数在使用后定义确实存在这种情况:我把这种情况的具体代码贴出来:

void fun2(void);

void fun1(unsigned char i)

{

       fun2();

       while(i--);

}



void fun2(void)

{

}

汇编代码如下:

; void fun1(unsigned char i)



       RSEG  ?PR?_fun1?TEST

_fun1:

       USING    0

                     ; SOURCE LINE # 14

       MOV         i?140,R7

; {

                     ; SOURCE LINE # 15

;     fun2();

                     ; SOURCE LINE # 16

       LCALL       fun2

?C0002:

;     while(i--);

                     ; SOURCE LINE # 17

       MOV         R7,i?140

       DEC         i?140

       MOV         A,R7

       JNZ         ?C0002

; }

                     ; SOURCE LINE # 18

?C0004:

       RET      

; END OF _fun1



;

; void fun2(void)



       RSEG  ?PR?fun2?TEST

fun2:

                     ; SOURCE LINE # 20

; {

                     ; SOURCE LINE # 21

; }

                     ; SOURCE LINE # 22

       RET      

; END OF fun2

fun2()在fun1()调用后定义,因fun1()调用fun2()时不知道fun2()对寄存器的使用情况,则认为fun2()改变了所有的寄存器(ACC、 B、 DPH、 DPL、 PSW、 R0、 R1、 R2、 R3、R 4、 R5、, R6、 R7)。因为fun1()认为fun2()改变了寄存器的值(包括R7),因此i虽然通过R7传递,但因已因调用fun2()而改变,所以不能再存在R7了,而上在RAM中额外的用一个Byte来存储。

使用特权

评论回复
地板
dong_abc| | 2010-11-14 16:08 | 只看该作者
菜鸟路过,顺便学习一下

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

11

主题

36

帖子

1

粉丝