首页 > 其他分享 >裸机:代码重定位实战

裸机:代码重定位实战

时间:2024-07-24 22:26:44浏览次数:11  
标签:实战 定位 led 代码 bin 裸机 start 0xd0024000

任务:

在SRAM中将代码从0xd0020010重定位到0xd0024000
任务解释:本来代码是运行在0xd0020010的,但是因为一些原因我们又希望代码实际是在0xd0024000位置运行的。这时候就需要重定位了

思路:

第一点:通过链接脚本将代码链接到0xd0024000
第二点:dnw下载时将bin文件下载到0xd0020010
第一点加上第二点,就保证了:代码实际下载运行在0xd0020010,但是却被链接在0xd0024000。从而为重定位奠定了基础。
当我们把代码链接地址设置为0xd0024000时,实际隐含意思就是我这个代码将来必须放在0xd0024000位置才能正确执行。如果实际运行地址不是这个地址就要出事(除非代码是PIC位置无关码),当以上都明白了后,就知道重定位代码的作用就是:在PIC执行完之前(在代码中第一句位置有关码执行之前)必须将整个代码搬移到0xd0024000位置去执行,这就是重定位。
第三点:代码执行时通过代码前段的少量位置无关码将整个代码搬移到0xd0024000
第四点:使用一个长跳转跳转到0xd0024000处的代码继续执行,重定位完成

总结:重定位实际就是在运行地址处执行一段位置无关码PIC,让这段PIC(也就是重定位代码)从运行地址处把整个程序镜像拷贝一份到链接地址处,完了之后使用一句长跳转指令从运行地址处直接跳转到链接地址处去执行同一个函数(led_blink),这样就实现了重定位之后的无缝连接。

代码修改

link.lds:
. = 0xd0024000
makefile: 修改链接脚本文件名:

led.bin: start.o led.o
    arm-linux-ld -Tlink.lds -o led.elf $^
    arm-linux-objcopy -O binary led.elf led.bin
    arm-linux-objdump -D led.elf > led_elf.dis
    gcc mkv210_image.c -o mkx210
    ./mkx210 led.bin 210.bin
    
%.o : %.S
    arm-linux-gcc -o $@ $< -c -nostdlib

%.o : %.c
    arm-linux-gcc -o $@ $< -c -nostdlib

clean:
    rm *.o *.elf *.bin *.dis mkx210 -f

    
    

start.S:重定义代码

#define WTCON       0xE2700000

#define SVC_STACK   0xd0037d80

.global _start               
_start:
    // 
    ldr r0, =WTCON
    ldr r1, =0x0
    str r1, [r0]
    
    // 
    ldr sp, =SVC_STACK
    
    // 
    mrc p15,0,r0,c1,c0,0;         
    //bic r0, r0, #(1<<12)         
    orr r0, r0, #(1<<12)           
    mcr p15,0,r0,c1,c0,0;
    
   // 第4步:重定位

//ldr和adr都是伪指令,区别是ldr是长加载、adr是短加载。
//重点:adr指令加载符号地址,加载的是运行时地址;
//ldr指令在加载符号地址时,加载的是链接地址。

    adr r0, _start //adr指令用于加载 start当前运行地址        
    

    ldr r1, =_start // // ldr指令用于加载 start的链接地址:0xd0024000
    //
    ldr r2, =bss_start // bss段的起始地址 重定位代码的结束地址 只需要重定位代码段和数据段
    cmp r0, r1          // 比较_start运行地址和链接地址是否相等
    beq clean_bss       //相等执行这里 跳过copy_loop,直接到clean_bss
                        // 不相等 需要重定位 执行copy_loop后执行clean_bss
                        // 

//深入分析:只要知道adr和ldr分别用于加载运行地址和链接地址,
//从而可以判断是否需要重定位即可;
//根本不需知道为什么adr和ldr是这样子,
//但是我们还是给大家扩展讲下为什么adr和ldr可以加载不同的地址。


//重定位:代码的作用是使用循环结构来逐句复制代码到链接地址
//复制的源地址是SRAM的0xd0020010,
//复制目标地址是SRAM的0xd0024000,
//复制长度是bss_start减去_start
//所以复制的长度就是整个重定位需要重定位的长度,也就是整个程序中代码段+数据段的长度。
//bss段(bss段中就是0初始化的全局变量)不需要重定位。

copy_loop:
    ldr r3, [r0], #4    //源
    str r3, [r1], #4    // 目的 完成四字节内容拷贝
    cmp r1, r2          // r1, r2都是链接地址
    bne copy_loop

// 清bss段
clean_bss:
    ldr r0, =bss_start                  
    ldr r1, =bss_end
    cmp r0, r1              // 相等 bss段为空 
    beq run_on_dram         // 为空执行这里
    mov r2, #0
clear_loop: //清空操作
    str r2, [r0], #4        // 先将r2中的值放入r0所指向的内存地址(R0中的内存地址内容)
    cmp r0, r1              // r0 = r0 + 4
    bne clear_loop

run_on_dram:    
    // 
    ldr pc, =led_blink  // 位置有关码 实现长跳转
    
    // 
    //bl led_blink                  // 短跳转
    
// 死循环
    b .
    

link.lds

SECTIONS
{
    . = 0xd0024000;
    
    .text : {
        start.o
        * (.text)
    }
            
    .data : {
        * (.data)
    }
    
    bss_start = .; 
    .bss : {
        * (.bss)
    }
    
    bss_end  = .;    
}

总结

重定位可以理解为需要将代码先重新写入到指定地址,然后长跳转到重写后代码正式执行的地方
SRAM不需要进行初始化可以直接使用

学习记录,侵权联系删除。
来源:朱老师物联网大课堂

标签:实战,定位,led,代码,bin,裸机,start,0xd0024000
From: https://blog.csdn.net/qq_43441284/article/details/140674665

相关文章

  • Ecahrts 基本柱线图配置代码
    <scriptsetuplang="ts">import{ref,onMounted}from'vue'import*asechartsfrom'echarts'constechartsRef=ref(null)onMounted(()=>{constmyChart=echarts.init(echartsRef.value)letoption={b......
  • Python数据分析与可视化大作业项目说明(含免费代码)
    题目:对全球和中国互联网用户的数据分析与可视化代码下载链接:https://download.csdn.net/download/s44359487yad/89574688一、项目概述1.1.项目背景:互联网是当今时代最重要和最有影响力的技术之一,它已经深刻地改变了人们的生活、工作、学习等方面。互联网用户数据是反映......
  • SpringBoot整合Swagger2,代码文档一手抓
    文章目录引言什么是swaggerSwagger的优势SpringBoot整合Swagger2添加Swagger依赖application.yml配置配置类SwaggerConfig启动类配置RESTful实战案例参考常见swagger注解说明页面访问效果常见错误引言什么是swaggerSwagger是一个规范且完整的框架,用于生成、描......
  • 优化代码质量:PyCharm插件在代码检查中的妙用
    优化代码质量:PyCharm插件在代码检查中的妙用PyCharm,作为业界领先的集成开发环境(IDE),提供了强大的代码编辑、调试和分析工具。其中,代码质量检查是确保代码健康的重要环节。PyCharm通过各种插件支持代码质量检查,帮助开发者发现潜在的错误、代码风格问题以及改进代码结构的机会......
  • 我可以写代码写到退休吗?记录我的10年前端技术之旅
    今天是2024年4月26日,是我的32岁生日,也是我从事前端开发十年的日子,这篇文章是对我职业生涯的一次回顾,这次回顾颇有感慨,不仅回顾了之前工作的公司、同事,也看了一遍之前写的代码、写的文章,还有以前看的技术书的笔记。本文就以技术栈为线,把这十年的前端经历串起来,一来让读者一窥这十......
  • 【Python实战因果推断】45_因果实验设计1
    目录Geo-Experiments在前文你学习了如何利用一段时间内的重复观察来帮助进行因果推理。现在,在本文中,你将从另一个角度来探讨同样的问题。如果你不必使用面板数据来确定干预效应,而是要设计一个实验来收集这些数据,会怎么样呢?本部分专门讨论了在简单的A/B测试行不通时的替代......
  • 【Python实战因果推断】51_因果推理概论1
    目录WhatIsCausalInference?WhyWeDoCausalInferenceMachineLearningandCausalInferenceWhatIsCausalInference?因果关系可能在你的认知中是一片危险的知识领域,你被告诫要避免涉足。你的统计学老师可能反复强调过,“相关性不等于因果性”,混淆两者可能会让......
  • 【Python实战因果推断】53_因果推理概论3
    目录CausalModelsCausalModels因果模型是一系列分配机制的集合,我们用符号来表示。在这个机制里,我使用u来代表模型外部的变量,也就是说,我不关心它们是如何生成的。而其他的变量则是我非常关注的,因此它们被纳入了模型之中。最后,存在函数f,用来描述一个变量如何映射到另一个......
  • 【Python实战因果推断】52_因果推理概论2
    目录AssociationandCausationTheTreatmentandtheOutcomeTheFundamentalProblemofCausalInferenceAssociationandCausation直观上,你大概明白为什么相关性并不等于因果性。如果有人告诉你顶级咨询能促使你的业务改善,你难免会持怀疑态度。你怎么能确定是咨询......
  • 我可以写代码写到退休吗?记录我的10年前端技术之旅
    今天是2024年4月26日,是我的32岁生日,也是我从事前端开发十年的日子,这篇文章是对我职业生涯的一次回顾,这次回顾颇有感慨,不仅回顾了之前工作的公司、同事,也看了一遍之前写的代码、写的文章,还有以前看的技术书的笔记。本文就以技术栈为线,把这十年的前端经历串起来,一来让读者一......