C51软复位分析
现单列复位部分如下:
main()
{
unsignedcharcoderst[]={0xe4,0xc0,0xe0,0xc0,0xe0,0x32};//复位代码
(*((void(*)())(rst)))();//执行上一行代码,将rst数组当函数调用
}
本来我告诉他嵌入如下代码:
clra
pushacc
pushacc
reti
结果他却玩了前面哪一段,而数组rst[]中的内容恰恰是上面的汇编机器码,他的做法是将
rst数组的数据当作代码保存,然后采用绝对地址方式指向该数组,将该数组中的代码当作
函数来运行。居然通过了!
我觉得有问题,我说即使如此,那绝对地址调用也应该写成(*((void(*)())(rst)))()
才对呀,结果他反驳说,那样的话,rst的地址就会当成参数传递给这个绝对地址函数,而
实际LJMP调用的地址并非rst的地址,而是一个不确定的地址。于是我按照自己的说法尝试
了一下,看看汇编结果,还真的是将rst的地址传递给了R1R2,而绝对函数最终LJMP到了
一个莫名其妙的地址上去了,死翘!
看来C真是一匹不容易驾驭的野马,这个大三学生理解力在我之上,我30多岁的人了,干了
这么多年还没他的境界呢,唉,人家才学了几天啊,翻了几天书就这么厉害了,服了!
首先分析帖子的C语言代码
第一句定义一个数组rst[],数组内数据就是完成复位功能的汇编机器码,具体对应关系
为:clra==0xe4、pushacc==0xc0,0xe0、reti==0x32
第二句是一个函数指针的用法,函数指针用法稍微有点复杂,可参看本人著的书,:),以
下为快速入门讲解。
定义一个返回值是空函数指针的定义形式如下:
void(*p)()
当把函数指针赋值后,就能通过函数指针调用函数,调用形式如下,
(*p)();
或等价的简化形式:
p();
假设rst就是函数指针,则如下调用形式就可以令单片机复位再起。
(*rst)();
但可惜,rst不是函数指针,而是数组名,虽然两者都是地址,但不可直接调用数组名。
如同把char型变量a赋值给int型变量b,(int)表示强制类型转换:
b=(int)a
函数指针的强制类型转换公式如下(C语言的哲学是定义形式和使用一致):
((void(*)())rst
这样经过转换后的rst就可以当作函数指针使用了,简单的调用形式如下:
#defineK((void(*)())rst
(*K)()
或:
(*(void(*)())rst)();
评论