作为一个使用ARM的学习者,有必要全面了解你的处理器内核。尽管有些内容可能在实际应用中用不到,但是“了解”还是很必要的。Thumb状态,是ARM的一个特色,但是你知道Thumb状态与ARM状态最大的区别是什么,ARM公司设计Thumb状态的初衷是什么?
带着这些问题,我就Thumb状态写了一个简单的程序以作测试。测试平台是ADS1.2,先贴上测试代码。
GET 2440addr.
inc AREA Init,CODE,READONLY
CODE32 ENTRY
EXPORT __ENTRY
__ENTRY
b ResetHandler
b HandlerUndef
; handler for Undefined mode b HandlerSWI
; handler for SWI interrupt b HandlerPabort
; handler for PAbort b HandlerDabort
; handler for DAbort b .
; reserved b HandlerIRQ
; handler for IRQ interrupt b HandlerFIQ
; handler for FIQ interrupt HandlerFIQ
b .
HandlerIRQ
b .
HandlerUndef
b .
HandlerSWI
b .
HandlerDabort
b .
HandlerPabort
b .
ResetHandler
ldr r0,=WTCON
; watch dog disable ldr r1,=0x0
str r1,[r0]
mov r1,#0x34000000
ldr r0,=ThumbState+
1 bx r0
CODE16 ThumbState
add r0,r0,r1
ldr r0,=HandlerFIQ
ldr r0,[r0]
ldr r0,=BackARM
bx r0
CODE32 ALIGN
BackARM
ldr r0,=GPFCON
ldr r1,=0x55aa
str r1,[r0]
ldr r0,=GPFDAT
ldr r1,=0x0
str r1,[r0]
; b .
我们在看一下反汇编代码。
__ENTRY [0xea00000c] b ResetHandler
00000004 [0xea000007] b HandlerUndef
00000008 [0xea000007] b HandlerSWI
0000000c [0xea000008] b HandlerPabort
00000010 [0xea000006] b HandlerDabort
00000014 [0xeafffffe] b 0x14
; (__ENTRY + 0x14) 00000018 [0xea000001] b HandlerIRQ
0000001c [0xeaffffff] b HandlerFIQ
HandlerFIQ [0xeafffffe] b HandlerFIQ
HandlerIRQ [0xeafffffe] b HandlerIRQ
HandlerUndef [0xeafffffe] b HandlerUndef
HandlerSWI [0xeafffffe] b HandlerSWI
HandlerDabort [0xeafffffe] b HandlerDabort
HandlerPabort [0xeafffffe] b HandlerPabort
ResetHandler [0xe3a00453]
mov r0,#0x53000000
0000003c [0xe3a01000]
mov r1,#
0 00000040 [0xe5801000]
str r1,[r0,#
0]
00000044 [0xe3a015d0]
mov r1,#0x34000000
00000048 [0xe59f0028] ldr r0,0x00000078
; = #0x00000051 0000004c [0xe12fff10] bx r0
ThumbState [0x1840]
add r0,r0,r1
00000052 [0x480a] ldr r0,0x0000007c
; = #0x00000020 00000054 [0x6800] ldr r0,[r0,#
0]
00000056 [0x480a] ldr r0,0x00000080
; = #0x0000005c 00000058 [0x4700] bx r0
0000005a [0x0000] dcw 0x000 (说明:为了使下边的CODE32代码4字节对齐起到占位作用)
BackARM [0xe59f0020] ldr r0,0x00000084
; = #0x56000050 00000060 [0xe59f1020] ldr r1,0x00000088
; = #0x000055aa 00000064 [0xe5801000]
str r1,[r0,#
0]
00000068 [0xe59f001c] ldr r0,0x0000008c
; = #0x56000054 0000006c [0xe3a01000]
mov r1,#
0 00000070 [0xe5801000]
str r1,[r0,#
0]
00000074 [0xeafffffe] b 0x74
; (BackARM + 0x18) 从反汇编代码中,我们可以看出Thumb状态的指令变为2个字节,所以指令代码密度更高。
下边,我再贴出用AXD调试过程中的现象。
mov r1,#0x34000000 ;运行后r1=0x34000000
ldr r0,=ThumbState+1 ;运行后 r0=x00000051
bx r0 ;跳转到Thumbstate位置处执行,并且切换处理器到Thumb状态
CODE16
ThumbState ;pc = x00000050
add r0,r0,r1 ;运行后r0=0x34000051
ldr r0,=HandlerFIQ ;运行后r0=0x0x00000020
ldr r0,[r0] ;运行后r0=0xeafffffe
ldr r0,=BackARM
bx r0
分析结果,"add r0,r0,r1;运行后r0=0x34000051"说明加法运算是32位的,也就是说CPU在Thumb状态还是32位的,还能说明寄存器也是32位的,并非16位的。"ldr r0,[r0] ;运行后r0=0xeafffffe"也说明了寄存器仍然与ARM状态一样是32位的。
结论:虽然,ARM的Thumb状态的指令是16位的,但是CPU还是32位的,而且寄存器也是32位的。所以,Thumb状态最大的区别就是指令变成16位的,寄存器少了一点,其他没什么变化。
附上ARM的Thumb状态与ARM状态寄存器的对应关系图
懂得的越多,越是无知