微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 单片机复位程序

单片机复位程序

时间:11-10 来源:互联网 点击:

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

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


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

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

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

而单片机复位的更好方法
clra//清除ACC=0
pushacc//压0到堆栈——8位
pushacc//再压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 120003LCALL 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 120000LCALL 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: }

请大家注意红色的部分。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top