×
嵌入式 > 嵌入式开发 > 详情

加载时域和运行时域

发布时间:2020-07-17 发布时间:
|
内容摘自 《S3C2410完全开发流程》

在开始后续实验之前,我们得了解一下arm-linux-ld连接命令的使用。在上述实验中,我们一直使用类似如下的命令进行连接:
arm-linux-ld -Ttext 0x00000000 crt0.o led_on_c.o -o led_on_c_tmp.o
我们看看它是什么意思:-o选项设置输出文件的名字为led_on_c_tmp.o;“--Ttext 0x00000000”设置代码段的起始地址为0x00000000;这条指令的作用就是将crt0.o和led_on_c.o连接成led_on_c_mp.o可执行文件,此可执行文件的代码段起始地址为0x00000000。

我们感兴趣的就是“—Ttext”选项!进入LINK目录,link.s代码如下:
1 .text
2 .global _start
3 _start:
4 b step1
5 step1:
6 ldr pc, =step2
7 step2:
8 b step2
Makefile如下:
1 link:link.s
2 arm-linux-gcc -c -o link.o link.s
3 arm-linux-ld -Ttext 0x00000000 link.o -o link_tmp.o
4 # arm-linux-ld -Ttext 0x30000000 link.o -o link_tmp.o
5 arm-linux-objcopy -O binary -S link_tmp.o link
6 arm-linux-objdump -D -b binary -m arm link >ttt.s
7 # arm-linux-objdump -D -b binary -m arm link >ttt2.s
8 clean:
9 rm -f link
10 rm -f link.o
11 rm -f link_tmp.o

实验步骤:
1.进入目录LINK,运行make生成arm-linux-ld选项为“-Ttext 0x00000000”的反汇编码ttt.s
2.make clean
3.修改Makefile:将第4、7行的“#”去掉,在第3、6行前加上“#”
4.运行make生成arm-linux-ld选项为“-Ttext 0x30000000”的反汇编码ttt2.s
link.s程序中用到两种跳转方法:b跳转指令、直接向pc寄存器赋值。我们先把在不同“—Ttext”选项下,生成的可执行文件的反汇编码列出来,再详细分析这两种不同指令带来的差异。
ttt.s: ttt2.s
0: eaffffff b 0x4 0: eaffffff b 0x4

4: e59ff000 ldr pc, [pc, #0] ; 0xc 4: e59ff000 ldr pc, [pc, #0] ; 0xc
8: eafffffe b 0x8 8: eafffffe b 0x8
c: 00000008 andeq r0, r0, r8 c: 30000008 tsteq r0, #8 ; 0x8
先看看b跳转指令:它是个相对跳转指令,其机器码格式如下:

Cond101Loffset

[31:28]位是条件码;[27:24]位为“1010”时,表示B跳转指令,为“1011”时,表示BL跳转指令;[23:0]表示偏移地址。使用B或BL跳转时,下一条指令的地址是这样计算的:将指令中24位带符号的补码立即数扩展为32(扩展其符号位);将此32位数左移两位;将得到的值加到pc寄存器中,即得到跳转的目标地址。我们看看第一条指令“b step1”的机器码eaffffff:
1. 24位带符号的补码为0xffffff,将它扩展为32得到:0xffffffff
2.将此32位数左移两位得到:0xfffffffc,其值就是-4
3.pc的值是当前指令的下两条指令的地址,加上步骤2得到的-4,这恰好是第二条指令step1的地址
各位不要被被反汇编代码中的“b 0x4”给迷惑了,它可不是说跳到绝对地址0x4处执行,绝对地址得像上述3个步骤那样计算。您可以看到b跳转指令是依赖于当前pc寄存器的值的,这个特性使得使用b指令的程序不依赖于代码存储的位置——即不管我们连接命令中“--Ttext”为何,都可正确运行。
再看看第二条指令ldr pc, =step2:从反汇编码“ldr pc, [pc, #0]”可以看出,这条指令从内存中某个位置读出数据,并赋给pc寄存器。这个位置的地址是当前pc寄存器的值加上偏移值0,其中存放的值依赖于连接命令中的“--Ttext”选项。执行这条指令后,对于ttt.s,pc=0x00000008;对于ttt2.s, pc=0x30000008。于是执行第三条指令“b step2”时,它的绝对地址就不同了:对于ttt.s,绝对地址为0x00000008;对于ttt.s,绝对地址为0x30000008。
ttt2.s上电后存放的位置也是0,但是它连接的地址是0x30000000。我们以后会经常用到“存储地址和连接地址不同”(术语上称为加载时域运行时域)的特性:大多机器上电时是从地址0开始运行的,但是从地址0运行程序在性能方面总有很多限制,所以一般在开始的时候,使用与位置无关的指令将程序本身复制到它的连接地址处,然后使用向pc寄存器赋值的方法跳到连接地址开始的内存上去执行剩下的代码。在实验5、6中,我们将会作进一步介绍。
arm-linux-ld命令中选项“-Ttext”也可以使用选项“-Tfilexxx”来代替,在文件filexxx中,我们可以写出更复杂的参数来使用arm-linux-ld命令——在实验6中,我们就是使用这种方法来指定连接参数的。



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
STM32的RTC配置和起振问题