一个程序包括:
1.代码段 : 指令
2.数据段 : 有初始值(并且不为0)的全局静态变量
第二列:机器码,表示当前地址中存放的内容。
第三列:汇编代码,机器码的转换,可以被人所识别。
第四列:解析。
在不同的链接地址获取全局变量的过程:
pc 的值 == 当前的pc值 + (bl test 与 test:指令之间的偏移值)====》相对跳转
而
ldr pc,=test的跳转:
pc = (test:标识的链接地址),如果链接地址上没有test:指令,则就会出错 -=====> 绝对跳转
1.代码段 : 指令
2.数据段 : 有初始值(并且不为0)的全局静态变量
3.bss段 : 初始值为0 / 无初始值的全局静态变量
链接选项-Ttext 0 :
这个链接选项表示程序的代码段从0开始运行,数据段,bss段依次向后排列。
除了上面指定各个段存放位置的方法,还可以使用另外一种方法:使用链接脚本 -T leds.lds,这个链接脚本决定了各个段如何排列。
例如下面的脚本就是链接脚本的格式:
SECTIONS
{
. = 0x50000000; /*设置当前地址*/
.text : { /*代码段*/
start.o
* (.text)
}
.data : { /*数据段*/
* (.data)
}
bss_start = .; /*bss段*/
.bss : {
* (.bss)
}
bss_end = .;
}
引入bss_start,bss_end的原因是:编译出来的二进制文件led.bin是没有bss段(
初始值为0或未初始化的全局静态变量)的。用这两个变量来给bss段清0.
如何分析反汇编文件?
先给出例子:
00000000 <_start>:
0: e3a00207 mov r0, #1879048192 ; 0x70000000
4: e3800013 orr r0, r0, #19
8: ee0f0f92 mcr 15, 0, r0, cr15, cr2, {4}
c: e59f0014 ldr r0, [pc, #20] ; 28 <halt+0x4>
10: e3a01000 mov r1, #0
14: e5801000 str r1, [r0]
18: e3a0db06 mov sp, #6144 ; 0x1800
1c: eb000047 bl 140 <clock_init>
20: eb000008 bl 48 <main>
第一列:地址
第二列:机器码,表示当前地址中存放的内容。
第三列:汇编代码,机器码的转换,可以被人所识别。
第四列:解析。
在不同的链接地址获取全局变量的过程:
1.当链接地址为0,变量i的地址为0x100。
2.当链接地址为0x50000000,变量i的地址为0x50000100。
所以说,当链接地址不一样的话,程序访问变量的地址是不一样的。(可以实验,将链接地址改为500000000的话,DDR还没有初始化,程序就会崩溃,使用openocd的现象是无法进行halt,因为跳转到了链接地址,而DDR没有初始化。)
实验代码:
#define CONFIG_PERIPORT_BASE 0x70000000
#define CONFIG_PERIPORT_SIZE 0x13
#define WTCON 0x7E004000
#define GPMCON 0x7F008820
#define GPMDAT 0x7F008824
.global _start
_start:
/*告诉CPU 外设的地址*/
ldr r0, =CONFIG_PERIPORT_BASE
orr r0, r0, #CONFIG_PERIPORT_SIZE
mcr p15,0,r0,c15,c2,4
/*关闭看门狗*/
ldr r0, =WTCON
mov r1, #1
str r1,[r0]
/*点灯nLED1 <==> GPM0*/
/*GPMCON 0x7F008820
**GPMDAT 0x7F008824
*/
/*设置GPM0为输出引脚*/
ldr r0, =GPMCON
mov r1, #0x1
str r1, [r0]
bl test
/* ldr pc, =test */
halt:
b halt
test:
/*设置GPM0的电平输出为低,点亮*/
ldr r0, =GPMDAT
mov r1, #0
str r1, [r0]
mov pc, lr
bl test的跳转:
pc 的值 == 当前的pc值 + (bl test 与 test:指令之间的偏移值)====》相对跳转
而
ldr pc,=test的跳转:
pc = (test:标识的链接地址),如果链接地址上没有test:指令,则就会出错 -=====> 绝对跳转
如果设置的链接地址为0x50000000,那么这个程序运行的地址也“应该”是0x50000000.但是硬件决定了如果从nand启动的话,首先运行的地址还是片内内存,因为一上电,6410 CPU 会将nandflash中的前8K内容源源本本的拷贝到6410的片内内存上去运行。那么如果想要程序在链接地址50000000上取运行,那么拷贝到片内内存上的程序需要做重定位操作。
在重定位之前的代码可以运行的原因是使用了位置无关码。
位置无关码:
1.在跳转的时候使用相对跳转指令:b bl
2.不妨问全局变量,不访问静态变量