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

这篇具有很好参考价值的文章主要介绍了qemu-基础篇——ARM 链接过程分析(六)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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-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_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-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

命令结果如下文章来源地址https://www.toymoban.com/news/detail-443339.html

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 表示第二个参数

到了这里,关于qemu-基础篇——ARM 链接过程分析(六)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • QEMU搭建arm虚拟机开发环境

    使用git指令切换到对应的分支上,我这里使用的是stable-4.0的分支 git checkout -b stable-4.0 remotes/origin/stable-4.0 在工程的根目录下执行 ./configure --target-list=aarch64-linux-user,aarch64-softmmu --enable-virtfs --enable-debug 然后执行make,视情况是否要执行make install

    2024年01月25日
    浏览(38)
  • 深入分析arm的程序启动过程内存分配和加载区域运行区域的关系

    STM32的启动过程一 启动代码 启动代码由MCU研发商提供。 MCU一上电,首先执行的是启动代码,她是一个汇编代码。 以stm32f1为例: 首先定义堆栈,然后定义中断向量表,然后执行复位中断服务函数Reset_Handler ; Reset handler Reset_Handler PROC EXPORT Reset_Handler [WEAK] IMPORT __main IMPORT Syste

    2024年02月19日
    浏览(44)
  • Linux 之搭建 arm 的 qemu 模拟器

    2024年02月03日
    浏览(42)
  • MINIX 3 系统之搭建QEMU ARM运行环境

      MINIX 3是一个比较完善的微内核架构的类unix系统。如果想要了解和学习操作系统,Linux肯定是首选,而且几乎所学即所用。但是,如今的Linux已经复杂到一定层度,即便有丰富的视频和书籍作为参考,想通过Linux以窥操作系统之精髓,继而自己实现一个系统,个人认为不是

    2024年02月02日
    浏览(40)
  • VSCode+GDB+Qemu调试ARM64 linux内核

    俗话说,工欲善其事 必先利其器。linux kernel是一个非常复杂的系统,初学者会很难入门。 如果有一个方便的调试环境,学习效率至少能有5-10倍的提升。 为了学习linux内核,通常有这两个需要 可以摆脱硬件,方便的编译和运行linux 可以使用图形化的工具来调试linux 笔者使用

    2024年02月08日
    浏览(43)
  • 手把手教你搭建ARM32 QEMU环境

    我们知道嵌入式开发调试就要和各种硬件打交道,所以学习就要专门购买各种开发版,浪费资金,开会演示效果还需要携带一大串的板子和电线,不胜其烦。然而Qemu的使用可以避免频繁在开发板上烧写版本,如果进行的调试工作与外设无关,仅仅是内核方面的调试,Qemu模拟

    2024年02月19日
    浏览(54)
  • Qemu虚拟arm开发板驱动开发详解(一)——驱动基本架构

            此前在《WSL2下Ubuntu22.04使用Qemu搭建虚拟Vexpress-A9开发板》系列文章中,我们已建立好Linux最小系统的运行环境,并将其成功移植到了由Qemu模拟的arm32开发板上。接下来将介绍如何基于上述环境进行驱动开发。         本节主要带各位读者了解Linux内核驱动的基本架

    2024年02月05日
    浏览(44)
  • ARM Linux 调试 -QEMU启动 Uboot/Kernel/Rootfs

    懒人方式: 直接去方锐/qemu克隆项目,执行script目录的脚本即可 1. build_env.sh安装环境 2. build_rootfs.sh 生成rootfs 3. build_kernel.sh编译kernel 4. qemu_run.sh开始调试 2.1busybox代码的下载编译 Busybox下载地址:https://busybox.net/downloads/ Download 1.36.0 Busybox 默认会安装到 ./_install 目录下 制作ro

    2024年02月02日
    浏览(57)
  • 在Ubuntu上用Qemu模拟ARM版本的Fedora39

    Fedora Quick Docs Fedora Server Documentation Deploy an ARM64 Fedora VM on your PC: 3 steps Architectures/AArch64/Install with QEMU Virtualization – Getting Started Fedora on Raspberry Pi Architectures/ARM ARM Single Board Computer (SBC) Installation Creating a virtual machine using Fedora Server Edition disk image 8 Linux virsh subcommands for managing VM

    2024年03月27日
    浏览(42)
  • 银河麒麟服务器arm、x86安装qemu虚拟机

    使用下面的命令安装的话只能安装同构的虚拟机,如arm的就只能安装arm的;x86的就只能安装x86的 等待安装完成 直接复制脚本执行即可 使用源码编译安装就能创建异构的虚拟机了,比如:在arm服务器上创建x86的,在x86上创建arm的 我测试使用的是qemu-4.2.0.tar.xz这个版本,因为我

    2024年02月02日
    浏览(70)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包