文章目录
ARM 链接过程分析
源文件
这里新建五个文件
- global_bss_file.c:定义了两个未初始化的全局变量
- global_bss_file.c:定义了两个初始化的全局变量
- global_function_file.c:定义了一个函数,函数实现传入的两个参数相加功能
- global_rodata_file.c:定义了两个只读常量,并初始化
- main.c:使用上述定义的变量和函数
根据上述自定义的链接脚本将这五个. c 文件链接为一个输出文件。编译环境为 arm-none-linux-gnueabihf-
global_bss_file.c
int bss_data1;
int bss_data2;
global_data_fle.c
int test_data1 = 1;
int test_data2 = 2;
global_function_file.c
int test_func(int a, int b)
{
return a + b;
}
global_rodata_file.c
const int rodata_1 = 3;
const int rodata_2 = 4;
main.c
/* rodata */
extern const int rodata_1;
extern const int rodata_2;
/* data */
extern int test_data1;
extern int test_data2;
/* bss data(no init) */
extern int bss_data1;
extern int bss_data2;
/* code */
extern int test_func(int a, int b);
int main (int argc, int *argv[])
{
bss_data1 = test_func(test_data1, test_data2);
bss_data2 = test_func(rodata_1, rodata_2);
return 0;
}
链接文件 link.lds
SECTIONS
{
. = 0x00900000;
.text :
{
*(.text)
}
.rodata :
{
*(.rodata)
}
. = 0x80000000;
.data :
{
*(.data)
}
.bss :
{
*(.bss)
}
}
编译命令及反汇编命令
命令示例
arm-none-linux-gnueabihf-gcc -c global_bss_file.c
arm-none-linux-gnueabihf-objdump -h global_bss_file.o > global_bss_file.sec
arm-none-linux-gnueabihf-objdump -s -d global_bss_file.o > global_bss_file.info
使用上述命令编译源文件之后会生成 global_bss_file.o/sec/info
,global_data_fle.o/sec/info
, global_function_file.o/sec/info
,global_rodata_file.o/sec/info
, 和 main.o/sec/info
等文件。
解析 .o 文件
global_bss_file.o
命令
arm-none-linux-gnueabihf-objdump -h global_bss_file.o >global_bss_file.sec
section,以及对应的 VMA 和 LMA
global_bss_file.o: file format elf32-littlearm
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000000 00000000 00000000 00000034 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000000 00000000 00000000 00000034 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000008 00000000 00000000 00000034 2**2
ALLOC
3 .comment 0000005e 00000000 00000000 00000034 2**0
CONTENTS, READONLY
4 .note.GNU-stack 00000000 00000000 00000000 00000092 2**0
CONTENTS, READONLY
5 .ARM.attributes 00000035 00000000 00000000 00000092 2**0
CONTENTS, READONLY
global_bss_file.o 有六个 sections 分别是
- .text:代码段,没有包含任何有用的代码信息,所以 .text 段为 0
- .data:数据段,没有已经初始化的数据,所以 .data 段是 0
- .bss:未初始化变量段 8,源码总定义了两个 int 数据,所以 .bss 段的长度为 8
- .comment:存放一些 GNU 的通用信息
- .note.GNU-stack:GNU 的注释信息
- .ARM.attributes:编译器相关信息
使用下面命令查看详细信息
arm-none-linux-gnueabihf-objdump -s -d global_bss_file.o >global_bss_file.info
命令返回结果如下
global_bss_file.o: file format elf32-littlearm
Contents of section .comment:
0000 00474343 3a202847 4e552054 6f6f6c63 .GCC: (GNU Toolc
0010 6861696e 20666f72 20746865 20412d70 hain for the A-p
0020 726f6669 6c652041 72636869 74656374 rofile Architect
0030 75726520 31302e33 2d323032 312e3037 ure 10.3-2021.07
0040 20286172 6d2d3130 2e323929 29203130 (arm-10.29)) 10
0050 2e332e31 20323032 31303632 3100 .3.1 20210621.
Contents of section .ARM.attributes:
0000 41340000 00616561 62690001 2a000000 A4...aeabi..*...
0010 05372d41 00060a07 41080109 020a030c .7-A....A.......
0020 01120414 01150117 03180119 011a021c ................
0030 011e0622 01 ...".
- 由于还未链接,没有 .bss 段的相关信息
global_data_fle.o
命令
arm-none-linux-gnueabihf-objdump -h global_data_fle.o >global_data_fle.sec
section,以及对应的 VMA 和 LMA
global_data_fle.o: file format elf32-littlearm
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000000 00000000 00000000 00000034 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000008 00000000 00000000 00000034 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 0000003c 2**0
ALLOC
3 .comment 0000005e 00000000 00000000 0000003c 2**0
CONTENTS, READONLY
4 .note.GNU-stack 00000000 00000000 00000000 0000009a 2**0
CONTENTS, READONLY
5 .ARM.attributes 00000035 00000000 00000000 0000009a 2**0
CONTENTS, READONLY
global_data_fle.o 同样有六个 sections 分别是
- .text:代码段,没有包含任何有用的代码信息,所以 .text 段为 0
- .data:数据段长度为 8,定义了两个 int 型全局变量并初始化,int 的长度是 4 个字节,两个 int 于是占用了 8 个字节,所以 .data 段的长度为 8
- .bss:没有未初始化的变量,所以 .bss 段为 0
- .comment:存放一些 GNU 的通用信息
- .note.GNU-stack:GNU 的注释信息
- .ARM.attributes:编译器相关信息
使用下面命令查看详细信息
arm-none-linux-gnueabihf-objdump -s -d global_data_fle.o >global_data_fle.info
命令结果如下
global_data_fle.o: file format elf32-littlearm
Contents of section .data:
0000 01000000 02000000 ........
Contents of section .comment:
0000 00474343 3a202847 4e552054 6f6f6c63 .GCC: (GNU Toolc
0010 6861696e 20666f72 20746865 20412d70 hain for the A-p
0020 726f6669 6c652041 72636869 74656374 rofile Architect
0030 75726520 31302e33 2d323032 312e3037 ure 10.3-2021.07
0040 20286172 6d2d3130 2e323929 29203130 (arm-10.29)) 10
0050 2e332e31 20323032 31303632 3100 .3.1 20210621.
Contents of section .ARM.attributes:
0000 41340000 00616561 62690001 2a000000 A4...aeabi..*...
0010 05372d41 00060a07 41080109 020a030c .7-A....A.......
0020 01120414 01150117 03180119 011a021c ................
0030 011e0622 01 ...".
-
由于还未链接,所以 .data 段的数据起始地址为
0
-
data.o 里面只有 .data 段的数据,并且长度为 8 个字节,小端模式,的确包含了 01000000 以及 02000000 两个全局变量的数据。
global_function_file.o
命令
arm-none-linux-gnueabihf-objdump -h global_function_file.o >global_function_file.sec
section,以及对应的 VMA 和 LMA
global_function_file.o: file format elf32-littlearm
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 0000001c 00000000 00000000 00000034 2**1
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000000 00000000 00000000 00000050 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 00000050 2**0
ALLOC
3 .comment 0000005e 00000000 00000000 00000050 2**0
CONTENTS, READONLY
4 .note.GNU-stack 00000000 00000000 00000000 000000ae 2**0
CONTENTS, READONLY
5 .ARM.attributes 00000035 00000000 00000000 000000ae 2**0
CONTENTS, READONLY
global_function_file.o 同样有六个 sections 分别是
- .text:代码段,文件中定义了一个函数,所以 .text 的数据长度不为 0
- .data:数据段,未定义任何数据,所以为 .data 段的长度为 0
- .bss:没有未初始化的变量,所以 .bss 段的长度为 0
- .comment:存放一些 GNU 的通用信息
- .note.GNU-stack:GNU 的注释信息
- .ARM.attributes:编译器相关信息
使用下面命令查看详细信息
arm-none-linux-gnueabihf-objdump -s -d global_function_file.o >global_function_file.info
命令结果如下
global_function_file.o: file format elf32-littlearm
Contents of section .text:
0000 80b483b0 00af7860 39607a68 3b681344 ......x`9`zh;h.D
0010 18460c37 bd465df8 047b7047 .F.7.F]..{pG
Contents of section .comment:
0000 00474343 3a202847 4e552054 6f6f6c63 .GCC: (GNU Toolc
0010 6861696e 20666f72 20746865 20412d70 hain for the A-p
0020 726f6669 6c652041 72636869 74656374 rofile Architect
0030 75726520 31302e33 2d323032 312e3037 ure 10.3-2021.07
0040 20286172 6d2d3130 2e323929 29203130 (arm-10.29)) 10
0050 2e332e31 20323032 31303632 3100 .3.1 20210621.
Contents of section .ARM.attributes:
0000 41340000 00616561 62690001 2a000000 A4...aeabi..*...
0010 05372d41 00060a07 41080109 020a030c .7-A....A.......
0020 01120414 01150117 03180119 011a021c ................
0030 011e0622 01 ...".
Disassembly of section .text:
00000000 <test_func>:
0: b480 push {r7}
2: b083 sub sp, #12
4: af00 add r7, sp, #0
6: 6078 str r0, [r7, #4]
8: 6039 str r1, [r7, #0]
a: 687a ldr r2, [r7, #4]
c: 683b ldr r3, [r7, #0]
e: 4413 add r3, r2
10: 4618 mov r0, r3
12: 370c adds r7, #12
14: 46bd mov sp, r7
16: f85d 7b04 ldr.w r7, [sp], #4
1a: 4770 bx lr
-
由于还未链接,所以代码段 .text 的起始地址为
0
-
global_function_file.o 里面只有 .text 段的数据,其代码实现数据相加功能。
global_rodata_file.o
objdump 解析命令
arm-none-linux-gnueabihf-objdump -h global_rodata_file.o >global_rodata_file.sec
objdump 解析结果:section,以及对应的 VMA 和 LMA
global_rodata_file.o: file format elf32-littlearm
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000000 00000000 00000000 00000034 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000000 00000000 00000000 00000034 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 00000034 2**0
ALLOC
3 .rodata 00000008 00000000 00000000 00000034 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .comment 0000005e 00000000 00000000 0000003c 2**0
CONTENTS, READONLY
5 .note.GNU-stack 00000000 00000000 00000000 0000009a 2**0
CONTENTS, READONLY
6 .ARM.attributes 00000035 00000000 00000000 0000009a 2**0
CONTENTS, READONLY
global_rodata_file.o 有七个 sections 分别是
- .text:代码段,由于没有代码,所以 .text 段的长度为 0
- .data:没有全局初始化的数据,所以 .data 段的长度为 0
- .bss:没有未初始化的全局数据,所以 .bss 段的长度为 0
- .rodata:数据段长度为 8,定义了两个 int 型全局只读常量并初始化,int 的长度是 4 个字节,两个 int 于是占用了 8 个字节,所以 .data 段的长度为 8。
- .comment:存放一些 GNU 的通用信息
- .note.GNU-stack:GNU 的注释信息
- .ARM.attributes:编译器相关信息
使用下面命令查看详细信息
arm-none-linux-gnueabihf-objdump -s -d global_rodata_file.o >global_rodata_file.info
命令结果如下
global_rodata_file.o: file format elf32-littlearm
Contents of section .rodata:
0000 03000000 04000000 ........
Contents of section .comment:
0000 00474343 3a202847 4e552054 6f6f6c63 .GCC: (GNU Toolc
0010 6861696e 20666f72 20746865 20412d70 hain for the A-p
0020 726f6669 6c652041 72636869 74656374 rofile Architect
0030 75726520 31302e33 2d323032 312e3037 ure 10.3-2021.07
0040 20286172 6d2d3130 2e323929 29203130 (arm-10.29)) 10
0050 2e332e31 20323032 31303632 3100 .3.1 20210621.
Contents of section .ARM.attributes:
0000 41340000 00616561 62690001 2a000000 A4...aeabi..*...
0010 05372d41 00060a07 41080109 020a030c .7-A....A.......
0020 01120414 01150117 03180119 011a021c ................
0030 011e0622 01 ...".
- 由于还未链接,所以 .rodata 段的起始地址为 0。
main.o
objdump 解析命令
arm-none-linux-gnueabihf-objdump -h main.o >main.sec
objdump 解析结果:section,以及对应的 VMA 和 LMA
main.o: file format elf32-littlearm
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000064 00000000 00000000 00000034 2**1
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data 00000000 00000000 00000000 00000098 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 00000098 2**0
ALLOC
3 .comment 0000005e 00000000 00000000 00000098 2**0
CONTENTS, READONLY
4 .note.GNU-stack 00000000 00000000 00000000 000000f6 2**0
CONTENTS, READONLY
5 .ARM.attributes 00000035 00000000 00000000 000000f6 2**0
CONTENTS, READONLY
main.o 有六个 sections 分别是
- .text:代码段,文件中定义了几个函数,所以 .text 的数据长度不为 0
- .data:没有全局初始化的数据,所以 .data 段的长度为 0
- .bss:没有未初始化的全局数据,所以 .bss 段的长度为 0
- .comment:存放一些 GNU 的通用信息
- .note.GNU-stack:GNU 的注释信息
- .ARM.attributes:编译器相关信息
使用下面命令查看详细信息
arm-none-linux-gnueabihf-objdump -s -d main.o >main.info
命令结果如下
main.o: file format elf32-littlearm
Contents of section .text:
0000 80b582b0 00af7860 396040f2 0003c0f2 ......x`9`@.....
0010 00031a68 40f20003 c0f20003 1b681946 ...h@........h.F
0020 1046fff7 feff0246 40f20003 c0f20003 .F.....F@.......
0030 1a6040f2 0003c0f2 00031a68 40f20003 .`@........h@...
0040 c0f20003 1b681946 1046fff7 feff0246 .....h.F.F.....F
0050 40f20003 c0f20003 1a600023 18460837 @........`.#.F.7
0060 bd4680bd .F..
Contents of section .comment:
0000 00474343 3a202847 4e552054 6f6f6c63 .GCC: (GNU Toolc
0010 6861696e 20666f72 20746865 20412d70 hain for the A-p
0020 726f6669 6c652041 72636869 74656374 rofile Architect
0030 75726520 31302e33 2d323032 312e3037 ure 10.3-2021.07
0040 20286172 6d2d3130 2e323929 29203130 (arm-10.29)) 10
0050 2e332e31 20323032 31303632 3100 .3.1 20210621.
Contents of section .ARM.attributes:
0000 41340000 00616561 62690001 2a000000 A4...aeabi..*...
0010 05372d41 00060a07 41080109 020a030c .7-A....A.......
0020 01120414 01150117 03180119 011a021c ................
0030 011e0622 01 ...".
Disassembly of section .text:
00000000 <main>:
0: b580 push {r7, lr}
2: b082 sub sp, #8
4: af00 add r7, sp, #0
6: 6078 str r0, [r7, #4]
8: 6039 str r1, [r7, #0]
a: f240 0300 movw r3, #0
e: f2c0 0300 movt r3, #0
12: 681a ldr r2, [r3, #0]
14: f240 0300 movw r3, #0
18: f2c0 0300 movt r3, #0
1c: 681b ldr r3, [r3, #0]
1e: 4619 mov r1, r3
20: 4610 mov r0, r2
22: f7ff fffe bl 0 <test_func>
26: 4602 mov r2, r0
28: f240 0300 movw r3, #0
2c: f2c0 0300 movt r3, #0
30: 601a str r2, [r3, #0]
32: f240 0300 movw r3, #0
36: f2c0 0300 movt r3, #0
3a: 681a ldr r2, [r3, #0]
3c: f240 0300 movw r3, #0
40: f2c0 0300 movt r3, #0
44: 681b ldr r3, [r3, #0]
46: 4619 mov r1, r3
48: 4610 mov r0, r2
4a: f7ff fffe bl 0 <test_func>
4e: 4602 mov r2, r0
50: f240 0300 movw r3, #0
54: f2c0 0300 movt r3, #0
58: 601a str r2, [r3, #0]
5a: 2300 movs r3, #0
5c: 4618 mov r0, r3
5e: 3708 adds r7, #8
60: 46bd mov sp, r7
62: bd80 pop {r7, pc}
-
由于还未链接,所以代码起始地址为
0
-
第 22 行可以看到一个跳转指令,表示需要链接的位置
f7ff fffe bl 0 <test_func>
有一个标签
<test_func>
,bl 目前跳转的地方是 0 地址,后期连接器会把这个值改回来 -
变量的赋值时通过如下汇编语句实现,可以看到变量的值都是 0,后期链接器会将这两个值改为真正的
test_data1
和test_data2
等数据。
test_data1:a: f240 0300 movw r3, #0 e: f2c0 0300 movt r3, #0 12: 681a ldr r2, [r3, #0] 20: 4610 mov r0, r2
movw
将一个 16 位数据移动到寄存器的低 16 位,并把高 16 位清零。movt
将一个 16 位数据移动到寄存器的高 16 位,低 16 位不处理。- 所以此时 r3 寄存器的值为 0,接着将 r3 寄存器的值解引用的值,加载到 r2
- 函数调用时,将 r2 寄存器的值放到 r0 寄存器中,r0 在函数调用时,传递的是第一个参数
test_data2:
14: f240 0300 movw r3, #0 18: f2c0 0300 movt r3, #0 1c: 681b ldr r3, [r3, #0] 1e: 4619 mov r1, r3
movw
将一个 16 位数据移动到寄存器的低 16 位,并把高 16 位清零。movt
将一个 16 位数据移动到寄存器的高 16 位,低 16 位不处理。- 所以此时 r3 寄存器的值为 0,接着将 r3 寄存器的值解引用的值,加载到 r3
- 函数调用时,将 r3 寄存器的值放到 r1 寄存器中,r1 在函数调用时,传递的是第二个参数
链接
上面描述中有五个 .o 文件,分别是
- global_bss_file.o 定义了 2 个未初始化的全局变量
- global_data_fle.o 定义了 2 个初始化的全局变量
- global_function_file.o 定义了一个函数
- global_rodata_file.o 定义了 2 个只读常量
- main.o 使用上面定义的函数和变量
在链接之前并不知道数据的具体数值,也不知道调用函数的函数位置,因此事先会把不知道的信息空出来,等到链接的时候再合并。因此接下来要观察链接的结果。
使用链接命令
arm-none-linux-gnueabihf-ld global_bss_file.o global_data_fle.o global_function_file.o global_rodata_file.o main.o -T link.lds -o test
得到输出文件 test
使用
arm-none-linux-gnueabihf-objdump -h test > test.sec
命令返回结果如下
test: file format elf32-littlearm
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000080 00900000 00900000 00010000 2**1
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .rodata 00000008 00900080 00900080 00010080 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .data 00000008 80000000 80000000 00020000 2**2
CONTENTS, ALLOC, LOAD, DATA
3 .bss 00000008 80000008 80000008 00020008 2**2
ALLOC
4 .comment 0000005d 00000000 00000000 00020008 2**0
CONTENTS, READONLY
5 .ARM.attributes 00000035 00000000 00000000 00020065 2**0
CONTENTS, READONLY
test 有六个 sections 分别是
- .text
- .rodata
- .data
- .bss
- .comment
- .ARM.attributes。
可以看到链接后的 test 文件的 .text,.data,.rodata,和 .bss 等段的 size 是多个 .o 文件的和。
使用下面命令查看详细信息
arm-none-linux-gnueabihf-objdump -s -d test >test.info
命令结果如下
test: file format elf32-littlearm
Contents of section .text:
900000 80b483b0 00af7860 39607a68 3b681344 ......x`9`zh;h.D
900010 18460c37 bd465df8 047b7047 80b582b0 .F.7.F]..{pG....
900020 00af7860 396040f2 0003c8f2 00031a68 ..x`9`@........h
900030 40f20403 c8f20003 1b681946 1046fff7 @........h.F.F..
900040 dfff0246 40f20803 c8f20003 1a6040f2 ...F@........`@.
900050 8003c0f2 90031a68 40f28403 c0f29003 .......h@.......
900060 1b681946 1046fff7 cbff0246 40f20c03 .h.F.F.....F@...
900070 c8f20003 1a600023 18460837 bd4680bd .....`.#.F.7.F..
Contents of section .rodata:
900080 03000000 04000000 ........
Contents of section .data:
80000000 01000000 02000000 ........
Contents of section .comment:
0000 4743433a 2028474e 5520546f 6f6c6368 GCC: (GNU Toolch
0010 61696e20 666f7220 74686520 412d7072 ain for the A-pr
0020 6f66696c 65204172 63686974 65637475 ofile Architectu
0030 72652031 302e332d 32303231 2e303720 re 10.3-2021.07
0040 2861726d 2d31302e 32392929 2031302e (arm-10.29)) 10.
0050 332e3120 32303231 30363231 00 3.1 20210621.
Contents of section .ARM.attributes:
0000 41340000 00616561 62690001 2a000000 A4...aeabi..*...
0010 05372d41 00060a07 41080109 020a030c .7-A....A.......
0020 01120414 01150117 03180119 011a021c ................
0030 011e0622 01 ...".
Disassembly of section .text:
00900000 <test_func>:
900000: b480 push {r7}
900002: b083 sub sp, #12
900004: af00 add r7, sp, #0
900006: 6078 str r0, [r7, #4]
900008: 6039 str r1, [r7, #0]
90000a: 687a ldr r2, [r7, #4]
90000c: 683b ldr r3, [r7, #0]
90000e: 4413 add r3, r2
900010: 4618 mov r0, r3
900012: 370c adds r7, #12
900014: 46bd mov sp, r7
900016: f85d 7b04 ldr.w r7, [sp], #4
90001a: 4770 bx lr
0090001c <main>:
90001c: b580 push {r7, lr}
90001e: b082 sub sp, #8
900020: af00 add r7, sp, #0
900022: 6078 str r0, [r7, #4]
900024: 6039 str r1, [r7, #0]
900026: f240 0300 movw r3, #0
90002a: f2c8 0300 movt r3, #32768 ; 0x8000
90002e: 681a ldr r2, [r3, #0]
900030: f240 0304 movw r3, #4
900034: f2c8 0300 movt r3, #32768 ; 0x8000
900038: 681b ldr r3, [r3, #0]
90003a: 4619 mov r1, r3
90003c: 4610 mov r0, r2
90003e: f7ff ffdf bl 900000 <test_func>
900042: 4602 mov r2, r0
900044: f240 0308 movw r3, #8
900048: f2c8 0300 movt r3, #32768 ; 0x8000
90004c: 601a str r2, [r3, #0]
90004e: f240 0380 movw r3, #128 ; 0x80
900052: f2c0 0390 movt r3, #144 ; 0x90
900056: 681a ldr r2, [r3, #0]
900058: f240 0384 movw r3, #132 ; 0x84
90005c: f2c0 0390 movt r3, #144 ; 0x90
900060: 681b ldr r3, [r3, #0]
900062: 4619 mov r1, r3
900064: 4610 mov r0, r2
900066: f7ff ffcb bl 900000 <test_func>
90006a: 4602 mov r2, r0
90006c: f240 030c movw r3, #12
900070: f2c8 0300 movt r3, #32768 ; 0x8000
900074: 601a str r2, [r3, #0]
900076: 2300 movs r3, #0
900078: 4618 mov r0, r3
90007a: 3708 adds r7, #8
90007c: 46bd mov sp, r7
90007e: bd80 pop {r7, pc}
观察链接前后的差异
地址变化
- 链接之后,代码起始地址为:0x00900000
- 链接之后,数据起始地址为:0x80000000
main.o
- 原先 bl 0 位置被连接器替换为了 bl 900000。而 900000 刚好是 test_func 的代码地址
90003e: f7ff ffdf bl 900000 <test_func>
- 全局变量的地址
900026: f240 0300 movw r3, #0 90002a: f2c8 0300 movt r3, #32768 ; 0x8000 90002e: 681a ldr r2, [r3, #0] 90003c: 4610 mov r0, r2
movw
将一个 16 位数据移动到寄存器的低 16 位,并把高 16 位清零。movt
将一个 16 位数据移动到寄存器的高 16 位,低 16 位不处理。- 所以此时 r3 寄存器的值为
0x80000000
- 将 r3 寄存器的值解引用后放到 r2 寄存器中,所以此时 r2 寄存器的值为
0x01
- 函数调用时,将 r2 寄存器的值给到 r0,所以
r0
的值为0x01
表示第一个参数
900030: f240 0304 movw r3, #4 900034: f2c8 0300 movt r3, #32768 ; 0x8000 900038: 681b ldr r3, [r3, #0] 90003a: 4619 mov r1, r3
movw
将一个 16 位数据移动到寄存器的低 16 位,并把高 16 位清零。movt
将一个 16 位数据移动到寄存器的高 16 位,低 16 位不处理。- 所以此时 r3 寄存器的值为
0x80000004
- 将 r3 寄存器的值解引用后放到 r3 寄存器中,所以此时 r3 寄存器的值为
0x02
- 函数调用时,将 r3 寄存器的值给到 r1,所以
r1
的值为0x02
表示第二个参数