ARM基础知识:ARM寻址方式
开始想的比较简单,在开始配置uboot的时候开始看最开始的汇编,发现了之前用arm7当单片机用的时候没有涉及到汇编这些东西,看到将arm指令相关基础知识的时候感觉没必要看,现在才发现这个是基本功,如果想进入嵌入式或者驱动开发,必须要了解芯片架构和指令系统,arm在arm7之后最主要的就是有了mmu功能,这个也是arm+linux的基本功。“基本功”,我师傅常说的一个词,现在真的领会到了它的含义。做东西还是不能只了解表面的东西,尤其是嵌入式驱动方面一方面和软件打交道,另外最重要的一点要理解硬件。这才是嵌入式软件和通用软件的最大区别。
下面开始学习下arm的寻址方式。这里主要是参考《arm嵌入式程序设计》这本小册子,讲的arm的基础知识,初学的同学们可以看看,和8086对比着讲的,很不错。
arm有一下的集中寻址方式:
1. 立即数寻址
这是一种比较简单的寻址方式,操作数包含在指令当中。取出指令,即取出了操作数。对应的寻址方式也就叫做立即数寻址。
例:
;注意arm汇编中,指令不能顶格写,在前面加空格。
;而定义变量的时候,必须顶格写,这里新手要注意。
ADD R0,R0,#1 ;R0 <==R0 +1 ,把R0的内容加1。
ADD R0,R0,#0x30 ;R0 <==R0 +0x30,把R0的内容加 0x30。
说明:以上两条指令中,第二个源操作数 #1 和#0x30为立即数。立即数必须以#作为前缀,对于16进制的立即数,要求有"0x"或者"&"符号。
2. 寄存器寻址
将寄存器中的值作为操作数,这种方式即为寄存器寻址。此种方式较为各类微处理器常用,执行效率高。
例:
ADD R0,R1,R3 ;R0 <==R1+R3
将R1和R3的内容相加,结果存放到R0。
3. 寄存器移位寻址
其是将2 寄存器寻址做变化而得到的一种新的寻址方式。即移位,第二个操作数通过相应移位和第一个操作数运算后放到目的寄存器中。
例:
ADD R0,R1,R3,LSL #3 ;R0 <== R0+R3*8 ,R3的值左移3位就是乘以8,结果与R1的值相加,存放到R0.
ARM的移位(或者循环移位)操作有如下几种:
LSL 逻辑左移,寄存器中低位空出的有效位用0填充
LSR 逻辑右移,寄存器中高端空出的有效位用0填充
ASR 算数右移,移位过程中必须保持符号位不变,即若源操作数为正,则高位用0填充,若为负,则高位用1填充。 其每移一位的操作和逻辑右移相同,仅是如果原最高位为1,则移位后最高位补1,所以在移大于1位时左边的高位都是1.
即:
MOV R1,#0
MOV R2,#&80000000 ;此处立即数为负数,
MOV R1,R2,ASR #3
R1 内的值为 0xF0000000
若立即数换为0x40000000,则R1的值最后为0x08000000.
ROR 循环右移,一处的最低位移到空出的最高位
RRX 扩展的循环右移,操作数右移一位(每次执行只能移动1位),高端空出的位用进位标志位C的当前值来填充。
4.寄存器间接寻址
寄存器间接寻址,就是以寄存器中的值作为操作数的地址。这种寻址方式类似于c语言中取指针对应的变量的值 *p。
例:
ADD R0,R1,[R2] ;R0 《==R1 + [R2]
LDR R0,[R1] ;R0 <==[R1]
STR R0,[R1] ;[R1] <== R0
第一条指令为将R2的值作为操作数的地址,将此地址对应的位置的操作数和R1相加,存放到R0 ,[R2]类似于 取指针对应的值 *p。
第二条指令为将R1的值作为地址的寄存器中的数传送到R0中。类似于c语言 R0 = *R1;
第三条指令将R0的值传送到R1的值作为地址的寄存器中。 类似于c语言中 *R1 = R0;