上一篇关于动态加载讲述的是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. SqlServer之触发器

    1.触发器之理论: 触发器(Trigger)是一种特殊类型的存储过程,是在用户对某一种表的数据进行UPDATE.INSERT 和 DELETE 操作时被触发执行的一段程序.触发器有助于强制引用完整性, ...

  2. 混淆篇之原生DOM操作方法小结

    1.0   DOM结构 1.1先来看结构图: 父节点        兄弟节点        当前节点            属性节点            子节点        兄弟节点一般任意一个节 ...

  3. Struts2问题,已解决No result defined for action and result input

    struts2.1.8 必须在struts.xml中配置namespace属性 如果你在2.0中一切OK,但是在2.1中确出现了No result defined for action的异常,就是在因 ...

  4. 随意记的一点 js 笔记

    1. 给未经声明的变量赋值在严格模式下会导致抛出 ReferenceError 错误(意思是,所有变量都必须用 var 去定义,不能在函数内部定义全局变量): 2. 在严格模式下,不能定义名为 eva ...

  5. mysql函数操作(5)

    <?php try{ $dbh = new PDO('mysql:dbname=testdb;host=localhost', 'mysql_user', 'mysql_pwd'); }catc ...

  6. B/S结构和C/S结构

    概念: C/S结构,即Client/Server(客户机/服务器)结构,是大家熟知的软件系统体系结构,通过将任务合理分配到Client端和Server端,降低了系统的通讯开销,可以充分利用两端硬件环境 ...

  7. 关于Apple Pay,一篇让你不看就会后悔的文章

    编者按:本文作者康上明学为“小米生活”产品经理,在苹果Apple Pay发布后,他对该产品做了深入研究,带来这篇文章. 对于 Apple Pay ,我有几个疑问: 线下支付是一个庞大复杂的流程,当中涉 ...

  8. delphi 7中使用idhttp抓取网页 解决假死现象

    在delphi 7中使用idhttp抓取网页,造成窗口无反应的假死状态.通过搜索获得两种方法. 1.写在线程中,但是调用比较麻烦 2.使用delphi 提供的idantifreeze(必须安装indy ...

  9. ios jsbrige

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  10. 蓝桥杯之K好数问题

    问题描述 如果一个自然数N的K进制表示中任意的相邻的两位都不是相邻的数字,那么我们就说这个数是K好数.求L位K进制数中K好数的数目.例如K = 4,L = 2的时候,所有K好数为11.13.20.22 ...