03.ARM - 两种指令运行模式(ARM/THUMB)

ARM的CPU运行的状态2种状态:ARM与THUMB。

        1、CPU在不同状态运行不同的指令集。取决于 cpsr 寄存器其中的位。

        2、thumb 指令集为 arm 指令集的子集。ARM指令4byte,32位,Thumb指令2byte(thumb中bl指令是4字节),16位。Thumb分为:分支指令、数据传送指令、单寄存器加载和存储指令以及多寄存器加载和存储指令。thumb指令集没有协处理器指令、信号量(semaphore)指令以及访问cpsr或spsr的指令。

        3、两者区别。可将Thumb 指令看作ARM指令压缩形式的子集,它具有16位的代码密度,以空间换取效率。Thumb不是一个完整的体系结构,不能独立于ARM指令集单独使用。比如所有异常自动进入ARM状态。编写 Thumb 指令时,先要使用伪指令 CODE16 声明,且在ARM指令中要使用BX指令跳转到Thumb指令,以切换处理器状态。编写 ARM指令时则可使用伪指令CODE32声明。

        4、编译thumb指令集程序:

            ①、在makefile中添加选项" -mthumb "以供编译使用。

            ②、汇编文件中指定thumb格式。" .code 32 "下的代码,使用arm指令集编译," .code 16 "下面的代码,使用thumb指令集。

                    切换指令集使用bx命令,bx指向的寄存器末尾数字为1表示thumb,为0表示arm指令。若要跳转到thumb指令,需要在目标地址后手动" +1 "。

                    bx执行时先判断末尾数字,然后再执行" PC=<rx> AND 0xFFFFFFFE "进行对齐。

                    ARM指令是字对齐(指令的地址后两位为[1:0]=0b00),Thumb是半字对齐(指令的地址后两位为[1:0]=0bx0,x为0或1)。指令的地址的最后一位必为0。

            ③、thumb指令不能直接向pc赋值( ldr pc, =main ),要先将伪指令赋给某寄存器,再把寄存器赋给pc ( ldr r0, =main   ldr pc, r0 )。

            ④、thumb指令集与变量初始化的冲突(memcpy问题)。可以把变量声明为静态的,无需修改的话还可以用const修饰。(或者自己实现memcpy。。。)