如题
离线
这个是怎么回事呢?
离线
Thumb-2 多数16位,部分32位,自动变长。
怎么确定是 thumb,还是thumb-2呢?
离线
thumb指令,相比较与arm代码,储存器的功耗也较低。
thumb指令,基本都是无条件的,一共有18条基本指令,全部指令都是16bit。
Thumb-2指令,由16bit、32bit的指令混合组成,一共有16条基本指令,
搜了一下, 确实如此, 可是我的 gcc 命令行没有指定 thumb-2, 而是:
$(ARMGNU)-gcc -c $(COPS) -mthumb notmain.c -o notmain.o
离线
我记得这里的BL看起好像是32位,实际上还是16位,但自动粘在一起了。
我看左边那个地址, bl应该是 4字节
离线
感谢大佬解惑,虽然还是一知半解,容我去给IQ充值再来提问。
离线
strap.s
.arm
_reset:
ldr r0, =0x101f1000 //UART0发送寄存器地址
ldr r1, =0x31 //输出1
str r1, [r0]
ldr r0, =_thum_mode + 1
bx r0
.thumb
_thum_mode:
ldr r1, =0x32 //输出2
str r1, [r0]
ldr r1, =0x33 //输出3
str r1, [r0]
@aozima 再请教大佬一个问题,为什么这个代码只能输出 1呢, 不能输出 2, 3
$ arm-linux-gnueabi-objdump -D strap.o
strap.o: file format elf32-littlearm
Disassembly of section .text:
00000000 <_reset>:
0: e59f0014 ldr r0, [pc, #20] ; 1c <_thum_mode+0x8>
4: e3a01031 mov r1, #49 ; 0x31
8: e5801000 str r1, [r0]
c: e59f000c ldr r0, [pc, #12] ; 20 <_thum_mode+0xc>
10: e12fff10 bx r0
00000014 <_thum_mode>:
14: 4903 ldr r1, [pc, #12] ; (24 <_thum_mode+0x10>)
16: 6001 str r1, [r0, #0]
18: 4903 ldr r1, [pc, #12] ; (28 <_thum_mode+0x14>)
1a: 6001 str r1, [r0, #0]
1c: 101f1000 andsne r1, pc, r0
20: 00000015 andeq r0, r0, r5, lsl r0
24: 00000032 andeq r0, r0, r2, lsr r0
28: 00000033 andeq r0, r0, r3, lsr r0
Disassembly of section .ARM.attributes:
00000000 <.ARM.attributes>:
0: 00001941 andeq r1, r0, r1, asr #18
4: 61656100 cmnvs r5, r0, lsl #2
8: 01006962 tsteq r0, r2, ror #18
c: 0000000f andeq r0, r0, pc
10: 00543505 subseq r3, r4, r5, lsl #10
14: 01080306 tsteq r8, r6, lsl #6
18: Address 0x0000000000000018 is out of bounds.
我照着书本写的, 基于arm926, 明明切换到了thumb模式。
离线
@aozima 感谢大佬,我再学习学习。
离线
.arm
_reset:
ldr r0, =0x101f1000 //UART0发送寄存器地址
ldr r1, =0x31 //输出1
str r1, [r0]
// ldr r0, =_thumb_mode + 1
adr r0, _thumb_mode + 1
bx r0
.thumb
_thumb_mode:
ldr r0, =0x101f1000 //UART0发送寄存器地址
ldr r1, =0x32 //输出2
str r1, [r0]
ldr r1, =0x33 //输出3
str r1, [r0]
这样可以输出 123 了, 前面没有初始化 r0 寄存器.
再加上
ldr r0, =_thumb_mode + 1
替换
adr r0, _thumb_mode + 1
$ qemu-system-arm -M versatilepb -m 128M -nographic -kernel notmain.bin
123
请问@aozima老大,为什么ldr指令不可以呢?
离线
这个代码不行:
.arm
_arm_mode:
ldr r0, =0x101f1000 //UART0发送寄存器地址
ldr r1, =0x31 //输出1
str r1, [r0]
ldr r6, =_thumb_mode + 1
add r6, #1
// adr r6, _thumb_mode + 1
bx r6
.thumb
_thumb_mode:
ldr r0, =0x101f1000 //UART0发送寄存器地址
ldr r1, =0x32 //输出2
str r1, [r0]
ldr r1, =0x33 //输出3
str r1, [r0]
ldr r1, =0x34 //输出4
str r1, [r0]
_loop:
b _loop //死循环
bx lr //跳回去
生成的代码:
$ arm-linux-gnueabi-objdump -D strap.o
strap.o: file format elf32-littlearm
Disassembly of section .text:
00000000 <_arm_mode>:
0: e59f0024 ldr r0, [pc, #36] ; 2c <_loop+0x6>
4: e3a01031 mov r1, #49 ; 0x31
8: e5801000 str r1, [r0]
c: e59f601c ldr r6, [pc, #28] ; 30 <_loop+0xa>
10: e2866001 add r6, r6, #1
14: e12fff16 bx r6
00000018 <_thumb_mode>:
18: 4804 ldr r0, [pc, #16] ; (2c <_loop+0x6>)
1a: 4906 ldr r1, [pc, #24] ; (34 <_loop+0xe>)
1c: 6001 str r1, [r0, #0]
1e: 4906 ldr r1, [pc, #24] ; (38 <_loop+0x12>)
20: 6001 str r1, [r0, #0]
22: 4906 ldr r1, [pc, #24] ; (3c <_loop+0x16>)
24: 6001 str r1, [r0, #0]
00000026 <_loop>:
26: e7fe b.n 26 <_loop>
28: 4770 bx lr
2a: 10000000 andne r0, r0, r0
2e: 0019101f andseq r1, r9, pc, lsl r0
32: 00320000 eorseq r0, r2, r0
36: 00330000 eorseq r0, r3, r0
3a: 00340000 eorseq r0, r4, r0
...
这个是可以的:
.arm
_arm_mode:
ldr r0, =0x101f1000 //UART0发送寄存器地址
ldr r1, =0x31 //输出1
str r1, [r0]
// ldr r6, =_thumb_mode + 1
// add r6, #1
adr r6, _thumb_mode + 1
bx r6
.thumb
_thumb_mode:
ldr r0, =0x101f1000 //UART0发送寄存器地址
ldr r1, =0x32 //输出2
str r1, [r0]
ldr r1, =0x33 //输出3
str r1, [r0]
ldr r1, =0x34 //输出4
str r1, [r0]
_loop:
b _loop //死循环
bx lr //跳回去
生成的代码:
$ arm-linux-gnueabi-objdump -D strap.o
strap.o: file format elf32-littlearm
Disassembly of section .text:
00000000 <_arm_mode>:
0: e59f0020 ldr r0, [pc, #32] ; 28 <_loop+0x6>
4: e3a01031 mov r1, #49 ; 0x31
8: e5801000 str r1, [r0]
c: e28f6001 add r6, pc, #1
10: e12fff16 bx r6
00000014 <_thumb_mode>:
14: 4804 ldr r0, [pc, #16] ; (28 <_loop+0x6>)
16: 4905 ldr r1, [pc, #20] ; (2c <_loop+0xa>)
18: 6001 str r1, [r0, #0]
1a: 4905 ldr r1, [pc, #20] ; (30 <_loop+0xe>)
1c: 6001 str r1, [r0, #0]
1e: 4905 ldr r1, [pc, #20] ; (34 <_loop+0x12>)
20: 6001 str r1, [r0, #0]
00000022 <_loop>:
22: e7fe b.n 22 <_loop>
24: 4770 bx lr
26: 10000000 andne r0, r0, r0
2a: 0032101f eorseq r1, r2, pc, lsl r0
2e: 00330000 eorseq r0, r3, r0
32: 00340000 eorseq r0, r4, r0
难道是ldr伪指令不能生成跳转到thumb?
离线
同样都是 0x15 给 R6, 为什么 上面的不行呢?
离线
感觉应该是qemu虚拟机的bug, 因为我用 MDK + GCC工具链 + 模拟调试, 发现编译出来的代码并无二致。
寄存器值一模一样。
离线