LDR、STR、MOV、B、BL、BX、BLX 和 BXJ

LDR、STR指令

LDR(load register)指令将内存内容加载入通用寄存器
STR(store register)指令将寄存器内容存入内存空间中

 1 #define GPJ0CON 0xE0200240
 2 
 3 _start:
 4 
 5  ldr r0, =0x11111111  // 将立即数/非法立即数,赋值给r0
 6 
 7  ldr r1, =GPJ0CON // 将GPJ0CON的地址赋给r1
 8 
 9  str r0, [r1] // 寄存器间接寻址。把r0中的数写入到r1中的数为地址的内存中去
10 
11  ldr r0,[r1] //将r1的值赋给r0,ARM是RISC结构,数据从内存到CPU之间的移动只能通过LDR/STR指令来完成。 但想把数据从内存中某处读取到寄存器,
           只能使用ldr ,mov只能在寄存器之间移动数据,或者把立即数移动到寄存器中,如 MOV r0,#0是将立即数0放到r0中
 

1、LDR与MOV的不同:ldr能将数据从内存读到CPU,或者从内存中某处读取到寄存器中,而mov只能在寄存器之间移动数据,或者把立即数移动到寄存器中,如 MOV r0,#0是将立即数0放到r0中;

2、MOV是从一个寄存器或者移位的寄存器或者立即数的值传递到另外一个寄存器。但不是所有立即数都可以传递的,这个立即数要符合一个8位数循环右移偶数位的取值。 原因是,MOV本身就是一条32bit指令,除了指令码本身,它不可能再带一个可以表示32bit的数字,所以用了其中的12bit来表示立即数,其中4bit表示移位的位数(循环右移,且数值乘以2),8bit用来表示要移位的一个基数。而对于ldr伪指令,可以在立即数前加上=,以表示把一个地址写到某寄存器中,比如:  ldr r0, =0x12345678  这样,就把0x12345678这个地址写到r0中了。ldr伪指令和mov是比较相似,但mov指令限制了立即数的长度为8位,也就是不能超过512。而ldr伪指令没有这个限制。如果使用ldr伪指令时,后面跟的立即数没有超过8位,那么在实际汇编的时候该ldr伪指令是被转换为 mov指令的。

3、LDR指令的寻址方式实例分类:

LDR r0,[r1]                //将存储器地址为R1的数据读入寄存器r0

LDR r0,[r1,r2]            //将存储器地址为r1+r2的数据读入寄存器r0

LDR r0,[r1,#8]            //将存储器地址为r1+8的数据读入寄存器r0

LDR r0,[r1],r2            //将存储器地址为r1的数据读入寄存器r0,并将r1+r2的值存入r1

LDR r0,[r1],#8            //将存储器地址为r1的数据读入寄存器r0,并将r1+8的值存入r1

LDR r0,[r1,r2]!           //将存储器地址为r1+r2的数据读入寄存器r0,并将r1+r2的值存入r1

LDR r0,[r1,LSL #3]        //将存储器地址为r1*8的数据读入寄存器r0

LDR r0,[r1,r2,LSL #2]    //将存储器地址为r1+r2*4的数据读入寄存器r0

LDR r0,[r1,r2,LSL #2]!  //将存储器地址为r1+r2*4的数据读入寄存器r0,并将r1+r2*4的值存入r1

LDR r0,[r1],r2,LSL #2    //将存储器地址为r1的数据读入寄存器R0,并将r1+r2*4的值存入r1

LDR r0,Label            //Label为程序标号,Label必须是当前指令的-4~4KB范围内
--------------------- 
作者:CYP_2015 
来源:CSDN 
原文:https://blog.csdn.net/CYP_2015/article/details/71195549 
版权声明:本文为博主原创文章,转载请附上博文链接!

 

 

1、MOV指令

MOV指令可以把立即数或者寄存器内容(注意:这里绝对不可以是内存!!)传递给一个寄存器。

 立即数相当于高级语言中的常量(常数),

 立即数就是数字嘛,表示数值的数字,
  存储器用的是地址,一般立即数前需要加#,
MOV对于立即数是有要求的,就是下面的“8位图”数据。

只能由一个8bit连续有效位通过偶数次移位得到的数。

它为什么会有这样的限制呢?

原因是,MOV本身就是一个32bit指令,除了指令码本身,他不可能再带一个可以表示32bit的数字,所以用了其中的12bit来表示

立即数,其中4bit表示移位的尾数(循环右移,且数值*2),8bit用来表示要移位的一个基数。

 

如果立即数超过这个范围,就没有办法用一条MOV指令给寄存器赋值

(这里就要用到LDR伪指令了,查看反汇编指令,你会看到LDR伪指令此变成了两条指令~~)。

2、LDR指令(有等号的ldr指令是伪汇编指令)

ldr指令既可以是大范围的地址读取伪指令,也可以内存访问指令。

当它的第二个参数前面有“=”时,表示伪指令,否则表示内存访问指令。

LDR指令:就是个单寄存器存储的ARM存储器访问指令。

(LDR补充了MOV指令不能访问内存的缺陷。)

 

 ARM是RISC结构的,数据从内存到CPU之间的移动只能通过ldr/str指令(我说的是单个寄存器~~)。

想要把数据从内存中某处读取到寄存器中,只能用ldr。

 

3、LDR伪指令

1)LDR伪指令没有立即数范围的限制,既,可以直接赋值。因为这是一条伪指令。

    如果立即数在MOV的要求内,系统会自动用一条汇编MOV指令来实现。

    如果不在MOV的范围内,就用其它的方式来实现,比如变成了两条指令,或者从PC偏移地址读取一个32位的数据给寄存器。

2)关于LDR伪指令,可以装载一个32bit立即数的说法并不正确,

     因为在实际中并不是这一条语句装载了32bit立即数(跟上面的貌似一样,呵呵~~),比如:

    ldr r1,=0x70000000

    其实真正的汇编代码是将某个地址的值传递给r1,就是说需要一个地址存放0x70000000这个立即数,在反汇编中,

    如果仔细看会返现,如果这个立即数可以用mov指令的表达形式来表达,编译器就直接用mov了~~

 


4、ARM汇编中ldr伪指令和ldr指令

     ARM是RISC结构,数据从内存到CPU之间的移动只能通过L/S指令来完成,也就是ldr/str指令。

    比如想把数据从内存中某处读取到寄存器中,只能使用ldr比如:

          ldr r0, 0x12345678

    就是把0x12345678这个地址中的值存放到r0中。

    而mov不能实现这个功能,mov只能在寄存器之间移动数据,或者把立即数移动到寄存器中。


        ldr伪指令:虽然ldr伪指令和ARM的ldr指令很像,但是作用不太一样。

 ldr伪指令可以在立即数前加上=,以表示把一个值(一般是一个地址)写到某寄存器中,比如:

 ldr r0, =0x12345678 @立即数前面有等号,所以是LDR伪指令

 这样,就把0x12345678这个值写到r0中了。所以,ldr伪指令和mov是比较相似的。

 只不过mov指令限制了立即数的长度为8位,也就是不能超过512。而ldr伪指令没有这个限制。

如果使用ldr伪指令时,后面跟的立即数没有超过8位,那么在实际汇编的时候该ldr伪指令是被转换为mov指令的。

 

比如:

ldr r1,=0x10

会变成

mov r1,#0x10


        综述所述:ldr伪指令用于加载32位的立即数或一个地址值到指定寄存器。

在汇编编译源程序时,ldr伪指令被编译器替换成一条合适的指令。

若加载的常数未超出mov或mvn的范围,则使用mov或mvn指令代替该ldr伪指令,

否则汇编器将常量放入文字池,并使用一条程序相对偏移的ldr指令从文字池读出常量。       

 
--------------------- 
作者:qingkongyeyue 
来源:CSDN 
原文:https://blog.csdn.net/qingkongyeyue/article/details/52239050 
版权声明:本文为博主原创文章,转载请附上博文链接!

 

跳转指令用于实现程序流程的跳转,在 ARM 程序中有两种方法可以实现程序流程的跳转:

(1) 使用专门的跳转指令。

(2) 直接向程序计数器 PC 写入跳转地址值。

通过向程序计数器 PC 写入跳转地址值,可以实现在 4GB 的地址空间中的任意跳转,在跳转之前结合使用

MOV LR , PC

等类似指令,可以保存下一条指令地址作为将来的返回地址值,从而实现在 4GB 连续的线性地址空间的子程序调用。

 

专门的跳转指令
B、BL、BX、BLX 和 BXJ:

跳转、带链接跳转(带返回的跳转)、跳转并切换指令集、带链接跳转并切换指令集(带返回的跳转并切换指令集)、跳转并转换到 Jazelle 状态。

1、 B 指令
B 指令的格式为:

B{条件} 目标地址

B 指令是最简单的跳转指令。一旦遇到一个 B 指令,ARM 处理器将立即跳转到给定的目标地址,从那里继
续执行。注意存储在跳转指令中的实际值是相对当前PC 值的一个偏移量,而不是一个绝对地址,它的值由汇编器来计算(参考寻址方式中的相对寻址)。它是 24 位有符号数,左移两位后有符号扩展为 32 位,表示的有效偏移为 26 位(前后32MB 的地址空间)。以下指令:

B Label ;程序无条件跳转到标号 Label 处执行

CMP R1 ,# 0 ;当 CPSR 寄存器中的 Z 条件码置位时,程序跳转到标号 Label 处执行

BEQ Label

2、 BL 指令
BL 指令的格式为:

BL{条件} 目标地址

BL 是另一个跳转指令,但跳转之前,会在寄存器R14 中保存PC 的当前内容,因此,可以通过将R14 的内容重新加载到PC 中,来返回到跳转指令之后的那个指令处执行。该指令是实现子程序调用的一个基本但常用的手段。以下指令:

BL Label ;当程序无条件跳转到标号 Label 处执行时,同时将当前的 PC 值保存到 R14 中

3、 BLX 指令
BLX 指令的格式为:

BLX 目标地址

BLX 指令从ARM 指令集跳转到指令中所指定的目标地址,并将处理器的工作状态有ARM 状态切换到Thumb 状态,该指令同时将PC 的当前内容保存到寄存器R14 中。因此,当子程序使用Thumb 指令集,而调用者使用ARM 指令集时,可以通过BLX 指令实现子程序的调用和处理器工作状态的切换。

同时,子程序的返回可以通过将寄存器R14 值复制到PC 中来完成。

4、 BX 指令 
BX 指令的格式为:
BX{条件} 目标地址

BX 指令跳转到指令中所指定的目标地址,目标地址处的指令既可以是ARM 指令,也可以是Thumb指令。

总结

语法

op1{cond}{.W} <wbr />label
 
op2{cond} <wbr />Rm

其中:

op1

是下列项之一:

B

跳转。

BL

带链接跳转

BLX

带链接跳转并切换指令集。

op2

是下列项之一:

BX

跳转并切换指令集。

BLX

带链接跳转并切换指令集。

BXJ

跳转并转换为 Jazelle 执行。

cond

是一个可选的条件代码。 cond 不能用于此指令的所有形式。

.W

是一个可选的指令宽度说明符,用于强制要求在 Thumb-2 中使用 32 位 B 指令。

label

是一个程序相对的表达式。

Rm

是一个寄存器,包含要跳转到的目标地址。

操作

所有这些指令均会引发跳转,或跳转到 label,或跳转到包含在 Rm 中的地址处。 此外:

BL 和 BLX 指令可将下一个指令的地址复制到 lr(r14,链接寄存器)中。

BX 和 BLX 指令可将处理器的状态从 ARM 更改为 Thumb,或从 Thumb 更改为 ARM。

BLX label 无论何种情况,始终会更改处理器的状态。

BX Rm 和 BLX Rm 可从 Rm 的位 [0] 推算出目标状态:

如果 Rm 的位 [0] 为 0,则处理器的状态会更改为(或保持在)ARM 状态

如果 Rm 的位 [0] 为 1,则处理器的状态会更改为(或保持在)Thumb 状态。

BXJ 指令会将处理器的状态更改为 Jazelle


http://www.techbulo.com/535.html

http://luleimi.blog.163.com/blog/static/175219645201210922139272/
--------------------- 
作者:bytxl 
来源:CSDN 
原文:https://blog.csdn.net/bytxl/article/details/49883103 
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值