上位机图像处理和嵌入式模块部署(f103 mcu中main入口函数误解)

本文主要是介绍上位机图像处理和嵌入式模块部署(f103 mcu中main入口函数误解),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

        学习stm32代码的时候,关于汇编文件,大家一般都会参考官方给出的汇编文件。通常情况下,不会自己去写汇编文件。特别是汇编文件的最后一行,大家都会把__main看成是直接进入main函数。后面通过反汇编,发现情况并不是这样的。我们编写代码,除了keil工程中的内容,还有MicroLib库,这一点常常被我们忽视。

1、之前的汇编代码

; Reset handler
Reset_Handler   PROCEXPORT  Reset_Handler             [WEAK]IMPORT  __mainIMPORT  SystemInitLDR     R0, =SystemInitBLX     R0               LDR     R0, =__mainBX      R0ENDP

        汇编代码这部分呢,大家一般都不会陌生,我们也通常都认为是__main直接跳转到了自定义的main函数。但是实际情况,我们可以通过反汇编来确认。

2、如何生成反汇编文件

        在项目的User tab配置中,添加这样的命令,就可以在project下面生成dis文件,

fromelf --text -a -c --output=Fire_F103VE.dis ../Output/Fire_F103VE.axf

        这样在最后的axf生成的同时,也能生成dis文件。如果需要生成bin文件,也是类似的做法。

fromelf --bin --output Fire_F103VE.bin ../Output/Fire_F103VE.axf

3、找到Reset_Handler位置

        首先我们找到Reset_Handler位置,

    __Vectors0x08000000:    20000410    ...     DCD    5368719520x08000004:    08000145    E...    DCD    1342180530x08000008:    08000d81    ....    DCD    134221185

        一般向量的第二个选项就是reset入口,不过mcu很奇怪,入口地址都要减去1才是正确的地址。也就是说,这里的Reset_Handler其实是08000144,

    Reset_Handler0x08000144:    4806        .H      LDR      r0,[pc,#24] ; [0x8000160] = 0x8000e170x08000146:    4780        .G      BLX      r00x08000148:    4806        .H      LDR      r0,[pc,#24] ; [0x8000164] = 0x80001310x0800014a:    4700        .G      BX       r0

        我们发现了,这边pc最后跳转的地址是8000131,因为需要减去1,那就是8000130,

    _main_stk0x08000130:    f8dfd00c    ....    LDR      sp,__lit__00000000 ; [0x8000140] = 0x20000410.ARM.Collect$$$$00000004_main_scatterload0x08000134:    f000f82a    ..*.    BL       __scatterload ; 0x800018c

        这边执行不久,就跳转到了__scatterload,

    __scatterload__scatterload_rt20x0800018c:    4c06        .L      LDR      r4,[pc,#24] ; [0x80001a8] = 0x8000ec40x0800018e:    4d07        .M      LDR      r5,[pc,#28] ; [0x80001ac] = 0x8000ee40x08000190:    e006        ..      B        0x80001a0 ; __scatterload + 200x08000192:    68e0        .h      LDR      r0,[r4,#0xc]0x08000194:    f0400301    @...    ORR      r3,r0,#10x08000198:    e8940007    ....    LDM      r4,{r0-r2}0x0800019c:    4798        .G      BLX      r30x0800019e:    3410        .4      ADDS     r4,r4,#0x100x080001a0:    42ac        .B      CMP      r4,r50x080001a2:    d3f6        ..      BCC      0x8000192 ; __scatterload + 60x080001a4:    f7ffffc8    ....    BL       __main_after_scatterload ; 0x8000138

        快结束的时候,又跳转到了__main_after_scatterload,

    __main_after_scatterload_main_clock_main_cpp_init_main_init0x08000138:    4800        .H      LDR      r0,[pc,#0] ; [0x800013c] = 0x8000e750x0800013a:    4700        .G      BX       r0

        这边貌似要回到main函数了,看这里的地址是8000e75,那就是8000e74,

    i.mainmain0x08000e74:    bf00        ..      NOP      0x08000e76:    f7ffff9e    ....    BL       SystemClock_Config ; 0x8000db60x08000e7a:    f7ffff2b    ..+.    BL       LED_GPIO_Config ; 0x8000cd40x08000e7e:    e012        ..      B        0x8000ea6 ; main + 500x08000e80:    2200        ."      MOVS     r2,#00x08000e82:    f44f5100    O..Q    MOV      r1,#0x20000x08000e86:    4808        .H      LDR      r0,[pc,#32] ; [0x8000ea8] = 0x400110000x08000e88:    f7fffb4a    ..J.    BL       HAL_GPIO_WritePin ; 0x80005200x08000e8c:    f44f707a    O.zp    MOV      r0,#0x3e80x08000e90:    f7fff992    ....    BL       HAL_Delay ; 0x80001b80x08000e94:    2201        ."      MOVS     r2,#10x08000e96:    0351        Q.      LSLS     r1,r2,#130x08000e98:    4803        .H      LDR      r0,[pc,#12] ; [0x8000ea8] = 0x400110000x08000e9a:    f7fffb41    ..A.    BL       HAL_GPIO_WritePin ; 0x80005200x08000e9e:    f44f707a    O.zp    MOV      r0,#0x3e80x08000ea2:    f7fff989    ....    BL       HAL_Delay ; 0x80001b80x08000ea6:    e7eb        ..      B        0x8000e80 ; main + 12

        看到上面的代码,大约可以验证到我们的猜测了。

4、总结

        之前在做linux soc芯片汇编文件编写的时候,中断初始化、bss初始化、sp初始化、已初始化全局变量copy、main函数跳转,这些都是基本的内容。后面自己看mcu代码的时候,却没有发现这部分内容,当时觉得很诧异,直到后来自己看了axf文件的反汇编内容之后,才晓得ide和背后的编译器帮我们做了很多事情。刚才说的这一切,都在main函数调用之前准备好了。但恰恰这一点,对于我们debug调试、分析和boot 加载研究很有帮助。

这篇关于上位机图像处理和嵌入式模块部署(f103 mcu中main入口函数误解)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1015886

相关文章

Python的time模块一些常用功能(各种与时间相关的函数)

《Python的time模块一些常用功能(各种与时间相关的函数)》Python的time模块提供了各种与时间相关的函数,包括获取当前时间、处理时间间隔、执行时间测量等,:本文主要介绍Python的... 目录1. 获取当前时间2. 时间格式化3. 延时执行4. 时间戳运算5. 计算代码执行时间6. 转换为指

Python正则表达式语法及re模块中的常用函数详解

《Python正则表达式语法及re模块中的常用函数详解》这篇文章主要给大家介绍了关于Python正则表达式语法及re模块中常用函数的相关资料,正则表达式是一种强大的字符串处理工具,可以用于匹配、切分、... 目录概念、作用和步骤语法re模块中的常用函数总结 概念、作用和步骤概念: 本身也是一个字符串,其中

Python中的getopt模块用法小结

《Python中的getopt模块用法小结》getopt.getopt()函数是Python中用于解析命令行参数的标准库函数,该函数可以从命令行中提取选项和参数,并对它们进行处理,本文详细介绍了Pyt... 目录getopt模块介绍getopt.getopt函数的介绍getopt模块的常用用法getopt模

python logging模块详解及其日志定时清理方式

《pythonlogging模块详解及其日志定时清理方式》:本文主要介绍pythonlogging模块详解及其日志定时清理方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录python logging模块及日志定时清理1.创建logger对象2.logging.basicCo

shell编程之函数与数组的使用详解

《shell编程之函数与数组的使用详解》:本文主要介绍shell编程之函数与数组的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录shell函数函数的用法俩个数求和系统资源监控并报警函数函数变量的作用范围函数的参数递归函数shell数组获取数组的长度读取某下的

MySQL高级查询之JOIN、子查询、窗口函数实际案例

《MySQL高级查询之JOIN、子查询、窗口函数实际案例》:本文主要介绍MySQL高级查询之JOIN、子查询、窗口函数实际案例的相关资料,JOIN用于多表关联查询,子查询用于数据筛选和过滤,窗口函... 目录前言1. JOIN(连接查询)1.1 内连接(INNER JOIN)1.2 左连接(LEFT JOI

Qt spdlog日志模块的使用详解

《Qtspdlog日志模块的使用详解》在Qt应用程序开发中,良好的日志系统至关重要,本文将介绍如何使用spdlog1.5.0创建满足以下要求的日志系统,感兴趣的朋友一起看看吧... 目录版本摘要例子logmanager.cpp文件main.cpp文件版本spdlog版本:1.5.0采用1.5.0版本主要

MySQL中FIND_IN_SET函数与INSTR函数用法解析

《MySQL中FIND_IN_SET函数与INSTR函数用法解析》:本文主要介绍MySQL中FIND_IN_SET函数与INSTR函数用法解析,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一... 目录一、功能定义与语法1、FIND_IN_SET函数2、INSTR函数二、本质区别对比三、实际场景案例分

Spring Boot项目部署命令java -jar的各种参数及作用详解

《SpringBoot项目部署命令java-jar的各种参数及作用详解》:本文主要介绍SpringBoot项目部署命令java-jar的各种参数及作用的相关资料,包括设置内存大小、垃圾回收... 目录前言一、基础命令结构二、常见的 Java 命令参数1. 设置内存大小2. 配置垃圾回收器3. 配置线程栈大小

C++ Sort函数使用场景分析

《C++Sort函数使用场景分析》sort函数是algorithm库下的一个函数,sort函数是不稳定的,即大小相同的元素在排序后相对顺序可能发生改变,如果某些场景需要保持相同元素间的相对顺序,可使... 目录C++ Sort函数详解一、sort函数调用的两种方式二、sort函数使用场景三、sort函数排序