免责声明:本文提供的所有内容仅供学习、分享与交流,不保证内容的正确性,亦不对内容可能带来的风险担责。如若转载,请署名以及注明原始出处。本文仅代表个人的立场和观点,并不代表任何公司或组织。
基于LiteOS Studio & Qemu零成本学习ARM 汇编——0x05 移花接木
下面的全部操作仅适用Window 10 64bits 环境。
前几篇中的示例程序都存储在Flash memory内,属于EEPROM(Electrically Erasable Programmable read only memory,是指带电可擦可编程只读存储器,是一种掉电后数据不丢失的存储芯片),类似硬盘。变量不方便存储在Flash内,需要存储在RAM内,以便进行变量的修改。
Connex开发板拥有64MB的RAM,内存起始地址为0xA0000000,变量可以存储这个内存区域。该开发板的内存映射如下图:
![8026816f29cd8c7b35d6cbbb608ea919.png](https://i-blog.csdnimg.cn/blog_migrate/af4edc42bf8abd32e3c9ff1a022fdb17.png)
Memory Map
0x01 LMA -> VMA
上电时,RAM中没有数据可以直接可用。所有的代码和数据在上电前存储在Flash内存内。上电时,启动代码复制Flash中的数据到RAM,然后运行程序处理数据。程序.data区段有2个地址,一个是Flash中的load address(也称为LMA,Load Memory Address),一个是RAM中的runtime address(也称为VMA ,Virtual Memory Address)。
链接脚本里需要指定.data区段的加载地址和运行时地址,汇编代码需要复制.data从Flash到RAM。
0x02 指定加载地址LMA
VMA运行时地址就是标签的地址。在之前的示例中,为.data区段指定了VMA。LMA加载地址没有显式指定,默认等同于运行时地址。程序直接从flash上执行时,这样是没有问题的。如果数据放到RAM上执行,LMA对应Flash、VMA对应RAM。看链接脚本:
SECTIONS {
. = 0x00000000;
.text : {
* (.text);
}
flash_sdata = .; ❶
. = 0xA0000000;
ram_sdata = .; ❷
.data : AT (flash_sdata) {
* (.data);
};
ram_edata = .; ❸
data_size = ram_edata - ram_sdata; ❹
}
❶
在Flash内存里,仅挨着代码段,放数据data段,flash_sdata表示数据段的开始地址。
❷
数据段在RAM中的开始地址就是RAM的基地址。AT关键字指定Flash中数据段的地址。
❸ ❹
数据段的大小的计算,即RAM中数据段的结束地址、开始地址的差值。
0x04 赋值.data到RAM
从Flash中复制数据到RAM,需要下述信息:
Flash中的数据起始地址flash_sdata、RAM中的数据起始地址ram_sdata、.data区段的大小data_size。汇编代码如下,注意copy操作的实现:
.data
val1: .4byte 10 @ First number 用于求和的第一个数
val2: .4byte 30 @ Second number 用于求和的第二个数
result: .space 4 @ 1 byte space for result 存放结果的空间
.global _start
.text
@;; Copy data to RAM. 复制Flash中的数据到RAM
_start:
ldr r0, =flash_sdata
ldr r1, =ram_sdata
ldr r2, =data_size
copy:
ldrb r4, [r0], #1
strb r4, [r1], #1
subs r2, r2, #1
bne copy
@;; Add and store result. 计算加和 并存放结果
ldr r0, =val1 @ r0 = &val1
ldr r1, =val2 @ r1 = &val2
ldr r2, [r0] @ r2 = *r0
ldr r3, [r1] @ r3 = *r1
add r4, r2, r3 @ r4 = r2 + r3
ldr r0, =result @ r0 = &result
str r4, [r0] @ *r0 = r4
stop: b stop
GDB 单步调试:
从https://gitee.com/huawei_liteos_studio/arm_assembly/tree/master/DataInRAM检出示例代码工程,使用LiteOS Studio打开工程。编译、开始调测,我们打开build目录下面的asm文件,并且分栏展示,F10单步调试,单步调试如之前操作。
点击查看内存,输入起始内存地址0xA000000,长度输入100,可以打开查看内存窗口。
可以看到0xA0000000处的值为0x0A=10 0xA0000004处的值为0x1E=30. 从Flash处复制了数据。
![8ba923304c662a3ba139ad287d39617a.png](https://i-blog.csdnimg.cn/blog_migrate/d9d19d45a711467d62b03b6823e1aabb.png)
查看内存
界面如下:
0x05 参考资料
http://www.bravegnu.org/gnu-eprog/data-in-ram.html