ARM汇编指令

1.ARM的跳转指令

	B或BL指令引起处理器转移到“子程序名(也就是地址)”处开始执行,这两个指令都是相对跳转指令。两者的不同之处在于BL指令在转移到子程序执行之前,将其下一条指令的地址拷贝到R14(LR,链接寄存器)。由于BL指令保存了下条指令的地址,因此使用指令“MOV PC ,LR”即可实现子程序的返回。
	而B指令则无法实现子程序的返回,只能实现单纯的跳转。如在中断向量表中就只能用B跳转指令,因为它不要返回。而常用的分支语句则用BL指令。

	[31:28]位是条件码[27:24]位为“1010”0xeaffffff表示B跳转指令“1011”时,表示BL跳转指令;[23:0]表示偏移地址。
使用BBL跳转时,下一条指令的地址是这样计算的
将指令中24位带符号的补码立即数扩展为32(扩展其符号位);将此32位数左移两位;将得到的值加到pc寄存器中,即得到跳转的目标地址。	

1.1 b label

该指令完成的操作是pc<-label,将label处的地址传给pc。b跳转指令是相对跳转,依赖当前PC的值,偏移量是通过该指令本身的 bit[23:0]算出来的,这使得使用b指令的程序不依赖于要跳到的代码的位置,只看指令本身。即该分支指令的二进制码的后24位的实际的值是相对当前 的 R15 的值的一个偏移量;而不是一个绝对地址,即跳转时PC的值是以PC=PC+/-n的方式来改变的。它的值由汇编器来计算,它是 24 位有符号数,左移两位后有符号扩展为 32 位,表示的有效偏移为 26 位(+/- 32 M)。 

例程:	1.text
2.global   _start
3_start:
4         b step1
5 step1:
6         ldr pc,  =step2
7 step2:
8         b step2 
反汇编代码:
0:  eaffffff     b   0x4 
4:  e59ff000   ldr pc, [pc, #0] ; 0xc
8:  eafffffe     b   0x8
c:  30000008  tsteq r0, #8  ; 0x8 
b跳转指令:它是个相对跳转指令,其机器码格式如下:
[31:28]位是条件码[27:24]位为“1010”0xeaffffff为一条指令的二进制机器码表示B跳转指令“1011”时,表示BL跳转指令;[23:0]表示一个相对于PC的偏移地址。    将指令中24位带符号的补码立即数扩展为32(扩展其符号位);将此32位数左移两位;将得到的值加到pc寄存器中,即得到跳转的目标地址。
我们看看第一条指令“b step1”的机器码0xeaffffff
124位带符号的补码为0xffffff,将它扩展为32得到:0xffffffff
2.将此32位数左移两位得到:0xfffffffc,其值就是-40xfffffffc符号位不变,其余位取反再加1得到-4);
3pc的值是当前指令的下两条(下一条的下一条指令的地址,加上步骤2得到的-4PC-4,即PC回退4个字节,刚好指向当前指令的下一条指令上),这恰好是第二条指令step1的地址。
    不要被被反汇编代码中的“b 0x4”给迷惑了,它可不是说跳到绝对地址0x4处执行,绝对地址得像上述3个步骤那样计算。


    
助记符
说    明
操    作
B
跳转指令
pc←label
BL
带返回的连接跳转
pc←label(lr←BL后面的第一条指令)
BX
跳转并切换状态,绝对地址
pc←Rm&0xfffffffe, T←Rm&1
BLX
带返回的跳转并切换状态
pc←lable, T←1
pc←Rm&0xfffffffe, T←Rm&1
lr←BL后面的第一条指令

2.STR(条件) 源寄存器,<存储器地址>。

	它们是存储器访问指令。ARM中对ROM,RAM,IO地址采用统一编址,
除RAM外,对外围IO、程序数据的访问都要采用L/S指令进行操作。

2.1 LDR和STR(加载到寄存器,存储到存储器如内存中)

LDR用于把内存中的数据加载到寄存器中,而STR则相反。
LDR R0, [R1] ,把R1所指向的存储单元的内容加载到R0寄存器中
比如 STR R0, [R1] ,意思是R0-> [R1],它把源寄存器写在前面,跟MOV、LDR都相反。
LDR应该是非常常见了。LDR就是把数据从存储器传输到寄存器上。
例一:
@ disable watch dog timer      
   mov   r1, #0x53000000   //立即数寻址方式 
   mov   r2, #0x0 
   str   r2, [r1]        
立即数寻址方式,立即数要求以“#”作前缀,对于十六进制的数,还要求在#后面加上0x或者&。
有个伪指令也是LDR,与之前的LDR加载命令相同。看这段代码
mov r1, #GPIO_CTL_BASE 
   add   r1, r1, #oGPIO_F 
   ldr   r2,=0x55aa   // 0x55aa是个立即数啊,前面加个=干什么? 
	对于当中的ldr 那句,如果你把=去掉,是不能通过编译的。
这个=应该表示LDR不是ARM指令,而是伪指令。作为伪指令的时候,LDR的格式如下:
    LDR 寄存器, =数字常量/Label
它的作用是把一个32位的地址或者常量调入寄存器。嗬嗬,那大家可能会问,
“MOV r2,#0x55aa”也可以啊。应该是这样的。不过,LDR是伪指令啊,
也就是说编译时编译器会处理它的。怎么处理的呢?——规则如下:
如果该数字常量在MOV指令范围内,汇编器会把这个指令作为MOV。
如果不在MOV范围中,汇编器把该常量放在程序后面,
用LDR来读取,PC和该常量的偏移量不能超过4KB

3.LDM和STM

LDM把一块连续内存单元的数据加载到多个寄存器中    LDM{Con}<mode> Rn{!},{reg_list}{^}
STM把多个寄存器的内容存储到一块连续的内存单元中。STM{Con}<mode> Rn{!},{reg_list}{^}
	CON如IA,FD
Rn为基址寄存器它不能为PC          !表示是否要改变Rn的值。
	LDMIA  R0,{R1-R4},把【R0】开始的四个字加载到R1-R4中,
但R0的值没有变。如果为R0!,则最后R0=R0+4*4

4.MRS(read)和MSR(store)p107ARM9嵌入式系统设计

	ARM中对程序状态寄存器的操作由上述两条专用指令实现,而不能由其它指令,
	MRS 读程序状态寄存器
	MSR 写程序状态寄存器。
5.BIC,把标志中的1清0,

实现 “1+2+3+.........+n”

   AREA     TEST, CODE, READONLY   ;定义一个代码段 TEST
   ENTRY                   ; 标记第一和可以执行的代码位置
   
start   
    mov r0, #0  ;r0=0

    ldr r1, =n ; r1=n

begin
   add r0, r0, r1 ;累加,r0=r0 + r1
   subs r1, r1, #1  ;将r1减1,影响标志位
   bne begin        ;如果r1不为0,则循环加,否则退出
   
stop
   b stop      ;让程序停止,此时r0里面就是结果        
   END     

http://blog.chinaunix.net/uid-24219701-id-1628854.html 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值