社区导航

 
快捷导航
  • 首页
  • 论坛
  • 查看新帖
  • 最新回复
  • 社区活动
  • 联系管理员
  • 消灭零回复
  • E金币兑换
  • 干货
搜索
查看: 2258|回复: 2

一种在CodeWarrior平台下任意定位RAM运行代码的方法

[复制链接]

180

TA的帖子

0

TA的资源

一粒金砂(高级)

Rank: 3Rank: 3

发表于 2012-9-26 21:52:33 | 显示全部楼层 |阅读模式

实现目标

 

CW 平台,编写一段能在 RAM 行的代码,并且代码的定位是自由的。

 

硬件平台:MC9S12HY64

软件平台:CodeWarrior V5.0

 

实现方法 

 

要实现与代码定位无关的代码需要设置 CW 的编译选项中的相关项,开启方法:

打开 CW 工程勾选Edit->Standard Settings->Compiler for HC12->Option->Code Generation->Generate Position Independent Code

 

生成代存在的问题

1. 使用变量地址是固定的,如果直接移植代码,变量地址访问出错。所以变量地址不能改变。

2. 函数传递入口参数,如果直接变量传递,在变量不多的情况下,可以通过编写汇编代码数和 堆栈连接实现,如果对于汇编不熟悉的情况(我就是这种情会比较困难。如果将多个变量打包成结构体变 量然后给函数代码传递结构体指针参数虽然只有 1 但是函数的代码都将是指针操作可能会出现代码量 增大或者运行速度降低等问题。

经过摸索,找到一个可以实现变量和代码定位在任意位置的办法。 代码中的对外入口直接使用全局变量当然如果变量地址变化也会产生变量访问错误的问题解决的办

法是先编译调试好代码然后反汇编将代码数据做成一个一维数组然后将代码中的全局变量信(全局变 量地址和变量偏移量和对应汇编代码地址偏移量提取出来 2 数据做成一个结构体然后提取汇编代码中所有地址数据和对应的索引偏移做成一个结构体数组这样一来在加载代码到 RAM 只需要修改对 应索引偏移所在的地址数据即可达到代码和变量的重新任意定位的效果提示一点可以将代码中的所有访问 的全局变量做成一个结构体那么在进行重新定位的时候可以通过循环体的方式来实现这样效率高而且方 便。例子如下:

typedef struct PG_INF

{

UINT8    CommandType;         //变量首地址偏移量 = 0

UINT8    BlockIndex;           //变量首址偏移量 = 1

UINT16 DestAddr;              //变量首址偏移量 =2

UINT16 DataSize;              //变量首地址偏移量 =4

UINT8    Pg_State;              //变量首址偏移量 = 6

UINT8    Buf[512];              //变量首址偏移量 = 7

UINT8    CheckSum;             //变量首地址偏移量 = 519

};

typedef struct   // 地址重定位

{

UINT16 AsmCode_Index;       //   代码偏移索引号

UINT16 GVal_Offset;            //    首地址偏移量,不同的值代表了结构变量体 Pg_Frame 的不同变量

}GVal_Ram_Locate;

 

const UINT8 Pg_Code[] =     //  码表

{

/* Flash_CommandProcess 函数代码 */

0x1B,0xF1,0xEC,0xCE,0x00,0x00,0xC6,0x01,0x7B,0x00,0x06,0x69,0x85,0xC7,0x87,

0x6C,0x80,0xE6,0x30,0xEB,0x85,0x6B,0x85,0xED,0x80,0x02,0x6D,0x80,0x8D,0x02,

0x07,0x25,0xF0,0xF6,0x02,0x07,  …………

};

 

const GVal_Ram_Locate    Gval_Ram_LocateTbl[] =    //地址定位表

{

{ 0x0004,        0x0000   },

{ 0x0009,   0x0006    },

{ 0x0022,   0x0207    },   …………

};

  

 

 

这里举例子,局变量地址 0x0000

 

图中 2

0003    ce0000       [2]         LDX    #Pg_Frame

 

 

最前面的其中 0003 ce0000 汇编代码偏移地址ce 是汇编指令ce 后面的 0000  这里他的值就是变量 地址+变量首地址偏移量,它占据了汇编代码偏移地址的 0004-0005 两个字节。所以汇编代码偏移索引号 Gval_Ram_LocateTbl[0]. AsmCode_Index = 0x0004  

这里#Pg_Frame 就是直接取全局变量 Pg_Frame 的首地址 = 0x0000,所以这里的变量首地址偏移量=0x0000,即 Gval_Ram_LocateTbl[0]. GVal_Offset = 0x0000,它对应了 Pg_Frame. CommandType 变量。 假如全局变量的首地址是 0x3000,则修改为

0003    ce3000       [2]         LDX    #Pg_Frame

 

所以可以很清楚的看到通过汇编代码偏移索引Gval_Ram_LocateTbl[]. AsmCode_Index就可定位到需要

修改的位置,然后将对应位置的值改成全局变量首地 +  首地址偏移量Gval_Ram_LocateTbl[].GVal_Offset对函数码和变进行任的重新位。前条件就要确定量的地,我想一点是

很容易做到的。

同理:图中 3

0008 7b0000            [3]         STAB    Pg_Frame:6

(这里的汇编代码是编译后没有连接定位的代码所以 0000 是没有计算变量首地址 + 变量首地址偏移量的

如变量首地址=0x3000, 变偏移量=6,连接定位后的目标代码应该是 7b3006  Gval_Ram_LocateTbl[1]. AsmCode_Index = 0x0009,                                        编代码的偏移地址=0x0009Gval_Ram_LocateTbl[1]. GVal_Offset = 0x0006, 变首地址偏移量= 0x0006,即 Pg_Frame. Pg_State

 

图中 4 框的

0021 f60000            [3]         LDAB    Pg_Frame:519

Gval_Ram_LocateTbl[2]. AsmCode_Index = 0x0022,  编代码的偏移地址=0x0022

Gval_Ram_LocateTbl[2]. GVal_Offset = 0x0207,变量首地址偏移量= 0x0207,即 Pg_Frame. CheckSum

 

 

 

代码中变量重定位,例代码

 

 

UINT16    i ;

UINT16 code_addr = 0x5000; //备将代码拷贝到 RAM 区的 5000 地址处

volatile struct PG_INF Pg_Frame @0x3900;   //函数代码中需要访问的结构体变量,变量地址定位在 0x3900

 

for( i=0; i<sizeof(Gval_Ram_LocateTbl) / sizeof(GVal_Ram_Locate); i++ ) // 对汇编代码进行重定位

{

*(UINT16*)( code_addr + Gval_Ram_LocateTbl[i].AsmCode_Index ) = Gval_Ram_LocateTbl[i].GVal_Offset + (UINT16)&Pg_Frame;

}

 

 

这里唯一繁琐的过程是制作 Gval_Ram_LocateTbl 表,因为要对照着汇编代码进行一个一个将变量地址信息 提取出来还有就是如果要修改代码则要重新做一次表比较繁琐不过将代码拷贝到 RAM 运行,一 般的情况下来说,代码量不会很大,修改的可能性也比较小。

RAM 运行代码,可以应用于 BootloaderFlash 编程要求提高运行速度等方面。

 

本人水平有限,难免有不当之处,希望能指出,大家一起讨论!

此帖出自单片机论坛


回复

使用道具 举报

403

TA的帖子

1

TA的资源

纯净的硅(初级)

Rank: 4

发表于 2012-10-6 01:25:29 | 显示全部楼层
坐在沙发上好好学习!向楼主致敬!正是想学的内容!!


回复

使用道具 举报

66

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

发表于 2012-10-8 23:38:12 | 显示全部楼层
之前碰到过这个问题,收藏
学如春起之苗,不见其增,日有所长;


回复

使用道具 举报

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

本版积分规则

  • 论坛活动 E手掌握

    扫码关注
    EEWORLD 官方微信

  • EE福利  唾手可得

    扫码关注
    EE福利 唾手可得

小黑屋|手机版|Archiver|电子工程世界 ( 京ICP证 060456

GMT+8, 2018-1-21 00:57 , Processed in 0.130056 second(s), 16 queries , Redis On.

快速回复 返回顶部 返回列表