MCS-51反汇编程序的解读技巧

🏠 首页 《无线电》杂志 2005年 🔗 第3期 🔗 第38页 分类:电脑·单片机·通信 🔗 刘明德 🔗, 肖文兵 🔗

如何解读反汇编出来的MCS-51系列单片机程序呢?以下是笔者在实践中总结的一些解读技巧。

一、区分主程序与子程序及中断服务程序


1. 找出中断服务程序

51系列单片机程序地址0003H、000BH、0013H、001BH、0023H为中断入口地址,除非中断程序非常短,能够在这有限的几个地址空间内放下,否则常见的是分别放置一条跳转指令,指向对应的中断服务程序。通过跳转指令就可找出中断服务程序的起始地址。

另外,常见的中断服务程序还有一个明显特征: 入口处是连续几句压栈语句PUSH以保护现场,在中断返回语句前是与压栈语句对应逆顺序的出栈语句POP以恢复现场。


2. 找出子程序

所有子程序都是通过调用语句(包括长调用语句LCALL和短调用语句ACALL)来实现对子程序的连接。把所有调用语句所指的地址都找出来,这些地址就是子程序的入口地址,也就是子程序的起始点。所有的子程序都有返回语句RET。与中断服务程序相似,RET之后的程序也可能是该子程序的组成部分,也有可能一个子程序有多条返回语句,判断方法是跟踪跳转语句。


3. 主程序段的分析

51系列单片机程序执行的起始地址为0000H,常见的是第一条指令就是跳转指令,它指向主程序段起始地址。除非所有中断都不用,主程序可从0000H地址一直往下连续编写。不过,这种方法不可取,因为节约这少量的空间没多大价值,还加大了出错的概率。

主程序的特点是无限循环等待。循环体内往往会使用查询语句,有的检查是否有键盘按下,有的检查输入端口的信号等。也有的主程序很简单,循环体内就根本没有查询语句,在这种情况下,一定会使用中断。当中断响应后先执行中断服务程序,直到中断服务程序运行完毕,返回到原中断点下一语句继续执行。当然,较多见的情况是既有查询,又有中断。

二、分析散转语句

散转语句在许多MCS-51系统中使用,通常在有键盘或有传感器阵列的系统中较为常见。散转语句就只有一条:

JMP @A+DPTR

在编辑软件中很容易将其找出。在散转语句前面几句语句中一般能找到

MOV DPTR, #XXXXH

其中XXXX就是散转语句所指向的首地址。一般主程序中常能见到散转语句。

三、分析查表语句

查表语句也只有一条:

MOVC A, @A+DPTR

它是一条常被用来进行数据代码转换的传数语句。查表语句在显示或打印程序中较为常见,所以在分析该部分程序时可结合分析显示和打印电路来进行判断。当你知道了程序的用途时,分析起来就容易多了。

在查表语句的前面很容易找到DPTR的值,该值就是定义表的表头地址,但是表尾是没有直接的方法来确定的。那么,我们如何区分哪些是表中数据,哪些又是程序语句呢?主要是通过查找跳转入口地址和子程序入口地址的方法。在所有这些入口地址中,从排在表头后面,且离表头最近的入口地址开始就可能不是表中数据了。

该入口地址是否仅仅是从表头到该入口之间的代码反汇编成的语句跳转或调用子程序产生的?如果不是,则该入口地址的前一个地址就是表尾,即表头到表尾之间的代码就不能反汇编成执行语句了;如果是,就是假入口,仍需继续向下查找,直到找到真正的表尾为止。下面是一段错误的反汇编程序:

F580 90F5A8 MOV DPTR, #0F5A8H

F583 E6 MOV A, @R0

F584 93 MOVC A, @A+DPTR

…………………………

F5AA 02F5B1 LJMP 0F5B1H

…………………………

F5B1 27 ADD A, @R1

…………………………

F5C2 C0E0 PUSH ACC

…………………………

F5DA D0E0 POP ACC

F5DC 32 RETI

…………………………

从F5AA地址处反汇编出来的命令产生了一个假入口F5B1,而其他程序里都未用该入口。所以要继续向下查找入口地址,而F5C2是一中断服务程序的入口地址,即地址F5C1才是该表的表尾。

文/刘明德 肖文兵