ARM的汇编学习

ARM 201浏览

如果你还是学习电子通信的学生又或者是从事嵌入式电子通信工作的工程师、助理工程、实习生、打杂员,笔者想你也曾经对汇编有着复杂的恐惧,甚至是这一恐惧是大学里学《微型计算机技术》开始的。但是就笔者浅薄的工作经历看来,如果你能掌握或者退一步说能看懂汇编,那你才能享受到作为一名底层硬件程序员的乐趣。试想一下用汇编任意操纵一款ARM内核处理器的寄存器、内存空间、外设空间,把它玩弄于手掌之中,这样是不是很有成就感?

  同时,笔者认为,要想对ARM内核有一个比较深刻的认识,还真非得过了汇编这关。因为很多东西与汇编相关,示例ARM的中断向量表,中断过程中的工作模式、堆栈的变化,ARM的一些协处理器寄存器,Cache,MMU等。所以笔者觉得自己有必要记录怎么去搞一搞这ARM的汇编的。

  如果有人叫笔者现场来一段ARM汇编show,那还真考验人,八成是写不出,这可能也与笔者陋习有关,就是有些东西不用的话就很快被大脑遗忘。但是,但是,如果能给我一份ARM指令表,或相关编译器的文档用以查阅的话,写出一段能用的ARM启动文件,那还是问题不大的。所以如果实在记不来那所谓的“精简指令集”的话,也不用太过灰心,下载一份前辈们整理出的指令表,据需要一条一条查。写汇编程序时从“MOV、LDR 、STR”指令开始,也是一条一条把汇编用上去,然后自然而然就懂了。现在一些ARM内核处理器的官方汇编启动文件貌似很复杂,可是笔者认为大部分是因为这样的文件会将各种情况都考虑在其中,而在对于用户来说可能就只会用到里面的一种情况,所以如果用户可以根据自己的系统进行改写,那样出来的程序则不会复杂。就笔者肤浅的认识,一段ARM的启动文件,里面只要有一段中断向量表、和堆栈设置就可以将处理器跑起来。

  下面开始几个简单而又常用的指令。(笔者用的编译环境是RVDS4.0,汇编指令大小书写都是一样哦)

  (1)mov 指令

       mov r0,#0x10 ;将一个立即数0x10赋给r0寄存器。mov指令就常用这一功能行了

       mov r0,r1   ;将寄存器r1的值赋给寄存器r0

   (2)ldr 指令

       ldr r0,=0x12345 ;将常数0x12345加载到r0寄存器,是不是与mov很像?

       ldr r0,[r1]  ;将地址为r1值上的数加载给r0,拗口吧?示例r1=0x80000000的话,就相当于把地址

                    ;0x80000000处的值赋给r0,用C语言可以如下表示,unsigned int *pData=(unsigned 

                    ;int *)0x80000000,“r0”=*pData;此条指令可以衍生出很多常用的形式,不再举例。

   注:无论是mov指令还是ldr指令,都可以将一个数赋给一个寄存器,但是对于mov指令,那个被“mov”的数是有条件限制的,并不是所以数都可以用mov指令来赋给一个寄存器,只能是由8bit(0或1)连续有效位通过偶数次移位能得到的数,于此可以得出一个结论就是凡是小等于255的数都可以用mov指令,大于255的也有行的哦。笔者习惯常用ldr指令,但是兴致到浓时也会用一下mov指令,“mov”不了的话再改用ldr指令。

    (3)str 指令

       str r0,[r1] ;将寄存器r0的值写到与地址为r1上,如r1=0x80000000,则是往地址0x80000000写入r0的值

   注,str 经常与ldr配套使用,也是最常用的一pair 指令了。

    (4)orr 指令

        orr r0,r0,r1 ;r0与r1按位或然后赋给r0

    (5)sub 指令

         sub r1, r1, #1 ;r1减1

         subs r1, r1, #1 ;与上是有区别的,特别是在ARM中断返回时常用“subs”,要阐述这个的话得大量

                         ;语言,还是用到时自行查阅吧

     (6)b,bl 指令

           均是跳转指令,跳转范围有限制的(ARM指令正负32MB,Thumb指令正负16MB)

          b指令是不带链接的跳转,用b指令跳到某一段子函数时,在执行完这段子函数后再也无法跳回来。

          bl指令是带链接的跳转,在跳转前程序会自动将链接寄存器备份,在跳转出去后还能跳回来。

     (7)循环指令

          mov r0,#3

          1    
              subs r0, r0, #1
              bne  �

           注:前面一段是r0减1,后面“bne”是判断r0不等于0的话就执行“�”,其中里面的“b”可以理解为back,“1”是汇编标号,意思是r0不等于0时就向后找到第一个为“1”的标号的指令段然后再按顺序执行。其实就是循环3次了。

     (6)其他常用指令...

        查阅ARM指令集...