当前位置: 首页 > 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 表示第二个参数

相关文章:

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

文章目录 ARM 链接过程分析源文件global_bss_file.cglobal_data_fle.cglobal_function_file.cglobal_rodata_file.cmain.c 链接文件 link.lds编译命令及反汇编命令解析 .o 文件global_bss_file.oglobal_data_fle.oglobal_function_file.oglobal_rodata_file.omain.o 链接观察链…...

Java企业工程项目管理系统+spring cloud 系统管理+java 系统设置+二次开发

工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#xff1a;实现对数据字典标签的增删改查操作 2、编码管理&#xff1a;实现对系统编码的增删改查操作 3、用户管理&#xff1a;管理和查看用户角色 4、菜单管理&#xff1a;实现对系统菜单的增删改查操…...

Eureka与Zookeeper的区别

著名的CAP 理论指出&#xff0c;一个分布式系统不可能同时满足 C( 一致性 ) 、 A( 可用性 ) 和 P( 分区容错性 ) 。 由于分区容错性在是分布式系统中必须要保证的&#xff0c;因此我们只能在 A 和 C 之间进行权衡&#xff0c;在此 Zookeeper 保证的是 CP, 而 Eureka 则是 AP…...

顺序表和链表的各种代码实现

一、线性表 在日常生活中&#xff0c;线性表的例子比比皆是。例如&#xff0c;26个英文字母的字母表&#xff08;A,B,C,……&#xff0c;Z&#xff09;是一个线性表&#xff0c;表中的数据元素式单个字母。在稍复杂的线性表中&#xff0c;一个数据元素可以包含若干个数据项。例…...

C# 介绍三种不同组件创建PDF文档的方式

1 c# 数据保存为PDF&#xff08;一&#xff09; &#xff08;spire pdf篇&#xff09; 2 c# 数据保存为PDF&#xff08;二&#xff09; &#xff08;Aspose pdf篇&#xff09; 3 c# 数据保存为PDF&#xff08;三&#xff09; &#xff08;PdfSharp篇&#xff09; 组件名称 绘制…...

极简面试题 --- Redis

什么是 Redis&#xff1f; Redis 是一个基于内存的键值存储系统&#xff0c;也被称为数据结构服务器。它支持多种数据结构&#xff0c;例如字符串、哈希表、列表、集合和有序集合&#xff0c;并且可以在内存中快速读写。 Redis 的优势有哪些&#xff1f; 快速&#xff1a;由…...

可视化图表API格式要求有哪些?Sugar BI详细代码示例(4)

Sugar BI中的每个图表可以对应一个数据 API&#xff0c;用户浏览报表时&#xff0c;选定一定的过滤条件&#xff0c;点击「查询」按钮将会通过 API 拉取相应的数据&#xff1b;前面说过&#xff0c;为了确保用户数据的安全性&#xff0c;Sugar BI上的所有数据请求都在Sugar BI的…...

学习vue(可与知乎合并)

一&#xff1a;组件及交互 1、什么是组件&#xff1f; 组件是可复用的 Vue 实例&#xff0c;且带有一个名字&#xff1a;在这个例子中是 。我们可以在一个通过 new Vue 创建的 Vue 根实例中&#xff0c;把这个组件作为自定义元素来使用&#xff1a; 声明组件 // 定义一个名…...

【UEFI实战】Linux下如何解析ACPI表

本文介绍如何在Linux下查看ACPI表示。使用的系统是Ubuntu18.04&#xff1a; Linux home 4.15.0-36-generic #39-Ubuntu SMP Mon Sep 24 16:19:09 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux 可以在如下的目录看到ACPI的基本信息&#xff1a; 但是默认的表都是不可以直接查看的&…...

Java-Redis持久化之RDB操作

Java-Redis持久化之RDB操作 1.为什么redis需要持久化&#xff1f;2.什么是RDB操作?3.请你用自己的话讲下RDB的过程?4.如何恢复rdb文件? 1.为什么redis需要持久化&#xff1f; Redis是内存数据库&#xff0c;如果不将内存数据库保存到磁盘&#xff0c;那么服务器进程退出&am…...

信号signal编程测试

信号会打断系统调用&#xff0c;慎用&#xff0c;就是用的时候测一测。 下面是信号的基础测试 信号 信号&#xff08;signal&#xff09;机制是UNIX系统中最为古老的进程之间的通信机制。它用于在一个或多个进程之间传递异步信号。信号可以由各种异步事件产生&#xff0c;例如…...

Linux学习记录——이십삼 进程信号(2)

文章目录 1、可重入函数2、volatile关键字3、如何理解编译器的优化4、SIGCHLD信号 1、可重入函数 两个执行流都执行一个函数时&#xff0c;这个函数就被重入了。比如同一个函数insert&#xff0c;在main中执行时&#xff0c;这个进程时间片到了&#xff0c;嵌入了内核&#xf…...

Revit中如何创建曲面嵌板及一键成板

一、Revit中如何创建曲面嵌板 在我们的绘图过程中可能会遇见一些曲面形状&#xff0c;而我们的常规嵌板没办法满足我们绘制的要求&#xff0c;我们今天学习如何在revit中绘制曲面嵌板。 1.新建“自适应公制常规模型”族&#xff0c;创建4个点图元并为其使用自适应。 2.在相同的…...

STM32F4_DHT11数字温湿度传感器

目录 前言 1. DHT11简介 2. DHT11数据结构 3. DHT11的传输时序 3.1 DHT11开始发送数据流程 3.2 主机复位信号和DHT11响应信号 3.3 数字 “0” 信号表示方法 3.4 数字 “1” 信号表示方法 4. 硬件分析 5. 实验程序详解 5.1 main.c 5.2 DHT11.c 5.3 DHT11.h 前言 DH…...

WiFi(Wireless Fidelity)基础(十一)

目录 一、基本介绍&#xff08;Introduction&#xff09; 二、进化发展&#xff08;Evolution&#xff09; 三、PHY帧&#xff08;&#xff08;PHY Frame &#xff09; 四、MAC帧&#xff08;MAC Frame &#xff09; 五、协议&#xff08;Protocol&#xff09; 六、安全&#x…...

操作系统—— 精髓与设计原理--期末复习

一、计算机系统概述 1、基本构成 计算机有四个主要的结构化部件&#xff1a; ①处理器&#xff08;Processor&#xff09;&#xff1a;控制计算机的操作&#xff0c;执行数据处理功能。当只有一个处理器时&#xff0c;它通常指中央处理器&#xff08;CPU&#xff09; ②内存…...

每天一道算法练习题--Day21 第一章 --算法专题 --- ----------位运算

我这里总结了几道位运算的题目分享给大家&#xff0c;分别是 136 和 137&#xff0c; 260 和 645&#xff0c; 总共加起来四道题。 四道题全部都是位运算的套路&#xff0c;如果你想练习位运算的话&#xff0c;不要错过哦&#xff5e;&#xff5e; 前菜 开始之前我们先了解下…...

D1. LuoTianyi and the Floating Islands (Easy Version)(树形dp)

Problem - D1 - Codeforces 这是问题的简化版本。唯一的区别在于在该版本中k≤min(n,3)。只有在两个版本的问题都解决后&#xff0c;才能进行黑客攻击。 琴音和漂浮的岛屿。 洛天依现在生活在一个有n个漂浮岛屿的世界里。这些漂浮岛屿由n−1个无向航线连接&#xff0c;任意两个…...

rk3588移植ubuntu server

ubuntu server 18.04 arm版本. 1、使用qemu运行 安装qemu-system-aarch64 sudo apt install -y qemu-system-arm 2、下载ubuntu server Index of /releases/18.04.3 3、创建虚拟磁盘 qemu-img create ubuntuimg.img 40G 4、创建虚拟机 弹出界面&#xff0c;直接回车选…...

如何更好地刷力扣

之前刷力扣是一口气看很多题目&#xff0c;打算时不时看一会题解&#xff0c;逐渐熟悉套路&#xff0c;争取背过&#xff0c;最后就可以写出来了。我个人是背知识比较喜欢这种方法&#xff0c;但后来发现根本不适用 算法题本身就比较复杂&#xff0c;不经过实际写代码中的思考…...

上采样和下采样

首先&#xff0c;谈谈不平衡数据集。不平衡数据集指的是训练数据中不同类别的样本数量差别较大的情况。在这种情况下&#xff0c;模型容易出现偏差&#xff0c;导致模型对数量较少的类别预测效果不佳。 为了解决这个问题&#xff0c;可以使用上采样和下采样等方法来调整数据集…...

小猪,信息论与我们的生活

前言 动态规划是大家都熟悉与陌生的知识&#xff0c;非常灵活多变&#xff0c;我自己也不敢说自己掌握了&#xff0c;今天给大家介绍一道题&#xff0c;不仅局限于动态规划做题&#xff0c;还会上升到信息论&#xff0c;乃至于启发自己认知世界的角度 因为比较难&#xff0c;本…...

【鸿蒙应用ArkTS开发系列】- http网络库使用讲解和封装

目录 前言http网络库组件介绍http网络库封装创建Har Module创建RequestOption 配置类创建HttpCore核心类创建HttpManager核心类对外组件导出添加网络权限 http网络库依赖和使用依赖http网络库&#xff08;httpLibrary&#xff09;使用http网络库&#xff08;httpLibrary&#x…...

【Java零基础入门篇】第 ⑥ 期 - 异常处理

博主&#xff1a;命运之光 专栏&#xff1a;Java零基础入门 学习目标 掌握异常的概念&#xff0c;Java中的常见异常类&#xff1b; 掌握Java中如何捕获和处理异常&#xff1b; 掌握自定义异常类及其使用&#xff1b; 目录 异常概述 异常体系 常见的异常 Java的异常处理机制…...

计算职工工资

目录 问题描述 程序设计 问题描述 【问题描述】 给定N个职员的信息,包括姓名、基本工资、浮动工资和支出,要求编写程序顺序输出每位职员的姓名和实发工资(实发工资=基本工资+浮动工资-支出)。 【输入形式】 输入在一行中给出正整数N。随后N行,每行给出一位职员的信息,…...

2019年上半年软件设计师下午试题

试题四(共 15 分) 阅读下列说明和 C 代码&#xff0c;回答问题 1 至 3&#xff0c;将解答写在答题纸的对应栏内 【说明】 n 皇后问题描述为&#xff1a;在一个 n*n 的棋盘上摆放 n 个皇后&#xff0c;要求任意两个皇后不能冲突, 即任意两个皇后不在同一行、同一列或者同一斜…...

IS200TPROH1BCB用于工业应用和电力分配等。高压型隔离开关用于变电站

​ IS200TPROH1BCB用于工业应用和电力分配等。高压型隔离开关用于变电站 什么是隔离器&#xff0c;它与断路器有何不同 什么是隔离器&#xff0c;为什么要使用隔离器 隔离器是一种开关装置&#xff0c;它可以手动或自动操作&#xff0c;隔离一部分电能。隔离器可用于在无负载情…...

【MySql】数据库 select 进阶

数据库 数据库表的设计ER 关系图三大范式 聚合函数与分组查询聚合函数 (count、sum、avg、max、min)分组查询 group by fields....having....(条件) 多表联查内连接外连接&#xff08;左连接&#xff0c;右连接&#xff09;自连接子查询合并查询 UNION 数据库表的设计 ER 关系…...

CVPR 2023 | VoxelNeXt实现全稀疏3D检测跟踪,还能结合Seg Anything

在本文中&#xff0c;研究者提出了一个完全稀疏且以体素为基础的3D物体检测和跟踪框架VoxelNeXt。它采用简单的技术&#xff0c;运行快速&#xff0c;没有太多额外的成本&#xff0c;并且可以在没有NMS后处理的情况下以优雅的方式工作。VoxelNeXt在大规模数据集nuScenes、Waymo…...

本地使用3台centos7虚拟机搭建K8S集群教程

第一步 准备3台centos7虚拟机 3台虚拟机与主机的网络模式都是桥接的模式&#xff0c;也就是他们都是一台独立的“主机” &#xff08;1&#xff09;kebe-master的配置 虚拟机配置&#xff1a; 网络配置&#xff1a; &#xff08;2&#xff09;kebe-node1的配置 虚拟机配…...