历史上的今天
返回首页

历史上的今天

今天是:2025年03月25日(星期二)

正在发生

2020年03月25日 | tiny4412裸机程序之位置无关码

2020-03-25 来源:eefocus

在上篇文章中,将代码的.text、.data、.rodata段重定位到了0x02026400位置处去执行点亮LED的操作。但是,在链接脚本里指定的链接地址是0x02026400,那么为什么在重定位之前的代码能够在0x02023400地址处可以开始执行?就是因为前面使用的是位置无关码。写介绍介个概念:


链接地址:链接脚本里指定的,理论上程序运行时所处的地址。在编译时,编译器会根据链接地址来翻译位置有关码。


加载地址(运行地址):程序运行时,实际所处的地址。


位置无关码,位置有关码,是相对于一条指令的正常目的来说的。比如ldr r0, =xx,它的正常目的是取得标号处的地址,对于这个目的,它是位置有关码,运行的地址不对就获取不到正确的标号地址,其实它无论在哪都是获取的程序加载地址等于链接地址时,标号的地址,如果你就是想要这个值,那么用这条指令是非常正确的,就不用理会什么位置无关码,位置有关码的概念了,这一点非常重要。


因此,当加载地址不等于链接地址时,并不是不可以用位置无关码,而是要看你用位置无关码是否达到了你想要的目的。


位置无关码,依赖于程序当前运行的PC值,进行相对的跳转,导致的结果就是,无论代码在哪,总能达到指令的正常目的,因此是位置无关的。


位置有关码,不依赖当前PC值,是绝对跳转,只有程序运行在链接地址处时,才能达到指令的正常目的,因此是位置有关系的。


下面,我们来看常用的汇编指令以及C语言中哪些操作是位置有关码,哪些是位置无关码。


示例1:


借助前面介绍的uart的代码来做这个实验;


start.S文件内容如下:


.text

.global _start

_start:

ldr sp, =0x02027400 //调用C函数之前必须设置栈,栈用于保存运行环境,给局部变量分配空间;

//参考ROM手册P14,我们把栈指向BL2的最上方;

//即:0x02020000(iROM基地址)+5K(iROM代码用)+8K(BL1用)+16K(BL2用)

bl main //跳转到C函数中执行

mov r0, pc

bl printPc

 

halt: //死循环

b halt


首先,设置栈,然后调整到main函数执行,最后将pc的值保存到R0寄存器中,然后调用printPc函数将R0寄存器中的值打印出来。


mian.c的内容如下:


//main函数

int main()

{

//初始化串口操作

uart0_init();

//打印16进制数

puthex(100);

return 0;

}

 

int printPc(unsigned int value)

{

puthex(value);

}


在main()函数中调用了uart0_init()函数初始化串口。然后打印一个100的值;另一个函数printPc函数打印传入的值。


链接脚本如下:


SECTIONS {

. = 0x0;

.text : { *(.text) }

.rodata ALIGN(4) : {*(.rodata)}

.data ALIGN(4) : { *(.data) }

.bss ALIGN(4) : { *(.bss) *(COMMON) }

}

其中,指定的链接地址是0x0,就是期望程序在0x0地址处开始运行。


编译烧写程序,查看输出如下:

第一个打印的数字是100;第二个打印的pc的值;大家可以发现,我们指定的链接地址是0x0,而程序运行在0x02023400地址处开始执行的,也能成功执行,为什么呢?就是因为我们使用的是位置无关码。查看反汇编:

已经在图中做了详细的注释。首先,就是将当前pc值加偏移量12处的值保存sp栈中。然后执行bl跳转到main()函数处执行。注意:bl 18这个指令并不是跳转到18地址处开始执行。bl是一条相对跳转指令,当前PC值加偏移量。其机器码是0xeb000003;我们将链接地址设置为0x02023400,看看这条指令的机器码是多少:

可以看到,将链接地址更改为0x02023400地址处,这个条指令的机器码还是0xeb000003。


可以得出结论:B/BL指令是位置无关码,是根据当前PC值加某个符合距离当前位置的offset值,不管链接地址是多少,此值是固定的。也就是不管链接地址是多少都能正常跳转。


还是看第一幅图片,我们将当前PC的值保存到了R0寄存器中了,然后跳转到printPc()函数执行,打印出的值是0x02023410。


也就是说,打印的值是加载地址,并不是链接地址。链接地址是期望程序运行的地址。加载地址是程序实际运行的地址。


结论:


1.程序的链接地址和加载地址不是一回事。


2.在重定位代码之前应该使用位置无关码,位置无关码的操作时根据当前PC值加上偏移量在进行执行。


怎么编写位置无关码:


1.使用相对跳转指令(B/BL);

2.重定位之前不可以使用绝对地址;不可以访问全局变量和静态变量;

3.重定位之后可以访问全局变量和静态变量;使用ldr pc, =xxx;指令跳转到某个地址开始执行;

4.不可访问有初始值的数组,数组中每个成员是位于栈中的,但是其初始值是保存在.rodata中的;

5.如果出了问题,最根本的办法是看反汇编。


在写位置无关码是不能使用全局变量和有初始值的数组:


全局变量(静态或非静态),如果有初始值则保存.data段中,没有初始值则保存到.bss段中。而取用.data段中的数据是根据链接地址来操作的。


有初始值的数组,数组中的每个变量是位于栈中的,但是其初始值是放在.rodata段中的,其地址是链接时就确定下来了。


本文完毕!

推荐阅读

史海拾趣

Crowd_Supply__Inc.公司的发展小趣事

随着电子行业的快速发展和市场竞争的加剧,Crowd Supply Inc.也面临着诸多挑战。为了保持竞争优势,公司不断调整战略方向,加大在新技术领域的投入。例如,公司近期开始关注物联网和人工智能等前沿技术的应用,通过整合社区资源和技术优势,成功开发出了一系列具有市场潜力的新产品。

长运通(CYT)公司的发展小趣事

长运通注重与高校和研究机构的合作,积极引进和培养人才。公司与电子科技大学、西安电子科技大学等知名高校建立了紧密的合作关系,共同开展技术研发和人才培养。通过与高校的合作,长运通不仅获得了更多的技术资源支持,也为公司培养了一批高素质的研发人才。这些人才为公司的发展提供了强有力的支撑。

Connection One公司的发展小趣事

在电子行业的快速发展中,Connection One公司始终保持着强烈的创新意识。公司不断投入研发资金,引进高端人才,推动技术创新和产品升级。这种持续创新的精神使得公司在行业中始终保持领先地位,铸就了辉煌的业绩。

这些故事虽然基于虚构情节,但反映了电子行业中企业发展的一些普遍规律。在实际情况中,一个成功的电子企业往往需要具备技术创新能力、市场拓展能力、全球化视野以及持续创新的精神。

Crocus Technology公司的发展小趣事

随着技术的不断成熟和市场需求的变化,Crocus Technology开始拓展其产品线。2015年,公司成功推出了首款磁开关产品,这标志着公司在磁传感器领域迈出了重要的一步。随后,公司又陆续推出了位置传感和2D传感器产品,进一步巩固了其在磁传感器市场的地位。

Astema公司的发展小趣事

随着业务的迅速增长,Astema意识到供应链管理的重要性。公司开始优化供应链管理流程,提高生产效率和产品质量。同时,Astema还与供应商建立了紧密的合作关系,确保原材料供应的稳定性和可靠性。这些举措使得Astema在激烈的市场竞争中保持了稳定的运营。

Astro Tool Corp公司的发展小趣事

Astro Tool Corp公司深知产品质量是企业生存和发展的关键。因此,公司始终将质量管理放在首位,建立了完善的质量管理体系和检测机制。通过严格把控原材料采购、生产过程和成品检测等各个环节,公司确保了产品的稳定性和可靠性。同时,公司还注重品牌建设,通过提升产品附加值和服务质量,不断增强客户对公司的信任度和忠诚度。

问答坊 | AI 解惑

单片机实现水中油浓度检测

用单片机实现水中油浓度在线实时检测…

查看全部问答>

FX-20P-E手持编程器操作手册

三菱手持式编程器使用手册,以前我学习编程序时候就是用它,虽然不如电脑直观,但是也锻炼了对指令的记忆了,呵呵呵,希望对大家能有用。…

查看全部问答>

用ARM写程序,串口发送等程序要自己编吗?

如果用ARM的开发板,向超级终端发送文字,我知道有很多现成的头文件,里面有串口发送的函数,那有没有必要自己再编写一个呢?如果换作是其他的现有的函数呢? 现在学ARM9,用的是2440.因为是刚接触ARM,很多都不了解,请高人指点一下!!!!…

查看全部问答>

我的2407无法仿真,观察到如下现象,网帮忙检查原因

用usb20emurst程序可以扫描到芯片?? 你只能判断是否连上了,仿真器,不能说你能扫描到芯片,…

查看全部问答>

ARM、DSP、FPGA的特点和区别

  ARM(Advanced RISC Machines)是微处理器行业的一家知名企业,设计了大量高性能、廉价、耗能低的RISC处理器、相关技术及软 件。ARM架构是面向低预算市场设计的第一款RISC微处理器,基本是32位单片机的行业标准,它提供一系列内核、体系扩展、微 ...…

查看全部问答>

LM3S的eth接口是不是很容易坏?

目前产品中已经有好几个芯片有类似情况,就是上电后,eth不能连接,换个cpu后就好了,不知道是什么情况。电路如下图所示:请有经验的大虾帮忙分析分析!CPU型号是LM3S9B92-C5 [ 本帖最后由 zxq6 于 2012-4-18 12:28 编辑 ]…

查看全部问答>

初学msp430,怎么开始啊???

以前学过51单片机,但是没有认真学,现在开始接触msp430,感觉无从下手,望高手指点指点,让我开始入门,谢谢…

查看全部问答>

《玩转TI MSP430 Launchpad》与大家见面了!

    TI-EEWORLD联手打造的《玩转TI MSP430 Launchpad》与广大工程师朋友们见面了!按照传统的观念,单片机入门教材或工具书之类都应是由资深专业人士编写,而与此不同的是,本书中大量精彩内容来自于网友们的经验和知识,这些都是来自于 ...…

查看全部问答>

IAR 430编译出现这个警告是什么意思,怎么消除啊

IAR 430编译出现这个警告是什么意思,怎么消除啊 Warning[Pa050]: non-native end of line sequence detected (this diagnostic is only issued once) F:\\Mixed Files\\msp430 files\\msp430g2452\\mcp2515_test\\main.c 2…

查看全部问答>

TI 电源芯片和电源拓扑结构对应选择

TI 电源芯片和电源拓扑结构对应这个资料不错,推荐给大家,,, [ 本帖最后由 qwqwqw2088 于 2013-10-27 22:08 编辑 ]…

查看全部问答>