上一篇关于动态加载讲述的是M3下面的ropi的实现细节,这一篇则讲述RW段的实现细节以及系统加载RW段的思路,我在M3上根据这个思路可以实现elf的动态加载,当然进一步的可以优化很多东西,还可以研究将bin加载起来,这个需要一些辅助的东西实现。

言归正文,使用/acps/rwpi编译代码,解决RW段即全局变量的加载。

首先编译的时候会为每一个全局变量生成一个相对于r9寄存器的偏移量,这个偏移量会在.text段中。

如下例子:

 static int elf_test_num = ;
int elf_test_num2 = ;
int main(void)
{
elf_test_num = ;
elf_test_num2 = ;
for(;;);
}

编译:

armcc  -c --cpu Cortex-M3 -O0 --apcs=interwork --apcs /ropi/rwpi -o main.o main.c

使用fromelf查看汇编代码

fromelf.exe -s -c main.o

生成的汇编代码如下(Cortex-M3):

 $t
.text
SystemInit
0x00000000: BX lr
main
0x00000002: MOVS r0,#
0x00000004: LDR r1,[pc,#] ; [0x18] =
0x00000006: ADD r1,r1,r9
0x00000008: STR r0,[r1,#]
0x0000000a: MOVS r0,#
0x0000000c: LDR r1,[pc,#] ; [0x1c] =
0x0000000e: ADD r1,r1,r9
0x00000010: STR r0,[r1,#]
0x00000012: bf00 NOP
0x00000014: e7fe B {pc} ; 0x14
$d
0x00000016: .. DCW
0x00000018: .... DCD
0x0000001c: .... DCD

在编译阶段相对r9偏移量还都是零,要到链接阶段才确定相对r9偏移量的大小,链接之后如下:

armlink.exe --cpu Cortex-M3 --ropi --ro_base  --rwpi --rw_base 0x0 --entry=main --no_startup main.o -o main.elf
使用fromelf查看汇编代码
fromelf.exe -s -c main.elf

查看最终的elf文件汇编如下:

 $t
.text
SystemInit
0x00000000: BX lr
main
0x00000002: MOVS r0,#
0x00000004: LDR r1,[pc,#] ; [0x18] = 0x4
0x00000006: ADD r1,r1,r9
0x00000008: STR r0,[r1,#]
0x0000000a: MOVS r0,#
0x0000000c: LDR r1,[pc,#] ; [0x1c] = 0x8
0x0000000e: ADD r1,r1,r9
0x00000010: STR r0,[r1,#]
0x00000012: bf00 NOP
0x00000014: e7fe B 0x14 ; main +
$d
0x00000016: .. DCW
0x00000018: .... DCD
0x0000001c: .... DCD

此时$d对应的偏移量均已确定大小。

取出对应一句C的汇编代码如下:

 elf_test_num = ;

 0x00000002:           MOVS     r0,#
0x00000004: LDR r1,[pc,#] ; [0x18] =
0x00000006: ADD r1,r1,r9
0x00000008: STR r0,[r1,#]

详细解释如下:

  1、MOVS     r0,#2

    即r0 = 2。

  2、LDR      r1,[pc,#16] ; [0x18] = 0

    即r1 = *(pc + 16)。这里实现了RW无关性,相对当前PC值取出偏移量所在的地址即pc,#16 = 0x18,再从0x18地址出取出偏移量的大小即[pc,#16] = 0x04,从上面加黑的位置查看0x00000018地址的值即为0x00000004,存放到r1寄存器。(这里的pc值应该是下一指令的pc值,并且应该是对齐32位的,具体赢查看arm指令手册。)

  3、ADD      r1,r1,r9

    即r1 = r1+r9,所以指定了在r9偏移0x00000004的地址处给到r1。

  4、STR      r0,[r1,#0]

    即*(r1 + 0) = r0,即将r0赋给r1指向的地址处,此时r1即是偏移r9基址4的地方。

综上所述,在加载elf阶段,将RW段加载到RAM当中之后,需要将r9寄存器指向此片内存的基地址,然后接下来就可以跳转到加载的elf的代码中去执行,就可以实现全局变量的加载了。具体实现思路可以如下:

 __global_reg() char *sb;   //在C中使用r9寄存器(static base register)的方法

 char rw_buf[];            //rw段的加载地址,也可以让系统动态分配一段内存地址

 char *saved_sb;           //保存r9

 void load_fun(void)

 {

     saved_sb = sb;     //先保存r9的值

     sb = rw_buf;      //将r9指向rw段的加载地址

     entry();          //跳转执行到具体的一个elf的入口执行

     sb = saved_sb;    //从elf程序跳转回来赋回原来r9的值

 }

Cortex-M3 动态加载二(RWPI数据无关实现)的更多相关文章

  1. vue:使用不同参数跳转同一组件,实现动态加载图片和数据,以及利用localStorage和vuex持久化数据

    需求:通过不同的参数复用同一组件,实现动态加载数据和图片,同时,在页面刷新时,图片依旧可以加载成功. 过程出现的bug和问题: 1.使用params传参后,再次刷新页面,参数丢失导致数据无法再次加载 ...

  2. 根据JSON对象动态加载表格--大数据量

    EasyUI的DataGrid加载数据的时候,如果列数过多(300列以上),数据渲染及其缓慢. JSON对象格式: 1:rowno 2:title 3:colspan 4:rowspan 5:back ...

  3. Ajax实现页面动态加载,添加数据

    前台代码: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Products ...

  4. EasyUI datagrid 动态加载表头和数据

    首先返回到页面的需要是JSON数据: 第一步: 遍历表头,插入到array中 for (var i = 0; i < jsonObj.title.length; i++) { //把返回的数据封 ...

  5. Cortex-M3 动态加载一(地址无关代码实现)

    这篇文章是自己疑惑究竟地址无关性是如何实现,然后查看汇编和CPU指令手册,最后分析解除自己疑惑的,高手不要鄙视,哈哈. 编译C代码时候需要制定--acps/ropi选项,如下例子: void Syst ...

  6. Echarts使用及动态加载图表数据 折线图X轴数据动态加载

    Echarts简介 echarts,缩写来自Enterprise Charts,商业级数据图表,一个纯JavaScript的图表库,来自百度...我想应该够简洁了 使用Echarts 目前,就官网的文 ...

  7. EasyUI datagrid动态加载json数据

    最近做一个项目,要求是两张张表可能查找出10多种不同的结果集. 如果想只用一个表格就把全部的结果不同的显示出来那么就肯定不同使用固定的字段名字,要通过动态加载后台返回来的数据把它显示出来就必须动态加载 ...

  8. 项目总结—jQuery EasyUI-DataGrid动态加载表头

    http://blog.csdn.net/zwk626542417/article/details/19248747 概要 在前面两篇文章中,我们已经介绍了在jQuery EasyUI-DataGri ...

  9. jQuery EasyUI-DataGrid动态加载表头

    项目总结—jQuery EasyUI-DataGrid动态加载表头     目录(?)[-] 概要 实现 总结   概要 在前面两篇文章中,我们已经介绍了在jQuery EasyUI-DataGrid ...

随机推荐

  1. SQL数据库知识二(Day 25)

    又到了总结知识的时候了,今天主要把SQL数据库给简单的学完了,明天开始就要开始学ADO.NET的知识了.好了,话不多说,还是看一下今天都学了哪些内容. 1  字符串类型的知识点 --类型的使用 --截 ...

  2. CSS中链接文本为图片时的问题(塌陷、对应的图片建立倒角的问题)

    我在做Javascript DOM编程艺术的时候,在12章自己做练习时遇到了一个问题,<a>的内容<img>从<a>的盒子中溢出.代码如下: <a href= ...

  3. stat 函数讲解

    表头文件:    #include <sys/stat.h>                     #include <unistd.h>定义函数:    int stat( ...

  4. Nodejs学习笔记——Assert(断言)

    Assert - a:actual e:expected m:message o:operator v:value b:block assert.fail(a, e, m, o) assert(v, ...

  5. oracle 查询表的大小,表空间的使用情况,默认表空间

    oracle 查询表的大小,表空间的使用情况,默认表空间 oracle 查询表的大小,表空间的使用情况,默认表空间 --查看某张表占用磁盘空间大小 ( 表名大写 ) Select Segment_Na ...

  6. PADS封装

    CAE 是原理图符号DECAL 是PCB封装PART 是将 CAE和 DECAL结合映射起来.比如PART包含了CAE和DECAL的管腿对应关系.CAE的1号腿,不一定对应DECAL的1号腿的.Pin ...

  7. aliyun 启用ECS iptables

    iptables -t nat -A POSTROUTING -s 0.0.0.0/24 -o eth0 -j MASQUERADEservice iptables saveecho 1 > / ...

  8. 多个target下编译的时候出错问题的解决

    在工程里如果有多个target的时候,如图 那么编译的时候一定要注意Xcode右侧勾选了正确的target,否则有可能会导致一系列让你想不到的bug. ,另外,如果工程中有framework,那么一定 ...

  9. 教你爱上Blocks(闭包)

    传值 Blocks是C语言的扩充功能:带有自动变量(局部变量)的匿名函数.通过Blocks,源代码中就能使用匿名函数,即不带名称的函数.在我们 的工作中,命名占据了很大一部分,函数名,变量名,属性名, ...

  10. linux性能监控三张图

    一.监控 二.测试 三.优化