重要的概念
1.链接地址:链接时指定的地址(指定方式:使用-Text,或者链接脚本)
运行地址:程序实际运行时地址(指定方式:由实际运行时被加载到内存的哪个位置决定的)
链接地址和运行地址:可能相同也可能不同
加载地址:程序在存储器(NAND,NOR等)中的地址
2.位置无关码:赖于程序当前运行的PC值,进行相对的跳转(编译器自动找到目标地址相对于当前PC值的偏移量offset,相对于当前PC值去跳转),导致的结果就是,无论代码在哪,总能达到指令的正常目的,因此是位置无关的
位置相关码:不依赖当前PC值,是绝对跳转,只有程序运行在链接地址处时(编译器根据链接脚本得到实际需要跳转目的的绝对地址),才能达到指令的正常目的,因此是位置有关系的
重要指令
1.位置无关跳转:B指令--B指令接受一个相对地址,在汇编里使用B跳转到一个标号时,实际编译结果是一个相对跳转。跳转范围不能太远,offset must in 32 Mbit
BL指令--BL指令用于调用函数,是相对跳转,与B一样
ADR指令--ADR指令获取标号地址,在编译时会使用PC+offset的方式得到该位置的地址
LDR指令--LDR指令不加“=”时,表示位置无关跳转
2.位置相关跳转:LDR指令,LDR PC,=LABLE,相对跳转,与代码位置和链接地址相关,跳转到绝对地址
LDR指令的重要说明
LDR指令有如下三种使用方法,说明如下:
1.LDR r1,#100 加载立即数到指定寄存器
2.LDR r1,=label 将label标号的地址值存入指定寄存器
3.LDR r1,label 将label地址中的值存入指定寄存器
实例说明
1.注:ARM9是3级流水线,也就是处理器处理时正在执行第1条指令的同时对第2条指令进行译码,并将第3条指令从存储器中取出,如下图所示,PC寄存器总是指向第3条指令取值的地方(就是说,处理器正在执行的是1号指令,PC寄存器的值是3号指令的地址值)
2.makefile
源码
反汇编
(1)ldr r0,on_sdram ,反汇编是ldr r0,[PC,#4],由于当前指令地址是4,PC寄存器值为4+8,偏移量offset是4,所有指令会把4+8+4这个地址的值(也就是机器码e3a0d30d)存到r0(注意反汇编的[]中括号)。一般情况ldr r0,label的使用情形是
ldr r0,label
label:
.word 0x10000000
把某个值放到寄存器里
(2)ldr r0,=on_sdram,反汇编是ldr r0,[PC,#24],ldr r0,= label 反汇编是ldr没有“=”标号的ldr指令,编译器根据链接地址,在text代码段的末端空白地址存放目标地址值(如0x28 地址处的0x10,实际就是目标地址值)这样计算offset以得到绝对地址(这个偏移量offset编译器自动计算),实际就是把:当前运行地址 8 + PC寄存器地址8 + 偏移量#24 = 40(0x28),最后把0x28地址中的值0x10放到r0中。如果指令是ldr pc,=on_sdram ,就是把0x10放到PC寄存器中,这样实现了跳转。
以上,
2020/04/17
原文:https://www.cnblogs.com/IamLoser/p/12717346.html