ARM局部变量初始化

时间:2021-07-21 19:37:11

1、函数内部的局部变量如何初始化,如以下程序中的cost_a、const_b、const_c:

extern int main( void )
{
	uint32_t	const_a = 0x12345678;
	uint32_t	const_b = 0x87654321;
	uint32_t	const_c = 0x04;
	
	while(1)
	{
		fun_a(const_a, const_b, const_c);
		fun_b(const_a, const_b, const_c, 123, 1234567);
	}
}

2、编译后,对应的汇编文件片段如下:

//  107 extern int main( void )
//  108 {
main:
        PUSH     {R4-R6,LR}
          CFI R14 Frame(CFA, -4)
          CFI R6 Frame(CFA, -8)
          CFI R5 Frame(CFA, -12)
          CFI R4 Frame(CFA, -16)
          CFI CFA R13+16
        SUB      SP,SP,#+8
          CFI CFA R13+24
//  109 	uint32_t	const_a = 0x12345678;
        LDR      R4,??DataTable0  ;; 0x12345678
//  110 	uint32_t	const_b = 0x87654321;
        LDR      R5,??DataTable0_1  ;; 0x87654321
//  111 	uint32_t	const_c = 0x04;
        MOV      R6,#+4
//  112 	
//  113 	while(1)
//  114 	{
//  115 		fun_a(const_a, const_b, const_c);
??main_0:
        MOVS     R2,R6
        MOVS     R1,R5
        MOVS     R0,R4
          CFI FunCall fun_a
        BL       fun_a
//  116 		fun_b(const_a, const_b, const_c, 123, 1234567);
        LDR      R0,??DataTable0_2  ;; 0x12d687
        STR      R0,[SP, #+0]
        MOV      R3,#+123
        MOVS     R2,R6
        MOVS     R1,R5
        MOVS     R0,R4
          CFI FunCall fun_b
        BL       fun_b
        B        ??main_0
          CFI EndBlock cfiBlock2
//  117 	}
//  118 }

        SECTION `.text`:CODE:NOROOT(2)
        SECTION_TYPE SHT_PROGBITS, 0
        DATA
??DataTable0:
        DC32     0x12345678

        SECTION `.text`:CODE:NOROOT(2)
        SECTION_TYPE SHT_PROGBITS, 0
        DATA
??DataTable0_1:
        DC32     0x87654321

其中:

//  109 uint32_tconst_a = 0x12345678;
        LDR      R4,??DataTable0  ;; 0x12345678
//  110 uint32_tconst_b = 0x87654321;
        LDR      R5,??DataTable0_1  ;; 0x87654321
//  111 uint32_tconst_c = 0x04;
        MOV      R6,#+4

说明在main函数中,使用R4、R5、R6分别保存局部变量const_a、const_b、const_c,并且使用LDR指令、MOV指令来初始化局部变量。LDR指令是寄存器加载指令,LDR指令将内存中指定地址的内容加载到目标寄存器,如上面所示,内存中指定的地址是??DataTable0、??DataTable_1,这些地址对应的内容就是局部变量的初始值:

        SECTION `.text`:CODE:NOROOT(2)
        SECTION_TYPE SHT_PROGBITS, 0
        DATA
??DataTable0:
        DC32     0x12345678

        SECTION `.text`:CODE:NOROOT(2)
        SECTION_TYPE SHT_PROGBITS, 0
        DATA
??DataTable0_1:
        DC32     0x87654321
另外,局部变量const_c,则是使用MOV指令初始化,因为其初始值0x04可以使用MOV指令中的立即数字段表示。若初始值不能使用立即数表示、或者不能通过立即数移位的形式得到,则使用LDR指令完成。


3、

//  109 	uint32_t	const_a = 0x12345678;
        LDR      R4,??DataTable0  ;; 0x12345678
//  110 	uint32_t	const_b = 0x87654321;
        LDR      R5,??DataTable0_1  ;; 0x87654321
//  111 	uint32_t	const_c = 0x04;
LDR指令在寻址时,使用[PC+offset]的形式计算PC相关的内存地址,然后从内存中加载32bit到目标寄存器中。