打印
[MCU]

编译后,变量在MCU中的处理流程

[复制链接]
668|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 terryzhouhz 于 2022-5-5 22:06 编辑

在开发mcu代码的时候经常会有些疑惑,变量是怎么在编译之后进入单片机的ram区的呢,特别是在使用keil开发的时候。后来在接触gcc编译器和自研的mcu后,终于明白了这个问题。实际上变量编译后被放在了bin文件中代码的后面(data存放在bin中,bss在bin里存放了长度信息)。程序运行时会主动将该区域的数据依次加载到ram区域中。
原理
写完代码编译后,会把code中的data区的变量放在代码的后面,bss区的变量仅存放长度在bin中,当然这个规则也是由链接文件来决定的。示例图如下



在程序运行后正式进入C环境前,code中会存在一段汇编代码。主要作用就是把data区域内存依次复制到ram中,复制结束后。把后面和bss区描述长度一致区域的内存全置为0。
通过这也能够看出为什么bss区域的值会被设置为0,因为内存中是没有类型的说法。如果不全置0,无论其它哪个值都没法确认实际类型的值。(例如设置为1的话,不同的类型就会对应不同的值。int是0x1111,short是0x11)
但是在keil中我们没有看到这样的代码。keil的汇编代码如下:
Reset_Handler   PROC                EXPORT  Reset_Handler                          IMPORT  SystemInit               
IMPORT  __main               
LDR     R0, =SystemInit               
BLX     R0               
LDR     R0, =__main               
BX      R0               
ENDP
这段代码执行完毕后会跳转到__main函数里执行,主要注意的是这里并不是直接跳转到我们编写的main函数里。在__main有很多的操作,其中就包括将变量加载到ram区域中。执行完毕后才会跳转到我们自己开发的main函数中执行。
示例分析
下面这段代码就是gcc编译器下加载变量的代码。其中有几个变量,data在bin文件中的起始地址,data在ram区的起始、结束地址,bss在ram区的起始、结束地址都是通过ld文件中获取的。
运行完下面的code后,程序中的所有变量都被加载到了ram区域中。
/*
*  The ranges of copy from/to are specified by following symbols
*    __etext: LMA of start of the section to copy from. Usually end of text
*    __data_start__: VMA of start of the section to copy to
*    __data_end__: VMA of end of the section to copy to
* *  All addresses must be aligned to 4 bytes boundary. */   
lrw     r1, __erodata       // data在bin文件中的起始地址   
lrw     r2, __data_start__  // data在ram中的起始地址   
lrw     r3, __data_end__    // data在ram中的结束地址   
subu    r3, r2              // r3为data的长度   
cmpnei  r3, 0               // 判断长度是否为0   
bf      .L_loop0_done


.L_loop0:                       // 将bin文件中数据依次移到ram中   
ldw     r0, (r1, 0)              
stw     r0, (r2, 0)            
addi    r1, 4   
addi    r2, 4   
subi    r3, 4   
cmpnei  r3, 0   
bt      


.L_loop0.L_loop0_done:
/*
*  The BSS section is specified by following symbols
*    __bss_start__: start of the BSS section.
*    __bss_end__: end of the BSS section.
* *  Both addresses must be aligned to 4 bytes boundary. */   
lrw     r1, __bss_start__   
lrw     r2, __bss_end__   
movi    r0, 0   
subu    r2, r1   
cmpnei  r2, 0   
bf      


.L_loop1_done.L_loop1:                       // 将bss里的数据复制为0   
stw     
r0, (r1, 0)   
addi    r1, 4   
subi    r2, 4   
cmpnei  r2, 0   
bt      
.L_loop1.L_loop1_done:


使用特权

评论回复

相关帖子

沙发
meeagle| | 2022-5-6 09:42 | 只看该作者
这简直就是瞎子“隔空摸象”

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

73

主题

104

帖子

1

粉丝