作为一个使用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 .    
        END

我们在看一下反汇编代码。

__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状态寄存器的对应关系图

懂得的越多,越是无知

最新文章

  1. 第39课 Qt中的事件处理(下)
  2. [BZOJ1854][Scoi2010]游戏(二分图匹配/并查集)
  3. beautifulsoup测试
  4. 2016 版 Laravel 系列入门教程(二)【最适合中国人的 Laravel 教程】
  5. JBPM4之decision节点:3、程序猿|菜鸟|攻城狮|牛人
  6. sqlite3 多线程和锁 ,优化插入速度及性能优化
  7. jstack(Stack Trace for Java)
  8. MySQL 加密/压缩函数
  9. Winform通用模块之流水号生成
  10. Ubuntu 12.04嵌入式交叉编译环境arm-linux-gcc搭建过程
  11. https原理及实践
  12. 重新编译Linux内核必要性及其准备工作
  13. FFmpeg源代码简单分析:avformat_alloc_output_context2()
  14. easyUI行删除
  15. linux下后台启动springboot项目
  16. springboot 02-PropertiesFile 自定义配置属性,多环境配置
  17. java中一些对象(po,vo,dao,pojo)等的解释
  18. python爬虫 urllib库基本使用
  19. 使用SQL Server发送邮件时遇到的诡异事件
  20. LOJ#6049. 「雅礼集训 2017 Day10」拍苍蝇(计算几何+bitset)

热门文章

  1. MongoDB的地埋空间数据存储、空间索引以及空间查询
  2. RHCA442学习笔记-Unit13网络性能调整
  3. shell 两个rpm包做差分
  4. 从零开始,打造自己的首个 iOS 框架
  5. 删除主目录下的.ssh目录下文件对boot2docker启动影响
  6. 制作win7+ubuntu +winPE+CDlinux多系统启动U盘
  7. freewrap——将tcl/tk脚本转变为可执行文件
  8. .net System.TypeInitializationException 类型初始值设定项引发异常
  9. UITabBarController 初学
  10. Android TabHost的使用