6873|16

78

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

请问C语言中如何读取程序空间的代码? [复制链接]

请问C语言中如何读取程序空间的代码?

我曾经试过多种方法,结果都是错的。
经检查发现其错的根源都是:编译生成的指令不是BLPD而是BLDD。也就是说,编译程序认为我要读的东西不是在程序空间而是在数据空间。
我用的CPU是TMSF240,开发工具是Code Composer 4.12。

我试过的方法有:

一、
在连接命令文件中将.const段定位于程序空间;
在C程序中定义一个const的全局变量,同时规定初值(例如const int xx=123;);
在程序中直接引用这个变量名(xx)来读取其值。

二、
引用函数名来代表函数所在的程序空间的首地址,用对指针强制类型转换的方法来读取该函数的第一个程序代码(机器码)。
例如,假定函数名是ff,则采用形式是:
*(int * )ff

这两种方法中,其他方面都完全正确,唯一错处就是:指令不是BLPD而是BLDD。
因为:
只要将这一段程序生成的汇编代码抄下来,将其中的BLDD换成BLPD,再作为汇编语言文件加入到这个project中替换掉原来的C原程序,就一切都对了。

但是,我的程序中类似的需要非常多(需要使用大量的固化在程序空间的数据表,即const数组),
如果都非得用汇编才行的话,
那么整个程序就不如完全不用C语言了。

查了很多资料,找不到如何解决。诚请行家给以指教。

最新回复

PFUNC_wordRead 用这个在TI网站中有个静态库文件,并且有代码例程可以下载的  详情 回复 发表于 2010-1-13 05:29
 
点赞 关注

回复
举报

64

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
我用的CPU是TMS320F240,开发工具是Code Composer 4.12。
 
 

回复

73

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
补充说明一点:
我上面说“只要将这一段程序生成的汇编代码抄下来,将其中的BLDD换成BLPD,”
是因为我这些例子里都只用到了直接的寻址,所以只需更换一条指令:BLDD换成BLPD。

如果换个需要间接寻址的例子情况就复杂些,不是只要更换一条指令了。
但现象的根源还是一样的,即:
编译程序认为我要读的东西不是在程序空间而是在数据空间。
实际读到的结果不是程序空间的该代码,而是数据空间中地址恰好与之相同的那个单元里的代码。

除上面的两个例子以外,我还试过以下的例子:

同样在连接命令文件中将.const段定位于程序空间;
程序中定义:
char *p="abcd";
此时,指针变量p虽然在数据空间,但字符串常量"abcd"则放在了程序空间中的.const段。

然后在程序中读取*p。本希望读出字符"a"的ASCII码,结果不是。
经查,错误性质与上述例子相同。
 
 
 

回复

73

帖子

0

TA的资源

一粒金砂(初级)

4
 
你可以试试 CODE_SECTION指令,c2000的编译器支持,cc的编译器是否支持没有测试。
 
 
 

回复

67

帖子

0

TA的资源

一粒金砂(初级)

5
 
谢tonyzheng版主。

我试过了的。CODE_SECTION指令虽可以成功将某个变量定位于程序区,但读取此变量的代码编译出来依然是错的,和上面叙述的性质一样。

将某个变量定位于程序区,按我上面的办法用const本来已经可以解决了。

假如不用const而用CODE_SECTION将某个变量定位于程序区,情况更复杂一些。有时似乎结果“正确”了,但细查发现是两个错误同时存在以致结果恰好表面“正确”但实际错误。

例如:

#pragma CODE_SECTION(xxx,".const")
unsigned int xxx=123;
然后在程序中作temp=xxx; j结果temp的值就是123。似乎是对了的。

但细查内存,发现xxx所在的位置内容并非123。
经分析,可能是这样的:

因为没有用const,所以编译时123并未放入xxx,而是放到.cinit段去了。
在引导程序cint0中初始化时,本该把.cinit段中的123送入xxx,但错误地送入到数据空间中地址恰等于xxx的地址处了。
后来在执行时,并没有从xxx处读取,而是从数据空间中地址恰等于xxx的地址处读取了。
恰好读得123。
但实际是错误的。
 
 
 

回复

76

帖子

0

TA的资源

一粒金砂(初级)

6
 
如果既用#pragma CODE_SECTION(xxx,".const")
又在定义前用const,
则结果和不用CODE_SECTION指令,效果一样。

即1楼的例一。
 
 
 

回复

77

帖子

0

TA的资源

一粒金砂(初级)

7
 
另:
您在短信回复中所说“你可以用读地址的方式,把具体的代码作为数据存放到数组里。”意义我没有看明白。

我想,240CPU特点,程序空间和数据空间地址编码是重叠的,而读取数据空间的存储内容和读取程序空间的代码内容的机器指令的操作码不同。
而C语言中如何体现这一个不同,则是现在问题的所在。

如果是其它CPU如80x86,数据和程序地址统一编码,不重叠,自然就没有这个问题了。
 
 
 

回复

76

帖子

0

TA的资源

一粒金砂(初级)

8
 
没人解答吗?
 
 
 

回复

86

帖子

0

TA的资源

一粒金砂(初级)

9
 
没人解答吗?
 
 
 

回复

57

帖子

0

TA的资源

一粒金砂(初级)

10
 
我过去没有用过面向单片机的C语言,
不知道别的CPU的C语言中有没有同样问题?

例如8051系列、AVR系列等等,都属于“读取数据空间的存储内容和读取程序空间的代码内容的机器指令的操作码不同”的。

我想请教用过51的C语言或AVR的C语言的朋友,在那里同样问题是怎么个情况?还有,其他版本的CCS下的C语言呢?
 
 
 

回复

78

帖子

0

TA的资源

一粒金砂(初级)

11
 
我想,

假如其他环境下这个问题都不是问题,比如,按照顶楼的例子做,结果都不错的话,
那么,是否可以认为,
现在发现的问题,是CC2000的系统中存在的BUG?

或者,假如其他系统中这个问题虽可以解决,但必须采用特殊的形式,如特别的pragma编译命令,或特别的描述符,等等,
那么,是否可以认为,
CC2000系统中缺少这部分功能支持,所以用户必须用汇编扩充?

如果用汇编扩充,这个问题当然是可以解决的。但我目前需要的是:知道C语言中正规的形式应该是什么。
 
 
 

回复

79

帖子

0

TA的资源

一粒金砂(初级)

12
 
现将我用汇编扩充的办法的程序列于下:

【C程序文件中的声明】
/********** 程序空间访问宏 **********/
/* 说明:程序空间的数据,一般可以定义成const型的全局变量的形式 */
/* 读取程序空间的代码(getcode与getcode_p实际使用同一汇编子程序) */
unsigned int getcode(const unsigned int * txtaddr); /* 读取程序空间的代码 */
/* 子程序地址类型PSUBROT */
typedef void (*PSUBROT)();
/* 读取程序空间的指针型代码 */
PSUBROT getcode_p(const PSUBROT * txtaddr); /* 读取程序空间的代码 */
/* 读取分支表,模型:PSUBROT getbranch(const PSUBROT * addrtbl, unsigned int i);  */
#define getbranch(addrtbl,i) (getcode_p((addrtbl) + (i)))
/* 例:设有分支表如下(作为全局变量)       */
/* const PSUBROT branchtable[5] = {sub0,sub1,sub2,sub3,sub4}; */
/* 则程序语句:  (*getbrunch(brunchtable,3))();     */
/* 即可执行sub3();         */

(待后续)
 
 
 

回复

74

帖子

0

TA的资源

一粒金砂(初级)

13
 
(续)
【汇编程序文件中的定义】
        .globl        _getcode , _getcode_p
;******************************************************
;* FUNCTION DEF : _getcode , _getcode_p
;******************************************************
_getcode_p:
_getcode:                                ;s-1:        txtaddr
        SAR        AR1,*                ;s1:        工作位置,AR1指向
        LAR        AR2,*,AR2
        MAR        *-                ;此时AR2所指即s-1:        txtaddr
        LACL        *,AR1                ;将txtaddr装入ACC
        TBLR        *        ;利用ACC间接寻址,求出(*txtaddr)放入工作位置
        LACL        *                ;取返回值
        RET
;******************************************************
 
 
 

回复

67

帖子

0

TA的资源

一粒金砂(初级)

14
 
从上面的程序可以看出,关键点在于这里使用了指令TBLR,读取程序区中的代码。
假如将其换成读取数据区的相应指令,
那么,
这里的y=getcode(&x);就和普通的y=x;完全一样了;
这里的(*getbrunch(brunchtable,3))();就和普通的(*brunchtable[3])();完全一样了。
 
 
 

回复

75

帖子

0

TA的资源

一粒金砂(初级)

15
 
我现在的实际问题是这样的:

数年以来,我已经用汇编语言设计出了一个相当规模的完整的实际应用的系统,并且与被控制设备本身的研制工作同步,该软件已经经过了长时间的不断调试、改进、升级,以及详细的测试。
该软件将来的继续维护工作,将会一直持续到该设备被淘汰为止,显然不可以仅靠我一个人,必须培训出一批可以接手的青年程序员来。

但是接受了消化本系统任务的青年程序员中,存在不少畏难情绪。虽然我的说明资料已经尽可能写得详细易懂,而且还进行过多次的讲解,但仅仅一句“汇编语言太难学”这一条,就成了一个“学不会”借口。

所以,我打算花时间把这个系统改写成一个C语言的版本,作为他们消化理解原系统的一个参考资料。或许会有些助益。

当然,改编后的C语言版本,因为其效率、性能的差异,响应的准时性、调节的精度、资源的安全裕度等都不如原汇编版本,而且它也没有经过充分测试。
所以,改编版本不打算实际交付使用,只提供给他们作为“学习参考资料”。

因此,这个版本最好尽量采用C语言的常规形式。前面说的汇编扩充,显然不是个理想的办法。
 
 
 

回复

53

帖子

0

TA的资源

一粒金砂(初级)

16
 
这个C语言版本中,用到读取程序区的操作处主要有三类情况:

一是:程序中有大量的数据表,被查表程序引用;
二是:实时自检功能要求定时校验固化的程序代码有无被破坏;
三是:程序中有不少“散转表”。

其中第三类比较次要(因为它可以用switch-case结构代替)。

其中第一类情况,我见过的不少设计都是:初始化时将数据表全部移到RAM区中。那样做就不存在本帖所说的问题了。但那样做有两个缺点,故本系统不能采用:
(1)占用RAM太多;
(2)RAM中数据受干扰被破坏的概率显然比ROM高得多,故可靠性不够好。
 
 
 

回复

64

帖子

0

TA的资源

一粒金砂(初级)

17
 
PFUNC_wordRead
用这个在TI网站中有个静态库文件,并且有代码例程可以下载的
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表