EXPORT __scatterload_rt2
ER_IROM1:0800311C __scatterload_rt2 ; CODE XREF: _main_scatterload↑p
ER_IROM1:0800311C 06 4C LDR R4, =Region$$Table$$Base
ER_IROM1:0800311E 07 4D LDR R5, =Region$$Table$$Limit
ER_IROM1:08003120 06 E0 B loc_8003130
ER_IROM1:08003120
ER_IROM1:08003122 ; ---------------------------------------------------------------------------
ER_IROM1:08003122
ER_IROM1:08003122 loc_8003122 ; CODE XREF: ER_IROM1:08003132↓j
ER_IROM1:08003122 E0 68 LDR R0, [R4,#0xC]
ER_IROM1:08003124 40 F0 01 03 ORR.W R3, R0, #1
ER_IROM1:08003128 94 E8 07 00 LDM.W R4, {R0-R2}
ER_IROM1:0800312C 98 47 BLX R3
ER_IROM1:0800312C
ER_IROM1:0800312E 10 34 ADDS R4, #0x10
ER_IROM1:0800312E
ER_IROM1:08003130
ER_IROM1:08003130 loc_8003130 ; CODE XREF: ER_IROM1:08003120↑j
ER_IROM1:08003130 AC 42 CMP R4, R5
ER_IROM1:08003132 F6 D3 BCC loc_8003122
ER_IROM1:08003132
ER_IROM1:08003134 FC F7 DE FF BL _main_init
ER_IROM1:08003134
ER_IROM1:08003134 ; ---------------------------------------------------------------------------
ER_IROM1:08003138 F8 3E 00 08 off_8003138 DCD Region$$Table$$Base ; DATA XREF: ER_IROM1:__scatterload_rt2↑r
ER_IROM1:0800313C 18 3F 00 08 off_800313C DCD Region$$Table$$Limit ; DATA XREF: ER_IROM1:0800311E↑r
ER_IROM1:08003140
EXPORT _main_init
ER_IROM1:080000F4 _main_init ; CODE XREF: ER_IROM1:08003134↓p
ER_IROM1:080000F4 00 48 LDR R0, =(main+1) ; argc
ER_IROM1:080000F6 00 47 BX R0
extern uint32_t Region$$Table$$Base;
extern uint32_t Region$$Table$$Limit;
//&Region$$Table$$Base compress data, bss
//&Region$$Table$$Limit the end of data bss
//data: 0x10 [Region$$Table$$Limit = compress data start] [ram base addr 0x20000000] [data size] [decompression function]
//bss : 0x10 [LOAD ends,the code end = compress data end] [ram addr start of bss segment] [bss size] [bss clear function]
ER_IROM1:0800315C ; =============== S U B R O U T I N E =======================================
ER_IROM1:0800315C
ER_IROM1:0800315C
ER_IROM1:0800315C ; int __fastcall _decompress1(char *in_buff, _BYTE *out_buff, int len)
ER_IROM1:0800315C EXPORT __decompress1
ER_IROM1:0800315C __decompress1
ER_IROM1:0800315C 70 B5 PUSH {R4-R6,LR}
ER_IROM1:0800315E 01 EB 02 04 ADD.W R4, R1, R2
ER_IROM1:0800315E
ER_IROM1:08003162
ER_IROM1:08003162 loc_8003162 ; CODE XREF: __decompress1+56↓j
ER_IROM1:08003162 10 F8 01 5B LDRB.W R5, [R0],#1
ER_IROM1:08003166 15 F0 07 03 ANDS.W R3, R5, #7
ER_IROM1:0800316A 01 D1 BNE loc_8003170
ER_IROM1:0800316A
ER_IROM1:0800316C 10 F8 01 3B LDRB.W R3, [R0],#1
ER_IROM1:0800316C
ER_IROM1:08003170
ER_IROM1:08003170 loc_8003170 ; CODE XREF: __decompress1+E↑j
ER_IROM1:08003170 2A 11 ASRS R2, R5, #4
ER_IROM1:08003172 06 D1 BNE loc_8003182
ER_IROM1:08003172
ER_IROM1:08003174 10 F8 01 2B LDRB.W R2, [R0],#1
ER_IROM1:08003178 03 E0 B loc_8003182
ER_IROM1:08003178
ER_IROM1:0800317A ; ---------------------------------------------------------------------------
ER_IROM1:0800317A
ER_IROM1:0800317A loc_800317A ; CODE XREF: __decompress1+28↓j
ER_IROM1:0800317A 10 F8 01 6B LDRB.W R6, [R0],#1
ER_IROM1:0800317E 01 F8 01 6B STRB.W R6, [R1],#1
ER_IROM1:0800317E
ER_IROM1:08003182
ER_IROM1:08003182 loc_8003182 ; CODE XREF: __decompress1+16↑j
ER_IROM1:08003182 ; __decompress1+1C↑j
ER_IROM1:08003182 5B 1E SUBS R3, R3, #1
ER_IROM1:08003184 F9 D1 BNE loc_800317A
ER_IROM1:08003184
ER_IROM1:08003186 2B 07 LSLS R3, R5, #0x1C
ER_IROM1:08003188 05 D4 BMI loc_8003196
ER_IROM1:08003188
ER_IROM1:0800318A 00 23 MOVS R3, #0
ER_IROM1:0800318A
ER_IROM1:0800318C
ER_IROM1:0800318C loc_800318C ; CODE XREF: __decompress1+38↓j
ER_IROM1:0800318C 52 1E SUBS R2, R2, #1
ER_IROM1:0800318E 0F D4 BMI loc_80031B0
ER_IROM1:0800318E
ER_IROM1:08003190 01 F8 01 3B STRB.W R3, [R1],#1
ER_IROM1:08003194 FA E7 B loc_800318C
ER_IROM1:08003194
ER_IROM1:08003196 ; ---------------------------------------------------------------------------
ER_IROM1:08003196
ER_IROM1:08003196 loc_8003196 ; CODE XREF: __decompress1+2C↑j
ER_IROM1:08003196 10 F8 01 3B LDRB.W R3, [R0],#1
ER_IROM1:0800319A 02 F1 02 02 ADD.W R2, R2, #2
ER_IROM1:0800319E A1 EB 03 03 SUB.W R3, R1, R3
ER_IROM1:080031A2 03 E0 B loc_80031AC
ER_IROM1:080031A2
ER_IROM1:080031A4 ; ---------------------------------------------------------------------------
ER_IROM1:080031A4
ER_IROM1:080031A4 loc_80031A4 ; CODE XREF: __decompress1+52↓j
ER_IROM1:080031A4 13 F8 01 5B LDRB.W R5, [R3],#1
ER_IROM1:080031A8 01 F8 01 5B STRB.W R5, [R1],#1
ER_IROM1:080031A8
ER_IROM1:080031AC
ER_IROM1:080031AC loc_80031AC ; CODE XREF: __decompress1+46↑j
ER_IROM1:080031AC 52 1E SUBS R2, R2, #1
ER_IROM1:080031AE F9 D5 BPL loc_80031A4
ER_IROM1:080031AE
ER_IROM1:080031B0
ER_IROM1:080031B0 loc_80031B0 ; CODE XREF: __decompress1+32↑j
ER_IROM1:080031B0 A1 42 CMP R1, R4
ER_IROM1:080031B2 D6 D3 BCC loc_8003162
ER_IROM1:080031B2
ER_IROM1:080031B4 00 20 MOVS R0, #0
ER_IROM1:080031B6 70 BD POP {R4-R6,PC}
ER_IROM1:080031B6
ER_IROM1:080031B6 ; End of function __decompress1
ER_IROM1:080031B6
ER_IROM1:080031B8
int _decompress1( unsigned char *in_buff, unsigned char *out_buff, int len )
{
unsigned char *end;
int temp;
int ctrl;
int copy_len;
int ref_len;
int offset;
int cnt;
unsigned char *i;
end = &out_buff[len];
do {
ctrl = *in_buff++;
temp = ctrl;
copy_len = ctrl & 7;
if ((ctrl & 7) == 0) {
copy_len = *in_buff++;
}
ref_len = temp >> 4;
if( ref_len == 0x00 ) {
ref_len = *in_buff++;
}
while (--copy_len){
*out_buff++ = *in_buff++;
}
if ((temp & 8) != 0){
offset = *in_buff++;
cnt = ref_len + 2;
for (i = &out_buff[-offset]; --cnt >= 0; ++i) {
*out_buff++ = i[0];
}
}else {
while (--ref_len >= 0){
*out_buff++ = 0;
}
}
} while (out_buff < end);
return 0;
}
EXPORT Region$$Table$$Base
ER_IROM1:08003EF8 18 3F 00 08 Region$$Table$$Base DCD Region$$Table$$Limit
ER_IROM1:08003EF8 ; DATA XREF: ER_IROM1:__scatterload_rt2↑o
ER_IROM1:08003EF8 ; ER_IROM1:off_8003138↑o
ER_IROM1:08003EFC 00 00 00 20 DCD SystemCoreClock
ER_IROM1:08003F00 3C 03 00 00 DCD 0x33C
ER_IROM1:08003F04 5C 31 00 08 dword_8003F04 DCD 0x800315C ; DATA XREF: ER_IROM1:loc_8003122↑r
ER_IROM1:08003F08 D8 3F 00 08 DCD 0x8003FD8
ER_IROM1:08003F0C 3C 03 00 20 DCD rxBuffer
ER_IROM1:08003F10 5C 0F 00 00 14 32 00 08 DCD 0xF5C, 0x8003214
ER_IROM1:08003F10 ; ER_IROM1 ends
早期:data段是直接拷贝的,没有压缩
现在:armcc.exe v5.06 data段是压缩存储的,启动时需要解压缩。
bss段还是老套路,直接清零。
其实对于这种修改,启动代码只需修改一个函数指针就行,整个程序架构都不会变。由data段拷贝函数改成data段解压函数。
这种玩法,类似uboot的启动初始化代码,遍历一个初始化函数指针表,逐个执行其中的初始化函数。
具体stm32这个表中,有2个函数指针,第一个指向解压缩data的函数,r0-r3是函数的参数,总共占用16字节
第二个指向bss清零的函数,构造也类似。
Reset_Handler
LDR R0, =(SystemInit+1)
BLX R0 ; SystemInit
LDR R0, =(_main_stk+1)
BX R0
; void NMI_Handler()
ER_IROM1:08000108 WEAK NMI_Handler
ER_IROM1:08000108 NMI_Handler ; CODE XREF: NMI_Handler↓j
ER_IROM1:08000108 ; DATA XREF: ER_IROM1:08000008↑o
ER_IROM1:08000108 FE E7 B NMI_Handler
ER_IROM1:08000108
_main_stk:
LDR.W SP, =0x20001298
EXPORT _main_scatterload
ER_IROM1:080000F0 _main_scatterload
ER_IROM1:080000F0 03 F0 14 F8 BL __scatterload_rt2
ER_IROM1:080000F0
ER_IROM1:080000F0 ; End of function _main_scatterload
ER_IROM1:080000F0
ER_IROM1:080000F4
ER_IROM1:080000F4 ; =============== S U B R O U T I N E =======================================
ER_IROM1:080000F4
ER_IROM1:080000F4
ER_IROM1:080000F4 ; int __cdecl main_init(int argc, const char **argv, const char **envp)
ER_IROM1:080000F4 EXPORT _main_init
ER_IROM1:080000F4 _main_init ; CODE XREF: ER_IROM1:08003134↓p
ER_IROM1:080000F4 00 48 LDR R0, =(main+1) ; argc
ER_IROM1:080000F6 00 47 BX R0
ER_IROM1:080000F6
ER_IROM1:080000F6 ; ---------------------------------------------------------------------------
ER_IROM1:080000F8 ; const int argc
ER_IROM1:080000F8 D7 04 00 08 argc DCD main+1 ; DATA XREF: _main_init↑r
ER_IROM1:080000F8 ; End of function _main_init
ER_IROM1:080000F8
ER_IROM1:080000FC EXPORT __rt_final_exit
ER_IROM1:080000FC 98 12 00 20 __rt_final_exit DCD 0x20001298 ; DATA XREF: _main_stk↑r
ER_IROM1:08000100
可以看到 从
BL __scatterload_rt2
返回后,就会进入c语言的main函数。
__scatterload_rt2这个函数就是前面描述的 data段解压缩和bss段清零程序。