arm的ldr和adr指令
.section .text "x"ldr r0,_start
adr r0,_start
ldr r0,=_start
nop
_start:
nop
编译:
ldradr:ldradr.o
arm-none-eabi-ld -Ttext=0x30000000 -Tdata=0x40000000 -Map ldrard.map -o ldradr.elf $^
arm-none-eabi-objdump -D ldradr.elf > ldradr.dis
反汇编之后主要代码如下:
ldradr.elf: file format elf32-littlearm
Disassembly of section .text:
30000000 <_start-0x10>:
30000000: e59f0008 ldr r0, ; 30000010 <_start> 指令基址0x30000000,在指令执行时pc值其实是0x30000008,所以指令的目的就是将0x30000008+8=0x30000010内存中的字数据传给r0。
//如果执行时的基地址与-Ttext指定的链接基址不同,最终也不影响ldr r0,_start对内存地址的寻址,也就是说是位置无关定位
30000004: e28f0004 add r0, pc, #4 //也就是指令adr r0,_start。pc值在指令执行时值为0x3000000C,所以pc+4=0x30000010,不管基址是多少,执行时都能正确定位目标地址,所以是位置无关定位
30000008: e59f0004 ldr r0, ; 30000014 <_start+0x4> 即寄存器基址加偏址寻址最终地址为0x30000014
3000000c: e1a00000 nop ; (mov r0, r0)
30000010 <_start>:
30000010: e1a00000 nop ; (mov r0, r0)
30000014: 30000010 andcc r0, r0, r0, lsl r0
汇编语法错误:
.section .text,"x"
ldr r0,_start
adr r0,_start
ldr r0,=_start
ldrb r1,data2//此句:Error: internal_relocation (type: OFFSET_IMM) not fixed up
ldrb r2,data1 //此句:Error: internal_relocation (type: OFFSET_IMM) not fixed up
nop
mov pc,lr
_start:
nop
.section .data
data1:
.ascii "hello world"
data2:
.string "arm string"
.end
如果改为
ldrb r1,=data2
ldrb r2,=data1
则反汇编之后主要代码:
Disassembly of section .text:
30000000 <_start-0x1c>:
30000000: e59f0014 ldr r0, ; 3000001c <_start>
30000004: e28f0010 add r0, pc, #16 不管链接地址与执行地址相不相同,都是位置无关定位
30000008: e59f0010 ldr r0, ; 30000020 <_start+0x4>
3000000c: e5df1010 ldrb r1, ; 30000024 <_start+0x8> 对应指令ldrb r1,=data2其实是一个绝对地址定位,并不是相对地址定位
30000010: e5df2010 ldrb r2, ; 30000028 <_start+0xc>
30000014: e1a00000 nop ; (mov r0, r0)
30000018: e1a0f00e mov pc, lr
3000001c <_start>:
3000001c: e1a00000 nop ; (mov r0, r0)
30000020: 3000001c andcc r0, r0, ip, lsl r0
30000024: 4000000b andmi r0, r0, fp
30000028: 40000000 andmi r0, r0, r0
Disassembly of section .data:注意:我们编译时用的是:arm-none-eabi-ld -Ttext=0x30000000 -Tdata=0x40000000 -Map ldrard.map -o ldradr.elf $^,所以数据段基址是0x40000000
40000000 <__data_start>:
40000000: 6c6c6568 cfstr64vs mvdx6, , #-416 ; 0xfffffe60data1的数据,从右到左对应的ascii码为字母:“hell”
40000004: 6f77206f svcvs 0x0077206f 从右到左对应的ascii码为字母:“o空格wo”
40000008: 61646c72 smcvs 18114 ; 0x46c2 从右到左对应的ascii码为字母:“rlda” 其实我们希望rld之后是C语言中对应的字符串结束符 \0
4000000b <data2>:
4000000b: 206d7261 rsbcs r7, sp, r1, ror #4data2的数据,从右到左对应的ascii码为字母:“arm空格”
4000000f: 69727473 ldmdbvs r2!, {r0, r1, r4, r5, r6, sl, ip, sp, lr}^ 从右到左对应的ascii码为字母:“stri”
40000013: Address 0x40000013 is out of bounds.因为不是ARM指令,所了本行在反汇编中看不到,但用winhex查看可以看到有字母:“ng"
如果改为:
data1:
.ascii "hello world\000"
data2:
.string "arm string\000"
反汇编之后:
Disassembly of section .data:
40000000 <__data_start>:
40000000: 6c6c6568 cfstr64vs mvdx6, , #-416 ; 0xfffffe60
40000004: 6f77206f svcvs 0x0077206f
40000008: 00646c72 rsbeq r6, r4, r2, ror ip 从右到左对应的ascii码为字母:“rld\0” 这才是我们希望的结果
4000000c <data2>:
4000000c: 206d7261 rsbcs r7, sp, r1, ror #4
40000010: 69727473 ldmdbvs r2!, {r0, r1, r4, r5, r6, sl, ip, sp, lr}^
40000014: 0000676e andeq r6, r0, lr, ror #14 同样地,从右到左是"ng\0\0",最后一个\0应该是汇编器自己加进去的,以补齐32位,以便地址4字节对齐而已
页:
[1]