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

news/2025/3/15 16:02:52/

文章目录

  • 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.ppmy.cn/news/65820.html

相关文章

网络基础学习:osi网络七层模型

osi网络七层模型 什么是OSI&#xff0c;什么是ISO?为什么ISO要提出OSI网络七层模型&#xff1f;OSI七层的划分以及具体内容第七层 应用层第六层 表示层第五层 会话层第四层 传输层第三层 网络层第二层 数据链路层第一层 物理层 每一层与设备的对应关系 什么是OSI&#xff0c;什…

情感分析讲解

情感分析简述 情感分析(Sentiment Analysis)又称倾向性分析&#xff0c;或意见挖掘&#xff0c;它是对带有情感色彩的主观性文本进行分析、处理、归纳和推理的过程。利用情感分析能力&#xff0c;可以针对带有主观描述的自然语言文本&#xff0c;自动判断该文本的情感正负倾向…

6. 神经网络

6.1 非线性假设 假设有一个监督学习分类问题&#xff0c;训练集如图 如果利用logistic回归来解决这个问题&#xff0c;我们可以构造一个包含很多非线性项的logistic回归函数。 但在这个训练集只给出了两个特征&#xff0c;如果一旦特征变多了&#xff0c;多项式就会变得很多。…

DEV SIT UAT PET SIM PRD PROD常见环境英文缩写含义

一、英文缩写 英文中文 DEV development开发 SIT System Integrate Test系统整合测试&#xff08;内测&#xff09; UAT User Acceptance Test用户验收测试 PET Performance Evaluation Test性能评估测试&#xff08;压测&#xff09; SIM simulation仿真 PRD/PROD produ…

倒计时|数字标准读书会—打破“信息孤岛”、拆除“数据烟囱”

业务与其他业务域间存在信息鸿沟&#xff0c;协作效率低下&#xff1b; 系统边界划分复杂混乱&#xff0c;技术标准不兼容&#xff1b; 新业务无法基于已有解决方案快速组装上线&#xff0c;迭代创新&#xff1b; …… 以上这些数字化转型痛点&#xff0c;你是否也遇到过&a…

长连接 、短连接、心跳机制与断线重连

在不同场景下要考虑长连接还是短连接&#xff0c;那么我们要先了解他。 短连接 概念 client与server通过三次握手建立连接&#xff0c;client发送请求消息&#xff0c;server返回响应&#xff0c;一次连接就完成了。 这时候双方任意都可以发起close操作&#xff0c;不过一般…

模式串匹配算法(朴素模式匹配与KMP)的机算与手算。

一.朴素模式匹配 1.机算 其实就是暴力匹配。 使用双指针 i (指向主串) j (指向模式串) 从主串 S 第一字符起,与模式串 T, 第一个字符比较&#xff0c;   ①若相同&#xff0c;则 i 与 j 统一向后移   ②若遇到 i 与 j 指向字符不同&#xff0c;回溯 i j 指针。继续如此&a…

JVM系列-第6章-方法区

方法区 栈、堆、方法区的交互关系 从线程共享与否的角度来看 ThreadLocal&#xff1a;如何保证多个线程在并发环境下的安全性&#xff1f;典型场景就是数据库连接管理&#xff0c;以及会话管理。 栈、堆、方法区的交互关系 下面涉及了对象的访问定位 Person 类的 .class …