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

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

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

1、之前的汇编代码

; Reset handler
Reset_Handler   PROC
                EXPORT  Reset_Handler             [WEAK]
                IMPORT  __main
                IMPORT  SystemInit
                LDR     R0, =SystemInit
                BLX     R0               
                LDR     R0, =__main
                BX      R0
                ENDP

汇编代码这部分呢,大家一般都不会陌生,我们也通常都认为是__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位置,

    __Vectors
        0x08000000:    20000410    ...     DCD    536871952
        0x08000004:    08000145    E...    DCD    134218053
        0x08000008:    08000d81    ....    DCD    134221185

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

    Reset_Handler
        0x08000144:    4806        .H      LDR      r0,[pc,#24] ; [0x8000160] = 0x8000e17
        0x08000146:    4780        .G      BLX      r0
        0x08000148:    4806        .H      LDR      r0,[pc,#24] ; [0x8000164] = 0x8000131
        0x0800014a:    4700        .G      BX       r0

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

    _main_stk
        0x08000130:    f8dfd00c    ....    LDR      sp,__lit__00000000 ; [0x8000140] = 0x20000410
    .ARM.Collect$$$$00000004
    _main_scatterload
        0x08000134:    f000f82a    ..*.    BL       __scatterload ; 0x800018c

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

    __scatterload
    __scatterload_rt2
        0x0800018c:    4c06        .L      LDR      r4,[pc,#24] ; [0x80001a8] = 0x8000ec4
        0x0800018e:    4d07        .M      LDR      r5,[pc,#28] ; [0x80001ac] = 0x8000ee4
        0x08000190:    e006        ..      B        0x80001a0 ; __scatterload + 20
        0x08000192:    68e0        .h      LDR      r0,[r4,#0xc]
        0x08000194:    f0400301    @...    ORR      r3,r0,#1
        0x08000198:    e8940007    ....    LDM      r4,{r0-r2}
        0x0800019c:    4798        .G      BLX      r3
        0x0800019e:    3410        .4      ADDS     r4,r4,#0x10
        0x080001a0:    42ac        .B      CMP      r4,r5
        0x080001a2:    d3f6        ..      BCC      0x8000192 ; __scatterload + 6
        0x080001a4:    f7ffffc8    ....    BL       __main_after_scatterload ; 0x8000138

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

    __main_after_scatterload
    _main_clock
    _main_cpp_init
    _main_init
        0x08000138:    4800        .H      LDR      r0,[pc,#0] ; [0x800013c] = 0x8000e75
        0x0800013a:    4700        .G      BX       r0

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

    i.main
    main
        0x08000e74:    bf00        ..      NOP      
        0x08000e76:    f7ffff9e    ....    BL       SystemClock_Config ; 0x8000db6
        0x08000e7a:    f7ffff2b    ..+.    BL       LED_GPIO_Config ; 0x8000cd4
        0x08000e7e:    e012        ..      B        0x8000ea6 ; main + 50
        0x08000e80:    2200        ."      MOVS     r2,#0
        0x08000e82:    f44f5100    O..Q    MOV      r1,#0x2000
        0x08000e86:    4808        .H      LDR      r0,[pc,#32] ; [0x8000ea8] = 0x40011000
        0x08000e88:    f7fffb4a    ..J.    BL       HAL_GPIO_WritePin ; 0x8000520
        0x08000e8c:    f44f707a    O.zp    MOV      r0,#0x3e8
        0x08000e90:    f7fff992    ....    BL       HAL_Delay ; 0x80001b8
        0x08000e94:    2201        ."      MOVS     r2,#1
        0x08000e96:    0351        Q.      LSLS     r1,r2,#13
        0x08000e98:    4803        .H      LDR      r0,[pc,#12] ; [0x8000ea8] = 0x40011000
        0x08000e9a:    f7fffb41    ..A.    BL       HAL_GPIO_WritePin ; 0x8000520
        0x08000e9e:    f44f707a    O.zp    MOV      r0,#0x3e8
        0x08000ea2:    f7fff989    ....    BL       HAL_Delay ; 0x80001b8
        0x08000ea6:    e7eb        ..      B        0x8000e80 ; main + 12

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

4、总结

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

相关推荐
hairenjing11231 小时前
使用 Mac 数据恢复从 iPhoto 图库中恢复照片
windows·stm32·嵌入式硬件·macos·word
模拟IC攻城狮3 小时前
华为海思招聘-芯片与器件设计工程师-模拟芯片方向- 机试题-真题套题题目——共8套(每套四十题)
嵌入式硬件·华为·硬件架构·芯片
IT B业生3 小时前
51单片机教程(六)- LED流水灯
单片机·嵌入式硬件·51单片机
一枝小雨3 小时前
51单片机学习心得2(基于STC89C52):串口通信(UART)
单片机·嵌入式硬件·51单片机
IT B业生4 小时前
51单片机教程(一)- 开发环境搭建
单片机·嵌入式硬件·51单片机
海绵波波1076 小时前
Webserver(4.8)UDP、广播、组播
单片机·网络协议·udp
好想有猫猫6 小时前
【51单片机】串口通信原理 + 使用
c语言·单片机·嵌入式硬件·51单片机·1024程序员节
云卓科技6 小时前
无人车之路径规划篇
人工智能·嵌入式硬件·算法·自动驾驶
stm 学习ing8 小时前
C语言 循环高级
c语言·开发语言·单片机·嵌入式硬件·算法·嵌入式实时数据库
w微信150135078128 小时前
小华一级 代理商 HC32F005C6PA-TSSOP20 HC32F005系列
c语言·arm开发·单片机·嵌入式硬件