- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
代码重定位的思考
代码重定位的思考(1)----PC基址跳转所谓代码的重定位(relocate),就是把可执行代码移动到内存中的另外一个地址去。OS一般会把内核从硬盘COPY到内存中去执行,就是用到了重定位这个技术。可执行代码经过编译,连接和定位之后,代码段和数据段都已经被定位器固定了。那么移动这段代码之后,程序若碰到branch指令,会不会跳到错误的地址去执行呢?为了验证这个问题,笔者以Renesas SH2A体系的CPU为例,来做了相关的测试。硬件平台:CPU和外部SDRAM其中CPU内部包含一小块SRAM程序被下载到外部SDRAM里面执行。笔者将外部SDRAM地08010120区间的代码复制到CPU内部SRAM地址FFF80000处,并跳转到FFF80000去执行08010120区间包含了flush_cache()和它调用的init_node()的代码。下面是代码拷贝的汇编函数_relocate:MOVML.L R6,@-R15STS.L PR,@-R15MOV.L #HFFF80000,R0 ; start address of the internal RAM.MOV.L #_flush_cache,R1 ; start address of flush_cache()MOV.L #H8010120,R6 ; copy stop addressCopy_Loop:MOV.L @R1,R2 MOV.L R2,@R0 ; 开始拷贝代码到SRAMADD #H4,R0ADD #H4,R1CMP/EQ R6,R1BT Continue ; if T = 1, copy finishedMOV.L #Copy_Loop,R3JMP @R3NOPContinue:CLRTMOV.L #HFFF80000,R5JSR @R5 ; execute flush_cache() in the internal RAM.NOPLDS.L @R15+,PRMOVML.L @R15+,R6RTS/N.END 下面是flush_cache()的C函数,里面调用另一个函数init_node(),以便让CPU产生branch指令// 入口地址为0oid flush_cache(void){CCNT.CCR1.BIT.ICF = 1; CCNT.CCR1.BIT.OCF = 1; // 入口地址为0init_node(0);}经过调试,发现程序能正常跳转到地址FFF80000去执行flush_cache(),接下来也能正常跳转到init_node()去执行,CPU完成了代码的重定位。下面我们来看看编译器对flush_cache()生成的地址,机器码和反汇编。移动之前:地址机器码指D703 MOV.L @(H000C:8,PC),R7 ;注意这里的R7就是init_node()的入口地472B JMP @R7 ;JMP是一条branch指令,用于子函数的跳转移动之后:地址机器码指令FFF80014 D703 MOV.L @(H000C:8,PC),R7FFF80016 472B JMP @R7我们发现了一个很奇怪的问题,就是移动之前和移动之后的代码是完全不变的,但是程序在执行JMP @R7之后,确都能准确地跳转到0执行init_node()。这是为什么呢?很明显,我们发现了MOV.L @(H000C:8,PC),R7这条指令的与众不同。该指令是把PC的内容加上H000C:8计算产生的偏移量之和送入R7,于是真相明白了。编译器在遇到branch指令时,是以PC为基址来跳转的。我们来查看该指令。16-bit/32-bit displacementPC indirect with displacement(带转移的PC间接寻址)MOV.L @(disp:8,PC),R7The effective address is the sum of PC value and an 8-bit displacement(disp). The value of disp is zero-extended, and is doubled for a word operation, and quadrupled for a longword operation. For a longword operation, the lowest two bits of the PC value are masked.Word:PC + disp * 2Longword:PC HFFFFFFFC + disp * 4由于copy代码的时候,是将flush_cache(
原创力文档


文档评论(0)