当前位置: 首页 > news >正文

qemu-基础篇——ARM 链接过程分析(六)

文章目录

  • ARM 链接过程分析
    • 源文件
      • global_bss_file.c
      • global_data_fle.c
      • global_function_file.c
      • global_rodata_file.c
      • main.c
    • 链接文件 link.lds
    • 编译命令及反汇编命令
    • 解析 .o 文件
      • global_bss_file.o
      • global_data_fle.o
      • global_function_file.o
      • global_rodata_file.o
      • main.o
    • 链接
    • 观察链接前后的差异
      • 地址变化
      • main.o

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/infoglobal_data_fle.o/sec/infoglobal_function_file.o/sec/infoglobal_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-littlearmSections:
Idx Name          Size      VMA       LMA       File off  Algn0 .text         00000000  00000000  00000000  00000034  2**0CONTENTS, ALLOC, LOAD, READONLY, CODE1 .data         00000000  00000000  00000000  00000034  2**0CONTENTS, ALLOC, LOAD, DATA2 .bss          00000008  00000000  00000000  00000034  2**2ALLOC3 .comment      0000005e  00000000  00000000  00000034  2**0CONTENTS, READONLY4 .note.GNU-stack 00000000  00000000  00000000  00000092  2**0CONTENTS, READONLY5 .ARM.attributes 00000035  00000000  00000000  00000092  2**0CONTENTS, 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-littlearmContents of section .comment:0000 00474343 3a202847 4e552054 6f6f6c63  .GCC: (GNU Toolc0010 6861696e 20666f72 20746865 20412d70  hain for the A-p0020 726f6669 6c652041 72636869 74656374  rofile Architect0030 75726520 31302e33 2d323032 312e3037  ure 10.3-2021.070040 20286172 6d2d3130 2e323929 29203130   (arm-10.29)) 100050 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-littlearmSections:
Idx Name          Size      VMA       LMA       File off  Algn0 .text         00000000  00000000  00000000  00000034  2**0CONTENTS, ALLOC, LOAD, READONLY, CODE1 .data         00000008  00000000  00000000  00000034  2**2CONTENTS, ALLOC, LOAD, DATA2 .bss          00000000  00000000  00000000  0000003c  2**0ALLOC3 .comment      0000005e  00000000  00000000  0000003c  2**0CONTENTS, READONLY4 .note.GNU-stack 00000000  00000000  00000000  0000009a  2**0CONTENTS, READONLY5 .ARM.attributes 00000035  00000000  00000000  0000009a  2**0CONTENTS, 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-littlearmContents of section .data:0000 01000000 02000000                    ........
Contents of section .comment:0000 00474343 3a202847 4e552054 6f6f6c63  .GCC: (GNU Toolc0010 6861696e 20666f72 20746865 20412d70  hain for the A-p0020 726f6669 6c652041 72636869 74656374  rofile Architect0030 75726520 31302e33 2d323032 312e3037  ure 10.3-2021.070040 20286172 6d2d3130 2e323929 29203130   (arm-10.29)) 100050 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-littlearmSections:
Idx Name          Size      VMA       LMA       File off  Algn0 .text         0000001c  00000000  00000000  00000034  2**1CONTENTS, ALLOC, LOAD, READONLY, CODE1 .data         00000000  00000000  00000000  00000050  2**0CONTENTS, ALLOC, LOAD, DATA2 .bss          00000000  00000000  00000000  00000050  2**0ALLOC3 .comment      0000005e  00000000  00000000  00000050  2**0CONTENTS, READONLY4 .note.GNU-stack 00000000  00000000  00000000  000000ae  2**0CONTENTS, READONLY5 .ARM.attributes 00000035  00000000  00000000  000000ae  2**0CONTENTS, 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-littlearmContents of section .text:0000 80b483b0 00af7860 39607a68 3b681344  ......x`9`zh;h.D0010 18460c37 bd465df8 047b7047           .F.7.F]..{pG
Contents of section .comment:0000 00474343 3a202847 4e552054 6f6f6c63  .GCC: (GNU Toolc0010 6861696e 20666f72 20746865 20412d70  hain for the A-p0020 726f6669 6c652041 72636869 74656374  rofile Architect0030 75726520 31302e33 2d323032 312e3037  ure 10.3-2021.070040 20286172 6d2d3130 2e323929 29203130   (arm-10.29)) 100050 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, #124:	af00      	add	r7, sp, #06:	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, r210:	4618      	mov	r0, r312:	370c      	adds	r7, #1214:	46bd      	mov	sp, r716:	f85d 7b04 	ldr.w	r7, [sp], #41a:	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-littlearmSections:
Idx Name          Size      VMA       LMA       File off  Algn0 .text         00000000  00000000  00000000  00000034  2**0CONTENTS, ALLOC, LOAD, READONLY, CODE1 .data         00000000  00000000  00000000  00000034  2**0CONTENTS, ALLOC, LOAD, DATA2 .bss          00000000  00000000  00000000  00000034  2**0ALLOC3 .rodata       00000008  00000000  00000000  00000034  2**2CONTENTS, ALLOC, LOAD, READONLY, DATA4 .comment      0000005e  00000000  00000000  0000003c  2**0CONTENTS, READONLY5 .note.GNU-stack 00000000  00000000  00000000  0000009a  2**0CONTENTS, READONLY6 .ARM.attributes 00000035  00000000  00000000  0000009a  2**0CONTENTS, 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-littlearmContents of section .rodata:0000 03000000 04000000                    ........
Contents of section .comment:0000 00474343 3a202847 4e552054 6f6f6c63  .GCC: (GNU Toolc0010 6861696e 20666f72 20746865 20412d70  hain for the A-p0020 726f6669 6c652041 72636869 74656374  rofile Architect0030 75726520 31302e33 2d323032 312e3037  ure 10.3-2021.070040 20286172 6d2d3130 2e323929 29203130   (arm-10.29)) 100050 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-littlearmSections:
Idx Name          Size      VMA       LMA       File off  Algn0 .text         00000064  00000000  00000000  00000034  2**1CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE1 .data         00000000  00000000  00000000  00000098  2**0CONTENTS, ALLOC, LOAD, DATA2 .bss          00000000  00000000  00000000  00000098  2**0ALLOC3 .comment      0000005e  00000000  00000000  00000098  2**0CONTENTS, READONLY4 .note.GNU-stack 00000000  00000000  00000000  000000f6  2**0CONTENTS, READONLY5 .ARM.attributes 00000035  00000000  00000000  000000f6  2**0CONTENTS, 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-littlearmContents of section .text:0000 80b582b0 00af7860 396040f2 0003c0f2  ......x`9`@.....0010 00031a68 40f20003 c0f20003 1b681946  ...h@........h.F0020 1046fff7 feff0246 40f20003 c0f20003  .F.....F@.......0030 1a6040f2 0003c0f2 00031a68 40f20003  .`@........h@...0040 c0f20003 1b681946 1046fff7 feff0246  .....h.F.F.....F0050 40f20003 c0f20003 1a600023 18460837  @........`.#.F.70060 bd4680bd                             .F..
Contents of section .comment:0000 00474343 3a202847 4e552054 6f6f6c63  .GCC: (GNU Toolc0010 6861696e 20666f72 20746865 20412d70  hain for the A-p0020 726f6669 6c652041 72636869 74656374  rofile Architect0030 75726520 31302e33 2d323032 312e3037  ure 10.3-2021.070040 20286172 6d2d3130 2e323929 29203130   (arm-10.29)) 100050 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, #84:	af00      	add	r7, sp, #06:	6078      	str	r0, [r7, #4]8:	6039      	str	r1, [r7, #0]a:	f240 0300 	movw	r3, #0e:	f2c0 0300 	movt	r3, #012:	681a      	ldr	r2, [r3, #0]14:	f240 0300 	movw	r3, #018:	f2c0 0300 	movt	r3, #01c:	681b      	ldr	r3, [r3, #0]1e:	4619      	mov	r1, r320:	4610      	mov	r0, r222:	f7ff fffe 	bl	0 <test_func>26:	4602      	mov	r2, r028:	f240 0300 	movw	r3, #02c:	f2c0 0300 	movt	r3, #030:	601a      	str	r2, [r3, #0]32:	f240 0300 	movw	r3, #036:	f2c0 0300 	movt	r3, #03a:	681a      	ldr	r2, [r3, #0]3c:	f240 0300 	movw	r3, #040:	f2c0 0300 	movt	r3, #044:	681b      	ldr	r3, [r3, #0]46:	4619      	mov	r1, r348:	4610      	mov	r0, r24a:	f7ff fffe 	bl	0 <test_func>4e:	4602      	mov	r2, r050:	f240 0300 	movw	r3, #054:	f2c0 0300 	movt	r3, #058:	601a      	str	r2, [r3, #0]5a:	2300      	movs	r3, #05c:	4618      	mov	r0, r35e:	3708      	adds	r7, #860:	46bd      	mov	sp, r762:	bd80      	pop	{r7, pc}
  • 由于还未链接,所以代码起始地址为 0

  • 第 22 行可以看到一个跳转指令,表示需要链接的位置

    f7ff fffe 	bl	0 <test_func>
    

    有一个标签 <test_func>,bl 目前跳转的地方是 0 地址,后期连接器会把这个值改回来

  • 变量的赋值时通过如下汇编语句实现,可以看到变量的值都是 0,后期链接器会将这两个值改为真正的 test_data1test_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-littlearmSections:
Idx Name          Size      VMA       LMA       File off  Algn0 .text         00000080  00900000  00900000  00010000  2**1CONTENTS, ALLOC, LOAD, READONLY, CODE1 .rodata       00000008  00900080  00900080  00010080  2**2CONTENTS, ALLOC, LOAD, READONLY, DATA2 .data         00000008  80000000  80000000  00020000  2**2CONTENTS, ALLOC, LOAD, DATA3 .bss          00000008  80000008  80000008  00020008  2**2ALLOC4 .comment      0000005d  00000000  00000000  00020008  2**0CONTENTS, READONLY5 .ARM.attributes 00000035  00000000  00000000  00020065  2**0CONTENTS, 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-littlearmContents of section .text:900000 80b483b0 00af7860 39607a68 3b681344  ......x`9`zh;h.D900010 18460c37 bd465df8 047b7047 80b582b0  .F.7.F]..{pG....900020 00af7860 396040f2 0003c8f2 00031a68  ..x`9`@........h900030 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 Toolch0010 61696e20 666f7220 74686520 412d7072  ain for the A-pr0020 6f66696c 65204172 63686974 65637475  ofile Architectu0030 72652031 302e332d 32303231 2e303720  re 10.3-2021.070040 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, #12900004:	af00      	add	r7, sp, #0900006:	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, r2900010:	4618      	mov	r0, r3900012:	370c      	adds	r7, #12900014:	46bd      	mov	sp, r7900016:	f85d 7b04 	ldr.w	r7, [sp], #490001a:	4770      	bx	lr0090001c <main>:90001c:	b580      	push	{r7, lr}90001e:	b082      	sub	sp, #8900020:	af00      	add	r7, sp, #0900022:	6078      	str	r0, [r7, #4]900024:	6039      	str	r1, [r7, #0]900026:	f240 0300 	movw	r3, #090002a:	f2c8 0300 	movt	r3, #32768	; 0x800090002e:	681a      	ldr	r2, [r3, #0]900030:	f240 0304 	movw	r3, #4900034:	f2c8 0300 	movt	r3, #32768	; 0x8000900038:	681b      	ldr	r3, [r3, #0]90003a:	4619      	mov	r1, r390003c:	4610      	mov	r0, r290003e:	f7ff ffdf 	bl	900000 <test_func>900042:	4602      	mov	r2, r0900044:	f240 0308 	movw	r3, #8900048:	f2c8 0300 	movt	r3, #32768	; 0x800090004c:	601a      	str	r2, [r3, #0]90004e:	f240 0380 	movw	r3, #128	; 0x80900052:	f2c0 0390 	movt	r3, #144	; 0x90900056:	681a      	ldr	r2, [r3, #0]900058:	f240 0384 	movw	r3, #132	; 0x8490005c:	f2c0 0390 	movt	r3, #144	; 0x90900060:	681b      	ldr	r3, [r3, #0]900062:	4619      	mov	r1, r3900064:	4610      	mov	r0, r2900066:	f7ff ffcb 	bl	900000 <test_func>90006a:	4602      	mov	r2, r090006c:	f240 030c 	movw	r3, #12900070:	f2c8 0300 	movt	r3, #32768	; 0x8000900074:	601a      	str	r2, [r3, #0]900076:	2300      	movs	r3, #0900078:	4618      	mov	r0, r390007a:	3708      	adds	r7, #890007c:	46bd      	mov	sp, r790007e:	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 表示第二个参数
http://www.lryc.cn/news/66821.html

相关文章:

  • Java企业工程项目管理系统+spring cloud 系统管理+java 系统设置+二次开发
  • Eureka与Zookeeper的区别
  • 顺序表和链表的各种代码实现
  • C# 介绍三种不同组件创建PDF文档的方式
  • 极简面试题 --- Redis
  • 可视化图表API格式要求有哪些?Sugar BI详细代码示例(4)
  • 学习vue(可与知乎合并)
  • 【UEFI实战】Linux下如何解析ACPI表
  • Java-Redis持久化之RDB操作
  • 信号signal编程测试
  • Linux学习记录——이십삼 进程信号(2)
  • Revit中如何创建曲面嵌板及一键成板
  • STM32F4_DHT11数字温湿度传感器
  • WiFi(Wireless Fidelity)基础(十一)
  • 操作系统—— 精髓与设计原理--期末复习
  • 每天一道算法练习题--Day21 第一章 --算法专题 --- ----------位运算
  • D1. LuoTianyi and the Floating Islands (Easy Version)(树形dp)
  • rk3588移植ubuntu server
  • 如何更好地刷力扣
  • 上采样和下采样
  • 小猪,信息论与我们的生活
  • 【鸿蒙应用ArkTS开发系列】- http网络库使用讲解和封装
  • 【Java零基础入门篇】第 ⑥ 期 - 异常处理
  • 计算职工工资
  • 2019年上半年软件设计师下午试题
  • IS200TPROH1BCB用于工业应用和电力分配等。高压型隔离开关用于变电站
  • 【MySql】数据库 select 进阶
  • CVPR 2023 | VoxelNeXt实现全稀疏3D检测跟踪,还能结合Seg Anything
  • 本地使用3台centos7虚拟机搭建K8S集群教程
  • NVIDIA CUDA驱动安装