c语言位置无关码,位置无关码、位置有关码、链接地址、加载地址

本文详细分析了ARM指令集中的BBL指令、ADR和LDR指令在不同加载地址下的行为,以及C函数调用中全局变量和局部变量的处理方式。对于BBL指令,其相对跳转特性使其成为位置无关码;ADR指令能获取标号的实际地址,无论加载地址如何;LDR指令加载标号地址时则与加载地址有关。C函数中,全局变量和函数调用的地址与加载地址有关,而局部变量的存储则不受影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SECTIONS { . = 0x33f80000; .text : { *(.text) } . = ALIGN(4); .rodata : {*(.rodata*)} . = ALIGN(4); .data : { *(.data) } . = ALIGN(4); __bss_start = .; .bss : { *(.bss) *(COMMON) } __bss_end = .; }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

SECTIONS{

.=0x33f80000;

.text:{*(.text)}

.=ALIGN(4);

.rodata:{*(.rodata*)}

.=ALIGN(4);

.data:{*(.data)}

.=ALIGN(4);

__bss_start=.;

.bss:{*(.bss)*(COMMON)}

__bss_end=.;

}

.text .global _start _start: bl close_watch_dog /* 相对跳转,位置无关 */ bl _start adr r0, close_watch_dog /* 获取标号地址,位置无关 */ ldr r0, SMRDATA /* 获取标号处的值,位置无关 */ ldr r0, =0x12345678 ldr r0, =SMRDATA /* 获取标号地址,位置有关 */ ldr r0, =main /* 获取函数名的地址,位置有关 */ ldr r0 ,=__bss_start /* 获取链接脚本里标号的地址,位置有关 */ close_watch_dog: mov r1, #0 str r1, [r0] mov pc, lr SMRDATA: .word 0x22111120

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

.text

.global_start

_start:

blclose_watch_dog/* 相对跳转,位置无关 */

bl_start

adrr0,close_watch_dog/* 获取标号地址,位置无关 */

ldrr0,SMRDATA/* 获取标号处的值,位置无关 */

ldrr0,=0x12345678

ldrr0,=SMRDATA/* 获取标号地址,位置有关 */

ldrr0,=main/* 获取函数名的地址,位置有关 */

ldrr0,=__bss_start/* 获取链接脚本里标号的地址,位置有关 */

close_watch_dog:

movr1,#0

strr1,[r0]

movpc,lr

SMRDATA:

.word0x22111120

int a; void abc(){ a = 2; } int main(){ int b; a =1 ; b =1 ; abc(); return 0; }

1

2

3

4

5

6

7

8

9

10

11

inta;

voidabc(){

a=2;

}

intmain(){

intb;

a=1;

b=1;

abc();

return0;

}

如果加载地址为 0 ,那么代码将按照下面的顺序排放

00000000 <_start>: 00000000: eb000006 bl 33f80020 00000004: ebfffffd bl 33f80000 <_start> 00000008: e28f0010 add r0, pc, #16 0000000c: e59f0018 ldr r0, [pc, #24] ; 00000010: e59f0018 ldr r0, [pc, #24] ; 00000014: e59f0018 ldr r0, [pc, #24] ; 00000018: e59f0018 ldr r0, [pc, #24] ; 0000001c: e59f0018 ldr r0, [pc, #24] ; 00000020 : 00000020: e3a01000 mov r1, #0 00000024: e5801000 str r1, [r0] 00000028: e1a0f00e mov pc, lr 0000002c : 0000002c: 22111120 andscs r1, r1, #8 00000030: 12345678 eorsne r5, r4, #125829120 ; 0x7800000 00000034: 33f8002c mvnscc r0, #44 ; 0x2c 00000038: 33f80064 mvnscc r0, #100 ; 0x64 0000003c: 33f800a0 mvnscc r0, #160 ; 0xa0 00000040 : 00000040: e52db004 push {fp} ; (str fp, [sp, #-4]!) 00000044: e28db000 add fp, sp, #0 00000048: e59f3010 ldr r3, [pc, #16] ; 33f80060 0000004c: e3a02002 mov r2, #2 00000050: e5832000 str r2, [r3] 00000054: e28bd000 add sp, fp, #0 00000058: e8bd0800 pop {fp} 0000005c: e12fff1e bx lr 00000060: 33f800a0 mvnscc r0, #160 ; 0xa0 00000064 : 00000064: e92d4800 push {fp, lr} 00000068: e28db004 add fp, sp, #4 0000006c: e24dd008 sub sp, sp, #8 00000070: e59f3024 ldr r3, [pc, #36] ; 33f8009c 00000074: e3a02001 mov r2, #1 00000078: e5832000 str r2, [r3] 0000007c: e3a03001 mov r3, #1 00000080: e50b3008 str r3, [fp, #-8] 00000084: ebffffed bl 33f80040 00000088: e3a03000 mov r3, #0 0000008c: e1a00003 mov r0, r3 00000090: e24bd004 sub sp, fp, #4 00000094: e8bd4800 pop {fp, lr} 00000098: e12fff1e bx lr 0000009c: 33f800a0 mvnscc r0, #160 ; 0xa0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

00000000<_start>:

00000000:eb000006bl33f80020

00000004:ebfffffdbl33f80000<_start>

00000008:e28f0010addr0,pc,#16

0000000c:e59f0018ldrr0,[pc,#24]   ;

00000010:e59f0018ldrr0,[pc,#24]   ;

00000014:e59f0018ldrr0,[pc,#24]   ;

00000018:e59f0018ldrr0,[pc,#24]   ;

0000001c:e59f0018ldrr0,[pc,#24]   ;

00000020:

00000020:e3a01000movr1,#0

00000024:e5801000strr1,[r0]

00000028:e1a0f00emovpc,lr

0000002c:

0000002c:22111120andscsr1,r1,#8

00000030:12345678eorsner5,r4,#125829120  ; 0x7800000

00000034:33f8002cmvnsccr0,#44 ; 0x2c

00000038:33f80064mvnsccr0,#100    ; 0x64

0000003c:33f800a0mvnsccr0,#160    ; 0xa0

00000040:

00000040:e52db004push{fp};(strfp,[sp,#-4]!)

00000044:e28db000addfp,sp,#0

00000048:e59f3010ldrr3,[pc,#16]   ; 33f80060

0000004c:e3a02002movr2,#2

00000050:e5832000strr2,[r3]

00000054:e28bd000addsp,fp,#0

00000058:e8bd0800pop{fp}

0000005c:e12fff1ebxlr

00000060:33f800a0mvnsccr0,#160    ; 0xa0

00000064:

00000064:e92d4800push{fp,lr}

00000068:e28db004addfp,sp,#4

0000006c:e24dd008subsp,sp,#8

00000070:e59f3024ldrr3,[pc,#36]   ; 33f8009c

00000074:e3a02001movr2,#1

00000078:e5832000strr2,[r3]

0000007c:e3a03001movr3,#1

00000080:e50b3008strr3,[fp,#-8]

00000084:ebffffedbl33f80040

00000088:e3a03000movr3,#0

0000008c:e1a00003movr0,r3

00000090:e24bd004subsp,fp,#4

00000094:e8bd4800pop{fp,lr}

00000098:e12fff1ebxlr

0000009c:33f800a0mvnsccr0,#160    ; 0xa0

如果加载地址为0x33f80000 则按照下边的顺序排放

33f80000 <_start>: 33f80000: eb000006 bl 33f80020 33f80004: ebfffffd bl 33f80000 <_start> 33f80008: e28f0010 add r0, pc, #16 33f8000c: e59f0018 ldr r0, [pc, #24] ; 33f8002c 33f80010: e59f0018 ldr r0, [pc, #24] ; 33f80030 33f80014: e59f0018 ldr r0, [pc, #24] ; 33f80034 33f80018: e59f0018 ldr r0, [pc, #24] ; 33f80038 33f8001c: e59f0018 ldr r0, [pc, #24] ; 33f8003c 33f80020 : 33f80020: e3a01000 mov r1, #0 33f80024: e5801000 str r1, [r0] 33f80028: e1a0f00e mov pc, lr 33f8002c : 33f8002c: 22111120 andscs r1, r1, #8 33f80030: 12345678 eorsne r5, r4, #125829120 ; 0x7800000 33f80034: 33f8002c mvnscc r0, #44 ; 0x2c 33f80038: 33f80064 mvnscc r0, #100 ; 0x64 33f8003c: 33f800a0 mvnscc r0, #160 ; 0xa0 33f80040 : 33f80040: e52db004 push {fp} ; (str fp, [sp, #-4]!) 33f80044: e28db000 add fp, sp, #0 33f80048: e59f3010 ldr r3, [pc, #16] ; 33f80060 33f8004c: e3a02002 mov r2, #2 33f80050: e5832000 str r2, [r3] 33f80054: e28bd000 add sp, fp, #0 33f80058: e8bd0800 pop {fp} 33f8005c: e12fff1e bx lr 33f80060: 33f800a0 mvnscc r0, #160 ; 0xa0 33f80064 : 33f80064: e92d4800 push {fp, lr} 33f80068: e28db004 add fp, sp, #4 33f8006c: e24dd008 sub sp, sp, #8 33f80070: e59f3024 ldr r3, [pc, #36] ; 33f8009c 33f80074: e3a02001 mov r2, #1 33f80078: e5832000 str r2, [r3] 33f8007c: e3a03001 mov r3, #1 33f80080: e50b3008 str r3, [fp, #-8] 33f80084: ebffffed bl 33f80040 33f80088: e3a03000 mov r3, #0 33f8008c: e1a00003 mov r0, r3 33f80090: e24bd004 sub sp, fp, #4 33f80094: e8bd4800 pop {fp, lr} 33f80098: e12fff1e bx lr 33f8009c: 33f800a0 mvnscc r0, #160 ; 0xa0 Disassembly of secTIon .bss: 33f800a0 : 33f800a0: 00000000 andeq r0, r0, r0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

33f80000<_start>:

33f80000:eb000006bl33f80020

33f80004:ebfffffdbl33f80000<_start>

33f80008:e28f0010addr0,pc,#16

33f8000c:e59f0018ldrr0,[pc,#24]   ; 33f8002c

33f80010:e59f0018ldrr0,[pc,#24]   ; 33f80030

33f80014:e59f0018ldrr0,[pc,#24]   ; 33f80034

33f80018:e59f0018ldrr0,[pc,#24]   ; 33f80038

33f8001c:e59f0018ldrr0,[pc,#24]   ; 33f8003c

33f80020:

33f80020:e3a01000movr1,#0

33f80024:e5801000strr1,[r0]

33f80028:e1a0f00emovpc,lr

33f8002c:

33f8002c:22111120andscsr1,r1,#8

33f80030:12345678eorsner5,r4,#125829120  ; 0x7800000

33f80034:33f8002cmvnsccr0,#44 ; 0x2c

33f80038:33f80064mvnsccr0,#100    ; 0x64

33f8003c:33f800a0mvnsccr0,#160    ; 0xa0

33f80040:

33f80040:e52db004push{fp};(strfp,[sp,#-4]!)

33f80044:e28db000addfp,sp,#0

33f80048:e59f3010ldrr3,[pc,#16]   ; 33f80060

33f8004c:e3a02002movr2,#2

33f80050:e5832000strr2,[r3]

33f80054:e28bd000addsp,fp,#0

33f80058:e8bd0800pop{fp}

33f8005c:e12fff1ebxlr

33f80060:33f800a0mvnsccr0,#160    ; 0xa0

33f80064:

33f80064:e92d4800push{fp,lr}

33f80068:e28db004addfp,sp,#4

33f8006c:e24dd008subsp,sp,#8

33f80070:e59f3024ldrr3,[pc,#36]   ; 33f8009c

33f80074:e3a02001movr2,#1

33f80078:e5832000strr2,[r3]

33f8007c:e3a03001movr3,#1

33f80080:e50b3008strr3,[fp,#-8]

33f80084:ebffffedbl33f80040

33f80088:e3a03000movr3,#0

33f8008c:e1a00003movr0,r3

33f80090:e24bd004subsp,fp,#4

33f80094:e8bd4800pop{fp,lr}

33f80098:e12fff1ebxlr

33f8009c:33f800a0mvnsccr0,#160    ; 0xa0

DisassemblyofsecTIon.bss:

33f800a0:

33f800a0:00000000andeqr0,r0,r0

一、B BL指令bl close_watch_dog

33f80000:eb000006bl33f80020

b 是相对跳转:PC + 偏移值 (PC值等于当前地址+8)

偏移值:机器码 0xeb000006 低 24位 0x000006 按符号为扩展为 32 位 0x00000006 正数,向后跳转 0x6 个 4字节 也就是 0x1c

加载地址0:0 + 8 + 0x1c = 0x20 正确跳转

加载地址0x3ff80000:0x3ff80000 + 8 + 0x1c = 0x33f80020 正确跳转bl _start

33f80004:ebfffffdbl33f80000

偏移值:机器码 0xebfffffd 低 24位 fffffd 按符号位扩展为 32 位 0xfffffffd 负数(-3),向前跳转 0x3 个 4字节 也就是 0xc

加载地址0:4 + 8 – 0xc = 0 正确跳转

加载地址0x3ff80000:0x3ff80004 + 8 + 0xc = 0x33f80000 正确跳转

通过以上分析,我们知道B是相对跳转,位置无关码,也可以知道为什么32为arm指令集,B的范围为正负32M了,24位去掉1位符号位,恰好等于32M。

二、ADRadr r0, close_watch_dog /* 获取标号处的地址,位置无关 */

33f80008:e28f0010addr0, pc, #16

加载地址0:0 + 8 + 16 = 0x20 正确

加载地址0x3ff80000:0x3ff80008 + 8 + 16 = 0x33f80020 正确

adr 获取的是标号处的“实际”地址,标号在哪就是哪个地址,跟位置无关,总能获得想要的值。

三、LDRldr r0, SMRDATA /* 获取标号处的值,位置无关 */

33f8000c:e59f0018ldrr0, [pc, #24]; 33f8002c

加载地址0:r0 = c + 8 + 24 = 0x2c 处的值0x22111120 正确

加载地址0x3ff80000:r0 = 0x3ff8000c + 8 + 24 = 0x33f8002c处的值0x22111120 正确ldr r0, =0x12345678 /* 常数赋值,位置无关*/

33f80010:e59f0018ldrr0, [pc, #24]; 33f80030

加载地址0:r0 = 0x10 + 8 + 24 = 0x30 处的值0x12345678 正确

加载地址0x3ff80000:r0 = 0x3ff80010 + 8 + 24 = 0x33f80030处的值0x12345678 正确ldr r0, =SMRDATA /* 获取标号地址,位置有关 */

33f80014:e59f0018ldrr0, [pc, #24]; 33f80034

加载地址0:r0 = 0x14 + 8 + 24 = 0x34 处的值33f8002c与标号实际地址(2c)不符合,不正确

加载地址0x3ff80000:r0 = 0x3ff80014 + 8 + 24 = 0x33f80034 处的值33f8002c 正确ldr r0, =main/* 获取函数名的地址,位置有关 */

ldr r0 ,=__bss_start /* 获取链接脚本里标号的地址,位置有关 */

这俩和ldr r0, =SMRDATA 一致,位置有关,在0地址处运行不正确。

四、C函数

1、全局变量

00000040 : 00000040: e52db004 push {fp} ; (str fp, [sp, #-4]!) 00000044: e28db000 add fp, sp, #0 00000048: e59f3010 ldr r3, [pc, #16] ; 33f80060 0000004c: e3a02002 mov r2, #2 00000050: e5832000 str r2, [r3] 00000054: e28bd000 add sp, fp, #0 00000058: e8bd0800 pop {fp} 0000005c: e12fff1e bx lr 00000060: 33f800a0 mvnscc r0, #160 ; 0xa0

1

2

3

4

5

6

7

8

9

10

00000040:

00000040:e52db004push{fp};(strfp,[sp,#-4]!)

00000044:e28db000addfp,sp,#0

00000048:e59f3010ldrr3,[pc,#16]   ; 33f80060

0000004c:e3a02002movr2,#2

00000050:e5832000strr2,[r3]

00000054:e28bd000addsp,fp,#0

00000058:e8bd0800pop{fp}

0000005c:e12fff1ebxlr

00000060:33f800a0mvnsccr0,#160    ; 0xa0

000000a0 : 000000a0: 00000000 andeq r0, r0, r0

1

2

000000a0:

000000a0:00000000andeqr0,r0,r0

33f80040 : 33f80040: e52db004 push {fp} ; (str fp, [sp, #-4]!) 33f80044: e28db000 add fp, sp, #0 33f80048: e59f3010 ldr r3, [pc, #16] ; 33f80060 33f8004c: e3a02002 mov r2, #2 33f80050: e5832000 str r2, [r3] 33f80054: e28bd000 add sp, fp, #0 33f80058: e8bd0800 pop {fp} 33f8005c: e12fff1e bx lr 33f80060: 33f800a0 mvnscc r0, #160 ; 0xa0

1

2

3

4

5

6

7

8

9

10

33f80040:

33f80040:e52db004push{fp};(strfp,[sp,#-4]!)

33f80044:e28db000addfp,sp,#0

33f80048:e59f3010ldrr3,[pc,#16]   ; 33f80060

33f8004c:e3a02002movr2,#2

33f80050:e5832000strr2,[r3]

33f80054:e28bd000addsp,fp,#0

33f80058:e8bd0800pop{fp}

33f8005c:e12fff1ebxlr

33f80060:33f800a0mvnsccr0,#160    ; 0xa0

33f800a0 : 33f800a0: 00000000 andeq r0, r0, r0

1

2

33f800a0:

33f800a0:00000000andeqr0,r0,r0

r3 为全局变量 a 的地址,a 是存放在 0起始的地址还是0x33f80000起始的地址,它都认为 a 的地址是 0x33f800a0 。因此,C函数中调用全局变量是位置有关码。

2、函数调用

33f80084:ebffffedbl33f80040

由于 main 函数和 abc 函数挨得比较近,在32M范围之内,因此被翻译成了一条 bl 指令,那么与位置无关。

如果,调用的函数比较远,大于32M的话,我认为是与位置有关系的,这个不再验证了。

3、局部变量

局部变量在函数刚开始的地方被压入栈,赋值语句被翻译成:

33f8007c:e3a03001movr3, #1

33f80080: e50b3008 str r3, [fp, #-8]

位置无关。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值