【小结】单片机复位程序

今天在网上看到这么一个单片机复位的程序,这个程序据说是一个大三的学生写出来的,不错,写的很有一定的道理,其C编程也达到了一定程度了【小盒子我还是很佩服这个人的】。下面我们来看看这个代码:

void main(void)
{
   unsigned char code rst[]={0xe4,0xc0,0xe0,0xc0,0xe0,0x32};  // 复位代码


   (*((void (*)())(rst)))();  // 执行上一行代码,将rst数组当函数调用
}

第一句定义一个数组rst[],数组内数据就是完成复位功能的汇编机器码,具体对应关系为:

clr a == 0xe4、push acc == 0xc0,0xe0、reti ==0x32
可以看出其程序起到复位的作用,完全就是汇编机器码的功劳。

而单片机复位的更好方法
clr a                      //清除ACC=0
push acc               //压0到堆栈——8位
push acc               //再压0到堆栈——再8位
reti                        //返回到0地址,从新执行。

这种复位方法比较麻烦,更加简单的复位写法是(摘自《C缺陷与陷阱》):
(     * (  void (*)( )  )0      ) ( );

看过上面更简单的复位方法,让我们多加考虑一下,为什么要写成0?别的不行吗?换成别的后会是什么样的效果呢?抱着这个想法,我亲自经过KEIL V2.4.0编译后的汇编程序:

可以看出若将(     * (  void (*)( )  )0     ) ( );  

改成(     * (  void (*)( )  )3      ) ( );

 

则程序会跳转到main()函数开始,避开startup文件的初始化……

 只所以我说的是会从main()开始,是因为我看过编译后的汇编文件,找到main的实际物理地址而已,否则我也不会写成3了。呵呵……下面就是编译后的汇编结果

C:0x0003    E4       CLR      A
C:0x0004    F508     MOV      0x08,A
C:0x0006    F509     MOV      0x09,A
    14:    while(1) {
    15:         if(i == 10) {
    16:            //(    *(   ( void (*)( ) )   (rst)    )    )();  // 执行上一行代码,将rst数组当函数调用
C:0x0008    E509     MOV      A,0x09
C:0x000A    640A     XRL      A,#0x0A
C:0x000C    4508     ORL      A,0x08
C:0x000E    7005     JNZ      C:0015
    17:            (    *(   ( void (*)( ) )   (3)    )    )();  // 执行上一行代码,将rst数组当函数调用
C:0x0010    120003   LCALL    main(C:0003)
    18:         } else {
C:0x0013    80F3     SJMP     C:0008
    19:                 i++;
C:0x0015    0509     INC      0x09
C:0x0017    E509     MOV      A,0x09
C:0x0019    70ED     JNZ      C:0008
C:0x001B    0508     INC      0x08
    20:         }

 

为了进行给大家一个很好的比较,从视觉上得到一定的感觉,我又再次将3改回成0,大家看看编译后的汇编结果是什么样子的;

下面的代码是函数(     * (  void (*)( )  )0     ) ( );   这个编译后的结果

C:0x0003    E4       CLR      A
C:0x0004    F508     MOV      0x08,A
C:0x0006    F509     MOV      0x09,A
    14:    while(1) {
    15:         if(i == 10) {
    16:            //(    *(   ( void (*)( ) )   (rst)    )    )();  // 执行上一行代码,将rst数组当函数调用
C:0x0008    E509     MOV      A,0x09
C:0x000A    640A     XRL      A,#0x0A
C:0x000C    4508     ORL      A,0x08
C:0x000E    7005     JNZ      C:0015
    17:            (    *(   ( void (*)( ) )   (0)    )    )();  // 执行上一行代码,将rst数组当函数调用
C:0x0010    120000   LCALL    C_STARTUP(C:0000)
    18:         } else {
C:0x0013    80F3     SJMP     C:0008
    19:                 i++;
C:0x0015    0509     INC      0x09
C:0x0017    E509     MOV      A,0x09
C:0x0019    70ED     JNZ      C:0008
C:0x001B    0508     INC      0x08
    20:         }

请大家注意红色的部分。

若大家都能亲自动手实际操作一下,会让你理解的更多,体会的也会更多的。。。具体的还有什么好的方法和好的建议,希望多多留言大家共同进步。【小盒子 2007.08.17     PM17:14】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值