来自:http://www.51hei.com/mcu/634.html

从单片机指针说到黑客程序
纯C51复位功能函数:一个大三学生,让人又爱又怕
现单列复位部分如下:

main()
{
unsigned char code rst[]={0xe4,0xc0,0xe0,0xc0,0xe0,0x32}; // 复位代码
(*((void (*)())(rst)))(); // 执行上一行代码,将rst数组当函数调用
}

本来我告诉他嵌入如下代码:
clr a
push acc
push acc
reti

结果他却玩了前面哪一段,而数组rst[]中的内容恰恰是上面的汇编机器码,他的做法是将
rst数组的数据当作代码保存,然后采用绝对地址方式指向该数组,将该数组中的代码当作
函数来运行。居然通过了!

我觉得有问题,我说即使如此,那绝对地址调用也应该写成(*((void (*)())(&rst)))() 
才对呀,结果他反驳说,那样的话,rst的地址就会当成参数传递给这个绝对地址函数,而
实际LJMP调用的地址并非rst的地址,而是一个不确定的地址。于是我按照自己的说法尝试
了一下,看看汇编结果,还真的是将rst的地址传递给了R1 R2,而绝对函数最终LJMP到了
一个莫名其妙的地址上去了,死翘!

看来C真是一匹不容易驾驭的野马,这个大三学生理解力在我之上,我30多岁的人了,干了
这么多年还没他的境界呢,唉,人家才学了几天啊,翻了几天书就这么厉害了,服了!

l 首先分析帖子的C语言代码
第一句定义一个数组rst[],数组内数据就是完成复位功能的汇编机器码,具体对应关系
为:clr a == 0xe4、push acc == 0xc0,0xe0、reti ==0x32
第二句是一个函数指针的用法,函数指针用法稍微有点复杂,可参看本人著的书,:),以
下为快速入门讲解。
定义一个返回值是空函数指针的定义形式如下:
void (*p) ( )
当把函数指针赋值后,就能通过函数指针调用函数,调用形式如下,
(*p) ( );
或等价的简化形式:
p ( );
假设rst就是函数指针,则如下调用形式就可以令单片机复位再起。
(*rst ) ( ); 
但可惜,rst不是函数指针,而是数组名,虽然两者都是地址,但不可直接调用数组名。
如同把char型变量a赋值给int型变量b,(int) 表示强制类型转换:
b = (int) a
函数指针的强制类型转换公式如下(C语言的哲学是定义形式和使用一致):
( (void (*)() ) rst 
这样经过转换后的rst就可以当作函数指针使用了,简单的调用形式如下:
#define K ( (void (*)( ) ) rst
(*K) ( )
或:
( * ( void (*)( ) )rst ) ( );
这样的语句就完成复位再启功能了。类型转换符()的优先级跟指针运算符*的优先级相同,
二者的结合方向是自右至左,所以上述语句就能完成复位功能了。保险起见有些程序员常
常喜欢再加个括号:
#define K ( ( (void (*)( ) ) rst )
(*K) ( )

( *( ( void (*)( ) )rst ) ) ( );
由于没有输入参数,上述复位代码更严谨的写法是: 
#define K ( ( (void (*)(void ) ) rst )
(*K) ( )

( *( ( void (*)(void ) )rst ) ) ( );
l 关于帖子作者的解释
千万不要犯“&rst”形式的错误,对于一维数组而言,数组名rst就代表地址。以下二者等
价,更常用的是等式左边的形式:
rst == &rst[0]
整个函数指针无所谓参数传递,只是把rst当作程序执行地址调用而已,那个学生的解释也
有问题。
还有一点必须提及,不是说能通过编译,甚至生成正确代码,就表示某语句一定是对的。
对很复杂的语句,要考虑到编译器不严格甚至出错的可能性。
l 哈佛结构和一个蠕虫病毒
请注意,定义数组rst[]时用了关键字code,这是C51特有的关键字,意味着把数组定义到
程序空间。标准C是没有关键字code的。
哈佛结构和普林斯顿结构:
哈佛结构——程序空间和存储空间分开的。C51算是不太严格的哈佛结构——虽地址线分
开,但数据线没有分开。DSP是增强的哈佛结构。
PC电脑上奔腾CPU是普林斯顿结构——数据空间和程序空间统一编址。
如果数组rst[]数据的汇编机器码是删除文件的机器码,这算不算是病毒?
曾经流行过一种蠕虫病毒,其发作机理采取的就是将恶意代码保存成文本文件,然后通过
指针调用执行这个文本,很多杀毒程序也不会查询文本文件。
程序也罢,数据也罢都是二进制形式,如果数据空间和程序空间是统一编码的, 数据当然
可以当作程序运行。
在这一点上,相对而言,哈佛结构的CPU安全性会好一点点。但嵌入式应用少有病毒,一般
不用关心。
l 单片机复位的更好方法
帖子中汇编语言解释如下:
clr a //清除ACC=0
push acc //压0到堆栈——8位
push acc //再压0到堆栈——再8位
reti //返回到0地址,从而执行。
帖子作者的这种复位方法比较麻烦,更加简单的复位写法是(摘自《C缺陷与陷阱》):
( * ( void (*)( ) )0 ) ( );
本句的分析方法同上,但更加精炼,没有多余的汇编语句。
上述复位的方法可称为软件复位。
软件复位跟真正上电复位有很大差别:上电复位时大部分寄存器都有确定的复位值;软件复位则只相当于从0地址开始执行而已,寄存器不会变为确定的复位值。
如果用户要编程实现上电复位这种情况,在程序中不要踢看门狗即可。大部分单片机都有看门狗吧。

 

转载于:https://www.cnblogs.com/juju/archive/2012/04/18/2455883.html

转帖:从C51的指针到病毒-c51软复位,经典,分析透彻相关推荐

  1. c51单片机c语言程序,C51单片机的C语言程序设计.ppt

    <C51单片机的C语言程序设计.ppt>由会员分享,可在线阅读,更多相关<C51单片机的C语言程序设计.ppt(44页珍藏版)>请在人人文库网上搜索. 1.2020/8/7,1 ...

  2. 根据c51程序改写汇编语言,Keil C51编译及连接技术

    主要介绍Keil C51的预处理方法如宏定义.常用的预处理指令及文件包含指令,C51编译库的选择及代码优化原理,C51与汇编混合编程的方法与实现以及超过64KB空间的地址分页方法的C51实现. 教学目 ...

  3. [实用技巧] (转帖)关于MyDocument.exe -- 打印店病毒

    该病毒的理念非常强大,在各个大学复印店屡禁不止--因为小白太多了. ※※※作用效果※※※: 1.在电脑中运行之后,始终存在于系统后台.把所有插入电脑的U盘和移动硬盘等外部存储设备中都复制一份自身MyD ...

  4. C51语言支持哪些数据类型,C51编译器支持的数据类型(1)

    1.1 C-51 编译器支持下列数据类型: 数 据 类 型 长 度 值 域 bit 1 字节 0 或 1 signed char 1 字节 -128-+127 unsigned char 1 字节 0 ...

  5. 单片机c51语言定义bool类型,C51单片机数据类型的具体定义及应用

    描述 先来简单说说C语言的标识符和关键字.标识符是用来标识源程序中某个对象的名字的,这些对象可以是语句.数据类型.函数.变量.数组等等.C语言是大小字敏感的一种高级语言,如果我们要定义一个定时器1,可 ...

  6. c51语言开发工具,KEIL C51 开发工具

    产业标准的Keil C编译器.宏汇编器.调试器.实时内核.单板计算机和仿真器,支持所有的8051系列微控制器,帮助你如期完成项目进度. 当启动一个新的项目,你只需从设备数据库选择使用的微控制器,μVi ...

  7. 简述单片机c51语言程序结构,单片机C51程序结构

    <单片机C51程序结构>由会员分享,可在线阅读,更多相关<单片机C51程序结构(14页珍藏版)>请在人人文库网上搜索. 1.1 C51程序流程与控制C语言是一种结构化的编程语言 ...

  8. 【C 语言】数组作为参数退化为指针问题 ( 问题描述 | 从编译器角度分析该问题 | 出于提高 C 语言执行效率角度考虑 | 数组作为参数的推荐方案 )

    文章目录 一.问题描述 二.从编译器角度分析该问题 三.数组作为参数的推荐方案 一.问题描述 将 数组 作为 函数参数 , 传递时会 退化为指针 ; 数组的首地址 , 变为指针地址 , 函数中无法判定 ...

  9. 管家病毒查杀模块逆向分析

    本文研究的是*管家2.8-3.6版本的杀毒模块功能实现.众所周知,杀毒软件查杀病毒分为主动查杀和被动查杀两种方式.*管家的主动查杀包括快速查收和全盘查杀,而快速查杀和全盘查杀都使用了本地查杀技术和云查 ...

最新文章

  1. 每位开发人员都应铭记的10句编程谚语 (我超喜欢,转载了)
  2. FSWD_2_JavaScript
  3. 语义分割--Loss Max-Pooling for Semantic Image Segmentation
  4. Fiddler 发送post 请求失败
  5. 【剑指offer-Java版】30最小的K个数
  6. [转载]项目风险管理七种武器-孔雀翎
  7. mabatisplus怎么给实体类自定义属性_如果你的角色属性可以自定义,你会怎么点?...
  8. 求职过程记录(5)——黎明到来
  9. 健忘族的大爱,机器人管家Watch Bot提醒你不要丢三落四
  10. 文本聊天室(TCP-中)
  11. android jni fork()子进程不运行_Android高级面试谈谈Zygote的理解
  12. HttpWebRequest中GetResponse或者说GetRequestStream偶尔超时,或者是各种操作超时造成的假死的一些解决方案...
  13. ubuntu目录结构
  14. ​「5G消息」的最新消息
  15. 概率论与数理统计基础概念整理
  16. 怎么在计算机网络上添加文件,教你win7如何设置网络共享文件夹
  17. 记一次Linux文件系统引发的项目启动错误(war包没有问题只有指定目录启动报错)
  18. 蓝牙5.2协议、主从一体、低功耗、工业级蓝牙模组BLE105新品上市
  19. 常用政务网络查询单打印地址
  20. ERP、MES(作用、功能、部署、相关模块)

热门文章

  1. 听说微软出了个 Windows XP reStart Edition? 重启版?
  2. Pycharm如何设置自定义背景颜色
  3. word打出来的字体总是变宋体
  4. 牛客华为机试第8题python
  5. opencv-python图像处理之磨皮相机
  6. C语言之结构体以及结构体对齐访问
  7. 你真的了解软件测试行业吗?
  8. AVFoundation学习Demo--拍摄视频
  9. Provisioning Services 7.6 入门到精通系列之九:创建和配置目标设备
  10. “中序表达式”转“后续表达式”