从单片机指针说到黑客程序

发布者:superstar10最新更新时间:2015-01-20 来源: laogu关键字:单片机  指针  黑客程序 手机看文章 扫描二维码
随时随地手机看文章
2004年7月的一天,在电子BBS讨论区上溜达,看到一个有趣的帖子,整个帖子内容如下:

纯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   )    ) ( );

[page]

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地址开始执行而已,寄存器不会变为确定的复位值。

如果用户要编程实现上电复位这种情况,在程序中不要踢看门狗即可。大部分单片机都有
看门狗吧。



l         附录

笔者精于DSP C24xx,但不太懂C51;读者应能从函数指针的定义和引用中看出来,C语言的
设计哲学是使用形式和定义形式一致,虽然这一点饱受质疑。

如果你觉得鸡蛋好吃时,不必认识那只母鸡;但如果你觉得本文不错,请来笔者网站坐坐
吧www.1piao.com/wlg.asp。

2004年7月看到这个有意思的帖子,也干了一件蠢事——买了飞利浦的一款拍照手机,屏幕
有强烈闪烁感,飞利浦拒换,服务意识真是不敢恭维。

可来信免费转载本文,请保持整篇文章的完整性,包括本句。 


----------------2---------------


汇编中的ORG 0X0000H 在C51中如何实现.
一般是在连接定位模块中来进行地址分配
1、选择"options fo target   "
2、选择“BL51 Locate”
3、在code 栏填入   ?PR?MAIN?SS(0x800)

其中MAIN是你要定位的函数名,SS是函数所在的文件名,要是有多个函数需要定位,则在中间加
逗号。



功能强大的时钟中断
  在单片机程序设计中,设置一个好的时钟中断,将能使一个CPU发挥两个CPU的功效,大大方
便和简化程序的编制,提高系统的效率与可操作性。我们可以把一些例行的及需要定时执行的程
序放在时钟中断中,还可以利用时钟中断协助主程序完成定时、延时等操作。
  下面以6MHz时钟的AT89C51系统为例,说明时钟中断的应用。
  定时器初值与中断周期 时钟中断无需过于频繁,一般取20mS(50Hz)即可。如需要百分之一
秒的时基信号,可取10mS(100Hz)。这里取20mS,用定时器T0工作于16位定时器方式(方式1)。
T0的工作方式为:每过一个机器周期自动加1,当计满0FFFFh,要溢出时,便会产生中断,并由
硬件设置相应的标志位供软件查询。即中断时比启动时经过了N+1个机器周期。所以,我们只要
在T0中预先存入一个比满值0FFFFh小N的数,然后启动定时器,便会在N个机器周期后产生中断。
这个值便是所谓的“初值”。下面计算我们需要的初值:时钟为6MHz,12个时钟周期为一个机器
周期,20mS中有10000个机器周期。(10000)10=(2710)16,0FFFFh-2710h+1=0D8F0h。由于响应
中断、保护现场及重装初值还需要7~8个机器周期,把这个值再加上7,即T0应装入的初值是
0D8F7h。每次中断进入后,先把A及PSW的值压入堆
栈,然后即把0D8F7h装入T0。
  设置一个单元,每次中断加1 我们可以取内部RAM中一个单元,取名为INCPI(Increase 
Per Interrupt),在中断中,装完T0初值后,用INC INCPI指令将其加一。从这个单元中,无
论中断程序还是主程序,都可以从中获得20mS的1~256之间任意整数倍的信号。例如:有一段向
数码管送显的程序,需要每0.5秒执行一次以便刷新显示器,便可以设一单元(称为等待单元)
W_DISP,用/MOV A,INCPI/ADD A,#25/MOV W_DISP,A/语句让其比当前的INCPI值大25,然后在
每次中断中检查是否于INCPI值相等。若相等,说明已过了25个中断周期,便执行送显程序,并
且让W_DISP再加上25,等待下个0.5秒。我们可以设置多个等待单元,以便取出多个不同的时基
信号。让中断程序在每次中断时依次查询各个等待单元是否与INCPI相等,若相等,则执行相应
的处理,并重新设置该等待单元的值,否则跳过。例如:用0.5秒信号刷新或闪烁显示器,用1秒
信号产生实时时钟,或输出一定频率的方波,以一定间隔查询输入设备等。
  在中断中读键 通常,我们在主程序中读键盘,步骤为:扫描键盘,若有键按下,则延时几
十毫秒去抖动,再次确认此键确实按下,然后处理该键对应的工作,完成后再次重上述步骤。但
这有两点不足:1.处理相应工作时无法锁存按键的输入,即可能漏键。2.延时去抖时CPU无法做
其它事情,效率不高。如果把读键放入时钟中断中,则可避免上述不足。方法为:如果两次相邻
的中断中都读到同一个键按下,则这个键是有效的(达到了去抖目的),并将其锁存到先入先出
(队列)的键盘缓冲区,等主程序来处理。这样,主程序处理按键的同时,仍可响应键盘的输入。
缓冲区深度通常可设为8级,若锁存的键数多于8个,则忽略新的按键,并报警提示用户新的按键
将无效。若键盘缓冲队列停滞的时间大大长于主程序处理按键所需要的最大时间,说明主程序已
出错或跑飞,可以在中断用指令将系统复位,起到了看门狗的目的。  
    主程序中的延时 由于有常开的时钟中断,所以当主程序中有需要时间较短、精度较高的延
时时,应暂时把时钟中断关闭。而程序中需要时间较长、精度不高的延时时,便可仿照下需的写
法,避免多层嵌套的循环延时。
  例:在P1.1输出1秒的高电平脉冲
    MOV    A,INCPI
    INC    A
    CJNE    A,INCPI$    ;等待一次中断处理完成
    SETB    P1.1        ;设P1.1为H,脉冲开始
    ADD    A,#50        ;50个20mS为1秒
    CJNE    A,INCPI,$    ;等中断将INCPI加一50次
    CLR    P1.1        ;设P1.1为L,脉冲结束
  结束语:从上看出,要灵活地应用时钟中断,将任务合理分配给中断和主程序,并且二者要
分工明确,接口简单。这其中的技巧还需要大家在实践中多多摸索与体会。另外要注意:应尽量
缩短中断处理程序的执行时间,更不要长于20mS。
关键字:单片机  指针  黑客程序 引用地址:从单片机指针说到黑客程序

上一篇:一种新型光电定向系统的设计与实现
下一篇:C语言中i++与++i的区别

推荐阅读最新更新时间:2024-03-16 13:51

小尺寸单片机C8051在便携式设备中的应用
引 言 手机在现代生活中的使用越来越广,其功能也是越来越多,如现在有很多手机都带有MP3及照相功能,有的还具有闪信和计步器功能。手机闪信需要处理器能完成多路模拟输入、数据的实时处理等,原有的手机很难直接实现这些功能,就需要MCU配合完成其功能。 PMP等便携式设备大都带有彩色的TFT屏,而传统的驱动是由白色LED完成的,但其存在色差;现在大都采用RGB三色LED来背光,同时需要检测背光的效果,克服LED亮度变暗的问题。MCU可以协助主处理器完成这些功能,达到很好的彩色TFT屏的背光效果。 便携式设备往往由多个公司共同提供模块,需要MCU有好的保密功能。因此便携式设备对MCU的要求,大都需要小尺寸,低功耗,实时快速
[单片机]
小尺寸<font color='red'>单片机</font>C8051在便携式设备中的应用
如何用指针式万用表测量直流电流
作为入门者,正确使用是最基本的技能,本文主要讲解如何用指针式万用表测量直流电流。 第一步:测量时转动开关至所需电流挡,测试笔应串接于被测电路中。 挡位的选择应使指针位于满刻度的2/3处,测量精度最高。如果不知道被测电流的范围,可先用较大的量程试测出大致数值后,再转到相应量程测量。 第二步:测量5a时,红表笔插头则插到对应的插座中。 第三步:测量5a时,转动开关可放在500ma直流电流量程上。 注意:测量时红表笔要接高电位点;严禁用电流挡去测量电压;转换量程必须先将表笔从被测电路中断开。
[测试测量]
如何用<font color='red'>指针</font>式万用表测量直流电流
51单片机DHT11温湿度检测手机蓝牙APP显示设计
今天给大家介绍的是一个温湿度检测设计,基于51单片机、蓝牙模块、温湿度传感器、Android APP完成。首先先展示一下设计好的实物,接下来将从系统方案、硬件设计、软件设计这三个方面来阐述。 1.系统方案 先来看一下整体的架构图:硬件部分由STC89C52单片机、DHT11温湿度传感器、BT08蓝牙串口模块和Android手机组成。传感器将采集到的温湿度数据传送给单片机,然后单片机通过蓝牙串口模块将数据发送到手机APP,从而将温湿度在APP显示出来。在APP上可以设置温湿度告警的阈值,超过阈值将显示“偏高”或者“偏低”的相关信息。 2.硬件设计 整个设计的原理图如下所示,由单片机最小系统、蓝牙串口模块、温湿度传感器组
[单片机]
51<font color='red'>单片机</font>DHT11温湿度检测手机蓝牙APP显示设计
RUPI-44系列单片机与051单片机在内部结构上有什么区别?
RUPI-44系列单片机中的CPU与8051基本相同,其指令系统、各口的操作、片内EPROM编程,以及为操作等均与8051相同。 它们的差异主要区别在: 1、RUPI-44系列单片机用SIU取代8051的串行口,并增加了一些SIU专用寄存器。 SIU发送和接收的数据自或送至内部双口RAM。这种双口ROM既可以由CPU访问,又可以由SIU访问。 2、有5个引脚具有特殊定义。 3、RUP1-44系列单片机的内部RAM有192个字节,而8051只有128个字节
[单片机]
单片机片外程序存储器数据存储器操作命令分析
单片机 片外程序 存储器 数据存储器操作命令与通常所说的存储器不同,和I2C总线的AT24C02不同,SPI协议的也不同,是指采用专用接口 电路 ,应用P0口P2口地址总线和控制线的“三总线”方式访问的。关于编程的时候,和访问内部程序存储器,数据存储器不同是:1对外部程序存储器,和内部一样,程序不用改。2,.对片外的数据存储器,汇编要用MOVX DPTR 什么的,我也不懂,C语言相关的部分比如:变量关键字:pdata xdata 是片外数据存储器类型。输送的片外数据的寄存器地址也要按实际输送,其他没什么区别。没有说要特意操作特殊寄存器。. 在设计片外程序存储器之前,首先要决定EA引脚的 电平 。 EA=0,单片机只访问
[单片机]
AVR单片机开发工具介绍
AVR 开发工具介绍 要开发AVR系统,编写AVR程序,你需要有软 件环境 【ICC+AVRstudio环境配置】,也需要有硬件环境,本文介绍硬件环境的选择与入门芯片的配备。 硬件环境:主要是有基本系统『最小系统』,编程器,仿真器,下面就这三方面做一些介绍。 推荐的工具: JTAG 仿真器 使用 AVR Studio 打开 *.cof 或 *.elf 仿真文件后,就能进行仿真操作。方便开发时测试与调试。 支持仿真的芯片:ATmega16、ATmega32、ATmega64、ATmega128、ATmega323、ATmega162 、ATmega165,但是这款官方的MKii 价格不菲,2380元每台。 兼容产
[单片机]
AVR<font color='red'>单片机</font>开发工具介绍
C指针+ STM32 理解
环境:IAR + Cortex-M3的处理器 关注:指针在寄存器层次上的存储、调用等。。。 推荐:让你不再害怕指针 存储: 示例代码如下: int yyy=16; int *ptr1 = int **ptr2 = &ptr1; int (*ptr3) ; int *(*ptr4) ; int main() { ................ //使用这几个变量 ................. return 0; } IAR--View--Statics显示的全局区(静态区)情况: 以ptr2来说,定义:int **ptr2 = &ptr1; 从上图可知,指针变量ptr2的类型,
[单片机]
C<font color='red'>指针</font>+ STM32 理解
如何创建51单片机KEIL工程步骤
1. 什么是Keil软件 Keil软件是一款专为嵌入式系统开发而设计的集成开发环境(IDE),常用于51、STM32单片机软件开发的编程软件。Keil编程软件不仅支持多种工具和扩展程序,还能够处理多种文件格式和数据交换方式;可支持单片机程序的在线仿真,或通过仿真器进行实物仿真,大大方便开发人员的工作。 其中,我们常用的Keil软件有两种,分别为Keil C51以及Keil MDK,前者主要用于51单片机等8051内核单片机的开发工具(不支持32位单片机),Keil MDK主要用于ARM架构单片机的开发工具,主要用于STM32单片机等32单片机。所以在使用Keil软件时需要主要这一点。 2.如何创建51单片机KEIL工程步骤
[单片机]
如何创建51<font color='red'>单片机</font>KEIL工程步骤
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved