用于嵌入式模块中汇编程序的自动查错改错方法和系统 [技术领域]
本发明涉及一种用于嵌入式模块中汇编源程序的自动查错改错方法和系统,特别涉及对汇编源程序中的页错误进行自动查错改错的方法和系统。
[背景技术]
当前,家电行业和通讯行业中的大多数产品都要用到嵌入式模块系统。随着微电子技术的飞速发展,CPU已经变成低成本器件。在可能的情况下,各种机电设备已经或者正在嵌入CPU构成的嵌入式模块系统。像数码相机、MP3播放机、PDA、游戏机和移动电话手机等手持设备以及各种信息家电等有更高性能要求的多媒体和通信设备。例如,目前移动电话手机需要多屏显示、网页浏览、文本信息发送、带查找功能的大容量地址簿和语音拨号等功能;最新数码相机及摄像机的高效率数据压缩、自动识别和各种智能处理等,需要增加DSP功能;电话交换机需要分布式处理而采用多处理器结构。像电视机、洗衣机、微波炉、汽车音响及电子玩具等传统产品也要应用到嵌入式模块系统。
嵌入式模块系统的核心是可编程计算部件,即处理器。这可以有很多种选择,而且近几年又增加了一些新的选择:除过去常用的通用处理器GPP(Gereral PurposeProcessor)、嵌入式处理器EP(Embedded Processor)、微控制器MCU(Micro-ControlUnit)、数字信号处理器DSP(Digital Signal Processor)外,目前发展很快、可以给我们提供新的选择的还有各种专用处理器ASP(Application Specific Processor)或专用标准产品ASSP(Application Specific Standard Product)。它们都是针对一些特定应用而设计的,如用于HDTV、ADSL、Cable Modem等地专用处理器。这些处理器的程序或用汇编语言编写,或用高级语言与汇编的混合编写,但是核心部分要用汇编语言编写以提高效率。
对于一些DSP和单片机来说,数据区间和程序区间是分页的(也有称为段的),正如早期PC机,每段内存和数据都是64k字节。不同的是DSP和单片机的一页是64或128或其他2的n次方(n为大于0的正整数)个存储单元。以大家熟悉的TI DSP为例,TI C28XX系列是64字为一页,TI C2XX/C24X/24XX是128字为一页。
图1所示是TI DSP数据存储空间中变量与页的对应关系,其中DP为DSP的页地址,指明当前使用的是数据空间的哪一页,Offset为页内偏移地址。这种结构与常用的PC机相似,不同的是DSP的DP寄存器指明的是页号,绝对地址计算公式为:DP页寄存器*每页存储单元数+偏移地址;而PC机段寄存器指明的是基地址,绝对地址计算公式为:段地址*16+偏移地址。
从图中容易看出页地址与页内存储单元的关系为1对多,即一个页对应n个存储单元,n为2的k次方(K为>0的正整数)。由于在DSP数据空间中,每个页内都可能会有若干个保留单元,比如m个,所以每个页地址实际对应n-m个存储单元。编写汇编程序时,编程者往往会用到很多分布在不同页内的变量,而这些变量的页内偏移地址可能是相同的,在程序运行中,操作不同的变量时要指明它属于哪一页才能正确使用。由于变量比较多,在编写过程中,编程员很可能会忘记切换页的情况而导致出错,造成读取或存储数据出错,进而导致判断出错或产生非法的地址操作,严重的还会导致系统崩溃或系统功能严重紊乱,不能实现程序的既定任务等。如果问题严重,批量生产的后果将不堪设想。因此人们希望能在开发阶段就找出这样的错误。
目前的查错方法一般是使用人工检查,但是人工检查往往费时费力,并且事倍功半,因为即使稍微复杂的系统,程序量也往往会达到上万行、十几万甚至几十万行,人工检查的难度之大可想而知。
[发明内容]
本发明提供了一种用于嵌入式模块中汇编程序的自动查错改错方法和系统,可以自动检查到汇编源程序中的页地址错误及无用代码,还可以实现自动纠正页错误以及删除无效代码。
本发明解决其技术问题所采用的技术方案是:一种用于嵌入式模块中汇编程序的自动查错方法,包括以下步骤:
101,读取并分析汇编源程序Y,根据特定芯片的语法及其指令得到所述汇编源程序Y使用到的全部变量,再生成所述变量和与其一一对应的页地址的关系列表A;
102,将所述汇编源程序Y进行预处理,规范汇编源程序Y,使形成一个易于识别和检查的汇编源程序B;
103,对所述汇编源程序B进行页切换正确性检查,发现并报告页错误。
步骤102中,所述预处理包括步骤:
201,读取汇编源程序Y;
202,删除汇编源程序Y中的注释、无用伪指令、加入行号位置信息,以建立与汇编源程序Y代码行的对应关系,以方便在发现页地址错误时准确定位出错的位置;
203,对汇编源程序Y进行编译,将汇编源程序Y中的宏进行代码替代,在每个子程序及函数调用下面插入一个构造标号,生成汇编源程序Y纯代码形式的汇编源程序B。
步骤103中,以顺序结构和跳转分支结构对所述汇编源程序B进行页切换正确性检查。
步骤103中,先以顺序结构对所述汇编源程序B进行页切换正确性检查,再以跳转分支结构对所述汇编源程序B进行页切换正确性检查。
所述以顺序结构对所述汇编源程序B进行页切换正确性检查的方法是:
501,从所述汇编源程序B开始处开始检查;
502,置首次进入子程序或函数的标记为F;
503,顺序读取汇编源程序B中的一条指令;
504,如果读取的指令是变量操作指令,执行步骤505,否则执行步骤506;
505,如果有标记F,则将当前页地址设为指令中的页地址,然后清除标记F,执行步骤503;如果没有标记F,将当前页地址与所述操作变量的页地址进行比较,如果相同则不存在页地址错误,执行步骤503,如果不相同,则标记该处存在页错误,并将当前页地址更新为所述操作变量的页地址,然后执行步骤503;
506,如果读取的指令是页切换指令,将当前页地址设为指令中的页地址,同时清标记F(即给F标记赋零值),然后执行步骤503;
507,如果读取的指令是绝对跳转或子程序或函数调用或函数及子程序返回指令,则执行步骤502,否则执行步骤503;
508,如果读取的指令不是上述所列的指令,则丢弃,执行步骤503。
所述以跳转分支结构对所述汇编源程序B进行页切换正确性检查的方法是:
601,将以顺序结构检查完得到的所有标号集合,组成集合E,包括每个标号的标号名称和其在汇编源程序B或汇编源程序Y中的位置;
602,找出所述集合E中每个标号的跳入或直接进入时的全部页地址及子程序、函数的出口页地址;
603,找到所述集合E中每个标号的所有该标号后第一个变量操作指令的页地址或第一个页切换的页地址,即标号出口页地址信息;
604,根据前面的标号入口、出口页地址,将所述集合E中出口页地址群组进行循环替换,得到所有子程序或函数的入口页地址、出口页地址;
605,将所有子程序及函数调用处的构造标号的入口地址替换为该构造标号前的子程序(或函数)的入口页地址、出口页地址;
606,比较所述集合E中所有标号(包含构造标号)的入口地址及出口地址,判断是否存在页地址错误;
607,将顺序结构检查及跳转分支结构检查中标记有错误的地方对照汇编源程序Y找出具体出错位置,然后生成一个页错误报告。
步骤602中找出所述集合E中每个标号的跳入或直接进入时的全部页地址及子程序、函数的出口页地址的方法是:
701,从所述汇编源程序B开始处读取;
702,置首次进入子程序或函数的标记为标记F,置标记F为刚有效标志G;
703,执行下面704到710直到汇编源程序B结束,汇编源程序B结束则执行步骤711,否则执行步骤704;
704,顺序读取汇编源程序B中一条指令;
705,如果读取的指令为变量操作指令,执行步骤706,否则执行步骤707;
706,如果有标记F,将当前页地址设为指令中的页地址,然后清除标记F,执行步骤704;如果没有标记F,直接执行步骤704;
707,如果读取指令为页切换指令,将当前页地址设为指令中的页地址,清除标记F,然后执行步骤704,否则执行步骤708;
708,如果读取指令是跳转或子程序或函数调用,则这些指令中必有一个标号,如果标记F为清除,则将当前页地址记录到标号集合E中,执行步骤709,如果标记F为置位并且标记G为清除,则将当前页地址记录到标号集合E中,执行步骤709,如果标记F为置位并且标记G为置位,则直接执行步骤709;如果读取指令不是跳转或子程序或函数调用则直接执行步骤709;
709,如果读取指令是绝对跳转或子程序或函数调用或函数及子程序返回指令,则置首次进入子程序或函数的标记为标记F,置标记F为刚有效标志G;继续判断,如果读取指令为函数及子程序返回指令,记录当前页地址为正在检查的子程序的出口页地址,执行步骤704;否则如果读取指令不是绝对跳转或子程序或函数调用或函数及子程序返回指令,执行步骤710;
710,如果读取的指令是标号,且标记F为清除状态,则也将当前页地址记录到标号集合E中;如果读取的指令是标号且标记F为置位,并且标记G为置位,则记录该刚读取的标号为子程序或函数入口标号,记录“是子程序信息”到集合E中,并记录当前页为该标号,然后清除标记G,执行步骤704;如果读取的指令是标号且标记F为置位,并且标记G为清除状态,则将当前页地址记录到标号集合E中;否则如果读取的是其他指令执行步骤704。
711,检查标号集合E中每一标号,将跳入标号页地址中的标号(步骤708,710执行过程中产生的)进行迭代,直到所有标号处理完毕,替换为具体数值的页地址为止。
步骤603中,找到所述集合E中每个标号的所有该标号后第一个变量操作指令页地址或第一个页切换的页地址,即标号出口页地址信息的方法是:
801,从所述汇编源程序B开始处开始;标记L清零。
802,执行步骤803到808直到汇编源程序B结束,如果汇编源程序B结束则执行步骤809,否则执行步骤803;
803,顺序读取汇编源程序B中一条指令;
804,如果读取的指令为标号,则判断标记L是否置位,如果没有置位,则置标记L,表示需要记录标号后首个页地址及页切换情况,并记录该标号在集合E中,执行步骤803。如果读取的指令为标号且已置位标记L,则将刚读取的标号记录到集合E中,记录该刚读取的标号在汇编源程序中的位置,并将刚读取的标号在集合E中的位置更新,执行步骤803;
805,如果读取指令为变量操作指令,当前页地址设为指令中的页地址,如果标记L为置位则记录当前页地址到集合E中,并记录无页切换指令信息到集合E中,记录该刚读取的变量操作指令在汇编源程序中的位置,清L标记,执行步骤803,如果L标记没有置位则执行步骤803,否则执行步骤806。
806,如果读取指令为页切换指令,将当前页地址设为指令中的页地址,如果标记L为置位则记录当前页地址到集合E中,并记录有页切换指令信息到刚记录的当前页地址的相关信息中,记录该刚读取的页切换指令在汇编源程序中的位置,清标记L,然后执行步骤803,如果标记L没有置位则执行步骤803,否则执行步骤807;
807,如果读取指令是跳转或子程序或函数调用,则这些指令中必有一个标号K,如果L标记为置位则将标号K记录到集合E中,执行步骤808,如果标记L没有置位则执行步骤803;否则如果读取的指令是子程序返回或函数返回,清标记L,执行步骤803,如果是其他指令,则执行步骤803;
808,如果读取指令是绝对跳转或子程序或函数调用,则清标记L,执行步骤803,否则执行步骤803。
809,检查标号集合E中每一标号的属性,将集合E中每个标号后首个变量操作或页切换指令所用到的页地址中的标号(步骤804、807执行过程中产生的)进行迭代,直到所有标号处理完毕,替换为具体数值的页地址为止,替换的同时,也要把页地址在汇编源程序Y中的位置一起替换过去,方便后边的自动修改页地址错误的方法的实现。
所述标记L置位表示需要记录标号后首个页地址及页切换情况。
步骤606中,判断是否存在页地址错误的方法是:
901,从所有标号集合E中读取一个标号的入口页地址及出口页地址及标号出口地址是否为页切换指令属性,直到处理完E中每一个标号;
902,判断刚读取的标号的出口页地址是单一的还是多个,如果是单一的,执行步骤903,否则执行步骤905;
903,判断标号出口页地址是否有页切换指令,如果是页切换指令形成的出口页地址,则该标号处没有页地址错误,执行步骤901;否则执行步骤904;
904,判断标号入口页地址是否都相同且与标号出口地址相同,如果相同则该标号处没有页地址错误,执行步骤901,否则标记该标号处存在页地址错误,执行步骤901;
905,判断标号出口页地址都是由页切换指令形成的,如果是则该标号处没有页地址错误,执行步骤901,否则执行步骤906;
906,判断入口页地址是否都相同,如果不都相同,则标记该标号处存在页地址错误,执行步骤901,否则执行步骤907;
907,判断入口页地址与出口页地址是否都相同,如果相同则该标号处没有页地址错误,执行步骤901,否则标记该标号处存在页地址错误,执行步骤901。
所述的一种用于嵌入式模块中汇编程序的自动查错方法的步骤103中,报告完页错误后,在汇编源程序B中对所有标号进行检查:对于每一个标号,如果该标号没有被跳转指令引用并且没有被子程序及函数指令调用,也没有其它指令对该标号进行引用,且其前面指令是绝对跳转指令或处在文件头上或是无条件子程序返回指令或是无条件函数返回指令,则报告此段代码为无效代码。
一种一种用于嵌入式模块中汇编程序的自动改错方法,在进行自动差错后,还进行以下步骤:
1101,顺序从所有标号集合E中读取一个标号的入口页地址及出口页地址及标号出口地址,然后执行步骤1102,直到处理完所有标号集合E中的最后一个标号再执行步骤1108;
1102,判断刚读取的标号的出口页地址是单一的还是多个,如果是单一的,执行步骤1103,否则执行步骤1105;
1103,判断标号出口页地址是否有页切换指令,如果是页切换指令形成的出口页地址,则该标号处没有页地址错误,执行步骤1101;否则执行步骤1104;
1104,判断标号入口页地址是否都相同且与标号出口地址相同,如果相同则该标号处没有页地址错误,执行步骤1101,否则该标号处存在页地址错误,在该标号后加入页地址切换指令予以纠正,加入位置是该标号后每个没有页切换指令的出口页地址在汇编源程序Y代码行中的位置的前面,数值为该出口页地址,然后执行步骤1101;
1105,判断标号出口页地址都是由页切换指令形成的,如果是则该标号处没有页地址错误,执行步骤1101,否则执行步骤1106;
1106,判断入口页地址是否都相同,如果不都相同,则该标号处存在页地址错误,在该标号后加入页地址切换指令予以纠正,加入位置是该标号后每个没有页切换指令的出口页地址在汇编源程序Y代码行中的位置的前面,数值为该出口页地址,执行步骤1101,否则执行步骤1107;
1107,判断入口页地址与出口页地址是否都相同,如果相同则该标号处没有页地址错误,执行步骤1101,否则该标号处存在页地址错误,在该标号后加入页地址切换指令予以纠正,加入位置是该标号后,每个没有页切换指令的出口页地址在汇编源程序Y代码行中的位置的前面,数值为该出口页地址,执行步骤1101;
1108,将汇编源程序Y修改完页地址错误后输出为一个文件,将自动纠错后的结果报告出来。
本发明还提供了一种基于本发明所述方法的系统,包括:
生成页地址关系列表模块,读取并分析汇编源程序Y,根据特定芯片的语法及其指令得到所述汇编源程序Y使用到的全部变量,再生成所述变量和与其一一对应的页地址的关系列表A;
预处理模块,将所述汇编源程序Y进行预处理,规范汇编源程序Y,使形成一个易于识别和检查的汇编源程序B;
页切换检测模块,对所述汇编源程序B进行页切换正确性检查,发现并报告页错误;
自动改错模块,对标定有页错误的地方进行改正,之后输出为一个文件,将自动纠错后的结果报告出来。
还包括无效代码检测模块,在汇编源程序B中对所有标号进行检查,如果为无效代码则在页错误报告中报告无效代码。
本发明的有益效果是:①通过本发明,可以快速准确地检查出汇编源程序中的页地址错误,还可以检查出程序中的无效代码,并进行自动修改,节省了人力,保证开发工作的高效进行。②本发明易于实现,可以在各种现有流行的计算机操作系统(如Windows系列操作系统,Unix,Linux等)上,利用C,C++,VC,VB等程序设计语言实现。③本发明思想适用范围广,可广泛用于所有数据空间或程序空间存在页或段区分的汇编源程序的检错。包括具有页/段特性存储空间的DSP处理器,MCU,MPU等芯片的汇编源程序的页地址错误检查。
[附图说明]
图1是TI DSP数据存储空间上变量与页的对应关系表。
图2是本发明的系统模式图。
图3是本发明整体方案流程图。
图4是本发明方法中所述预处理的流程图。
图5是本发明方法中顺序检查方法的流程图。
图6是本发明方法中跳转分支检查方法的流程图。
图7a扫描汇编源程序B得到每个标号的入口页地址的流程图。
图7b扫描汇编源程序B得到每个标号的入口页地址的流程图。
图8a扫描汇编源程序B得到每一标号出口页地址的流程图。
图8b扫描汇编源程序B得到每一标号出口页地址的流程图。
图9是本发明方法中跳转分支页错误判断流程图。
图10本发明检查无效代码的流程
图11本发明所述一种用于嵌入式模块中汇编程序的自动改错方法的流程图。
[具体实施方式]
下面根据附图和具体实施例对本发明作进一步地阐述。
如图2所示,一种用于嵌入式模块中汇编程序的自动查错改错系统,包括:
生成页地址关系列表模块,读取并分析汇编源程序Y,根据特定芯片的语法及其指令得到所述汇编源程序Y使用到的全部变量,再生成所述变量和与其一一对应的页地址的关系列表A;
预处理模块,将所述汇编源程序Y进行预处理,规范汇编源程序Y,使形成一个易于识别和检查的汇编源程序B;
页切换检测模块,对所述汇编源程序B进行页切换正确性检查,发现并报告页错误;
自动改错模块,对标定有页错误的地方进行改正,之后输出为一个文件,将自动纠错后的结果报告出来。
还包括无效代码检测模块,在汇编源程序B中对所有标号进行检查,如果为无效代码则在页错误报告中报告无效代码。
如图3至图4所示,基于本发明系统的自动查错方法,包括以下步骤:
首先,读取并分析汇编源程序Y,根据特定芯片的语法及其指令得到所述汇编源程序Y使用到的全部变量,生成所述变量和与其一一对应的页地址的关系列表A;
然后,删除汇编源程序Y中的注释、无用伪指令、加入行号位置信息,以建立与汇编源程序Y代码行的对应关系,以方便在发现页地址错误时准确定位出错的位置;对汇编源程序Y进行编译,将汇编源程序Y中的宏进行代码替代,在每个子程序及函数调用下面插入一个构造标号,生成汇编源程序Y纯代码形式的、易于识别和检查的汇编源程序B。
可以将待检测的汇编源程序Y的所有文件合并为一个文件,并删除汇编源程序中的注释,对齐代码,在每行代码前加入该代码行所在合并前文件的编号及在合并前文件中的行位置。合并的目的是方便找到程序使用的所有子程序及函数及所有标号。
最后,先以顺序结构对所述汇编源程序B进行页切换正确性检查,再以跳转分支结构对所述汇编源程序B进行页切换正确性检查,发现并报告页错误。
如图5所示,上述以顺序结构对所述汇编源程序B进行页切换正确性检查的方法是:
首先,从所述汇编源程序B开始处开始检查;置首次进入子程序或函数的标记为F。
然后顺序读取汇编源程序B中的一条指令。如果读取的指令是变量操作指令,则判断是否有标记F,否则判断是否是页切换指令。如果有标记F,则将当前页地址设为指令中的页地址,然后清除标记F,顺序读取汇编源程序B中的下一条指令;如果没有标记F,将当前页地址与所述操作变量的页地址进行比较,如果相同则不存在页地址错误,顺序读取汇编源程序B中的下一条指令,如果不相同,则标记该处存在页错误,并将当前页地址更新为所述操作变量的页地址,然后顺序读取汇编源程序B中的下一条指令。如果读取的指令是页切换指令,将当前页地址设为指令中的页地址,同时清标记F(即给F标记赋零值),然后顺序读取汇编源程序B中的下一条指令。如果读取的指令是绝对跳转或子程序或函数调用或函数及子程序返回指令,则置首次进入子程序或函数的标记为F,否则顺序读取汇编源程序B中的下一条指令。
如果读取的指令不是上述所列的指令,则丢弃,顺序读取汇编源程序B中的下一条指令,直到判断完汇编源程序B中的所有指令。
如图6到图8b所示,上述以跳转分支结构对所述汇编源程序B进行页切换正确性检查的方法是:
首先,将以顺序结构检查完得到的所有标号集合,组成集合E。集合E中每一个标号具有如下属性(具体到一个标号时,某些属性可以为空):1、标号名称;2、标号在汇编源程序B或汇编源程序Y中的位置;3、跳转或直接进入标号的各个分支带来的页地址;4、标号后出现的第一个变量操作或页切换指令中的页地址信息,包括具体页地址数值,每个页地址是否为页切换指令形成的,页地址切换指令或变量操作在汇编源程序中的位置等;5、标号是否为子程序或函数入口标号;6、标号为子程序或函数时,子程序或函数的出口页地址信息。以顺序结构检查完可以得到标号的属性1和2。另外查找所有标号过程中可以得到汇编源程序B中所有子程序及函数调用的名称的集合S,不同类型芯片的汇编指令可能不同,例如TI DSP汇编程序中可以用检测CALL指令来得到函数及子程序名称。
然后,找出所述集合E中每个标号的跳入或直接进入时的全部页地址及子程序、函数的出口页地址:首先,从所述汇编源程序B开始处读取,置首次进入子程序或函数的标记为标记F,置标记F为刚有效标志G。然后,顺序读取汇编源程序B中一条指令,如果读取的指令为变量操作指令,则判断是否有标记F,如果有标记F,将当前页地址设为指令中的页地址,然后清除标记F,顺序读取汇编源程序B中下一条指令;如果没有标记F,直接顺序读取汇编源程序B中下一条指令。如果读取指令为页切换指令,将当前页地址设为指令中的页地址,清除标记F,然后顺序读取汇编源程序B中下一条指令。如果读取指令是跳转或子程序或函数调用,则这些指令中必有一个标号,如果标记F为清除,则将当前页地址记录到标号集合E中该标号的属性3中,并判断读取的指令是否是绝对跳转或子程序或函数调用或函数及子程序返回指令;如果标记F为置位并且标记G为清除,则将当前页地址记录到标号集合E中该标号的属性3中,再判断读取的指令是否是绝对跳转或子程序或函数调用或函数及子程序返回指令;如果标记F为置位并且标记G为置位,则直接判断读取的指令是否是绝对跳转或子程序或函数调用或函数及子程序返回指令;如果读取指令不是跳转或子程序或函数调用则直接判断读取的指令是否是绝对跳转或子程序或函数调用或函数及子程序返回指令。如果读取指令是绝对跳转或子程序或函数调用或函数及子程序返回指令,则置首次进入子程序或函数的标记为标记F,置标记F为刚有效标志G;继续判断,如果读取指令为函数及子程序返回指令,则将正在检查的子程序的出口页地址作为当前页地址记录到子程序标号的属性6中,然后顺序读取汇编源程序B中下一条指令。如果读取的指令是标号,且标记F为清除状态,则也将当前页地址记录到标号集合E中该标号的属性3中;如果读取的指令是标号且标记F为置位,并且标记G为置位,则记录该刚读取的标号为子程序或函数入口标号,记录“是子程序信息”到集合E中该标号的属性5中,并记录当前页为该标号,然后清除标记G,顺序读取汇编源程序B中下一条指令;如果读取的指令是标号且标记F为置位,并且标记G为清除状态,则将当前页地址记录到标号集合E中该标号的属性3中;否则如果读取的是其他指令,则顺序读取汇编源程序B中下一条指令。最后,如果汇编源程序B结束则检查标号集合E中每一标号,将跳入标号页地址中的标号进行迭代,直到所有标号处理完毕,替换为具体数值的页地址为止,
再次,找到所述集合E中每个标号的所有该标号后第一个变量操作指令的页地址或第一个页切换的页地址,即标号出口页地址信息的方法是(如图8a和图8b所示):从所述汇编源程序B开始处开始;标记L清零(标记L置位表示需要记录标号后首个页地址及页切换情况)。顺序读取汇编源程序B中一条指令;如果读取的指令为标号,则判断标记L是否置位,如果没有置位,则置标记L,表示需要记录标号后首个页地址及页切换情况,并记录该标号在集合E中的位置为P,顺序读取汇编源程序B中下一条指令。如果读取的指令为标号且已置位标记L,则将刚读取的标号记录到集合E中P位置处此标号的属性4中,记录该刚读取的标号在汇编源程序中的位置到属性4中,并将刚读取的标号在集合E中的位置更新为P,再顺序读取汇编源程序B中下一条指令。如果读取指令为变量操作指令,当前页地址设为指令中的页地址,如果标记L为置位则记录当前页地址到集合E中P位置处标号的属性4中,并记录无页切换指令信息到集合E中P位置处标号的属性4中,记录该刚读取的变量操作指令在汇编源程序中的位置到属性4中,清L标记,在顺序读取汇编源程序B中下一条指令,如果L标记没有置位则顺序读取汇编源程序B中下一条指令。如果读取指令为页切换指令,将当前页地址设为指令中的页地址,如果标记L为置位则记录当前页地址到集合E中P位置处标号的属性4中,并记录有页切换指令信息到该属性4中刚记录的当前页地址的相关信息中,记录该刚读取的页切换指令在汇编源程序中的位置到属性4中,清标记L,然后顺序读取汇编源程序B中下一条指令,如果标记L没有置位则执行步骤顺序读取汇编源程序B中下一条指令。如果读取指令是跳转或子程序或函数调用,则这些指令中必有一个标号K,如果L标记为置位则将标号K记录到集合E中P位置处标号的属性中;如果标记L没有置位则顺序读取汇编源程序B中下一条指令;否则如果读取的指令是子程序返回或函数返回,清标记L,顺序读取汇编源程序B中下一条指令,如果是其他指令,则顺序读取汇编源程序B中下一条指令。如果读取指令是绝对跳转或子程序或函数调用,则清标记L,再顺序读取汇编源程序B中下一条指令,否则顺序读取汇编源程序B中下一条指令。如果汇编源程序B结束,检查标号集合E中每一标号的属性4,将集合E中每个标号后首个变量操作或页切换指令所用到的页地址中的标号进行迭代,直到所有标号处理完毕,替换为具体数值的页地址为止,替换的同时,也要把页地址在汇编源程序Y中的位置一起替换过去,方便后边的自动修改页地址错误的方法的实现。
所述标记L置位表示需要记录标号后首个页地址及页切换情况。
根据上述步骤得到子程序集合S中每一子程序(或函数)的入口页地址及出口页地址,可以根据S中两个子程序(或函数)标号名称到集合E的属性中查找,将两标号之间的所有是子程序(或函数)出口地址的标号找出,并将所有找出的标号的属性6合并,得到两个子程序(或函数)中标号靠前的那个子程序(或函数)的出口页地址。通过重复这种方法,可以得到所有子程序(或函数)的出口页地址。
然后,根据前面的标号入口、出口页地址,将所述集合E中出口页地址群组进行循环替换,得到所有子程序或函数的入口页地址、出口页地址。
再将所有子程序及函数调用处的构造标号的入口地址替换为该构造标号前的子程序(或函数)的入口页地址、出口页地址。
然后,比较所述集合E中所有标号(包含构造标号)的入口地址及出口地址,判断是否存在页地址错误(如图9所示):1,首先从所有标号集合E中读取一个标号的入口页地址及出口页地址及标号出口地址是否为页切换指令属性,直到处理完E中每一个标号。2,判断刚读取的标号的出口页地址是单一的还是多个,如果是单一的,执行步骤3,否则执行步骤5。3,判断标号出口页地址是否有页切换指令,如果是页切换指令形成的出口页地址,则该标号处没有页地址错误,执行步骤1;否则执行步骤4。4,判断标号入口页地址是否都相同且与标号出口地址相同,如果相同则该标号处没有页地址错误,执行步骤1,否则标记该标号处存在页地址错误,执行步骤1。5,判断标号出口页地址都是由页切换指令形成的,如果是则该标号处没有页地址错误,执行步骤1,否则执行步骤6。6,判断入口页地址是否都相同,如果不都相同,则标记该标号处存在页地址错误,执行步骤1,否则执行步骤7。7,判断入口页地址与出口页地址是否都相同,如果相同则该标号处没有页地址错误,执行步骤1,否则标记该标号处存在页地址错误,执行步骤1。
最后,将顺序结构检查及跳转分支结构检查中标记有错误的地方对照汇编源程序Y找出具体出错位置,然后生成一个页错误报告。所述页错误报告包含的信息有:出错文件的路径、名字,出错页地址在文件中的位置,指出所在的行号,变量名字。对检查汇编程序中发现的未定义变量进行报告,同样指出所在文件,及在文件中的位置。
如图10所示,报告完页错误后,在汇编源程序B中对所有标号进行检查:对于每一个标号,如果该标号没有被跳转指令引用并且没有被子程序及函数指令调用,也没有其它指令对该标号进行引用,且其前面指令是绝对跳转指令或处在文件头上或是无条件子程序返回指令或是无条件函数返回指令,则报告此段代码为无效代码。可以在上述页错误报告中报告所找到的无效代码段开始处标号的位置,包括其所在的源程序文件的路径、名字,在文件代码行中的位置。本是发明所述方法的另一个用途。
如图11所示是一种用于嵌入式模块中汇编程序的自动改错方法的流程图,在进行自动差错后,还进行以下步骤:首先,顺序从所有标号集合E中读取一个标号的入口页地址及出口页地址及标号出口地址。
然后,判断刚读取的标号的出口页地址是单一的还是多个,如果是单一的,执行下一步骤,否则判断标号出口页地址是否都是由页切换指令形成的。
判断标号出口页地址是否有页切换指令,如果是页切换指令形成的出口页地址,则该标号处没有页地址错误,顺序从所有标号集合E中读取一个标号的入口页地址及出口页地址及标号出口地址;否则判断入口页地址是否都相同。
判断标号入口页地址是否都相同且与标号出口地址相同,如果相同则该标号处没有页地址错误,顺序从所有标号集合E中读取一个标号的入口页地址及出口页地址及标号出口地址,否则该标号处存在页地址错误,在该标号后加入页地址切换指令予以纠正,加入位置是该标号后每个没有页切换指令的出口页地址在汇编源程序Y代码行中的位置的前面,数值为该出口页地址,然后顺序从所有标号集合E中读取一个标号的入口页地址及出口页地址及标号出口地址。
判断标号出口页地址是否都是由页切换指令形成的,如果是则该标号处没有页地址错误,顺序从所有标号集合E中读取一个标号的入口页地址及出口页地址及标号出口地址,否则执行下一步骤。
判断入口页地址是否都相同,如果不都相同,则该标号处存在页地址错误,在该标号后加入页地址切换指令予以纠正,加入位置是该标号后每个没有页切换指令的出口页地址在汇编源程序Y代码行中的位置的前面,数值为该出口页地址,顺序从所有标号集合E中读取一个标号的入口页地址及出口页地址及标号出口地址,否则执行下一步骤。
判断入口页地址与出口页地址是否都相同,如果相同则该标号处没有页地址错误,顺序从所有标号集合E中读取一个标号的入口页地址及出口页地址及标号出口地址,否则该标号处存在页地址错误,在该标号后加入页地址切换指令予以纠正,加入位置是该标号后,每个没有页切换指令的出口页地址在汇编源程序Y代码行中的位置的前面,数值为该出口页地址,顺序从所有标号集合E中读取一个标号的入口页地址及出口页地址及标号出口地址。
最后,处理完所有标号集合E中的最后一个标号后,将汇编源程序Y修改完页地址错误后输出为一个文件,将自动纠错后的结果报告出来。