自己学驱动2——ARM汇编

常用ARM汇编指令
1.相对跳转指令b和bl
bl指令除了跳转之外,还将返回地址(bl的下一条指令的地址)保存在lr寄存器中。这两条指令的跳转范围都是当前指令的前后32MB的空间。这个32MB的来源是b和bl指令的机器码格式为:

[24]:0,跳转(branch即b);1,跳转并返回连接地址(branch with link即bl)。
[23:0]:一共24个bits,在计算的时候需要将这个地址左移两bits(因为arm处理器是32位的处理器,都是4字节对齐的),所以一共26个bits,可以表示的有符号数的范围就是-2^25~+2^25。
补充:lr寄存器(连接寄存器,link register):一是用来保存子程序的返回地址;二是发生异常时,lr中保存的值等于异常发生时pc寄存器(在ARM中就是R15寄存器)的值减4(或者减2),因此可以在各种异常模式下根据lr的值返回异常发生前的相应位置继续执行。

2.数据传送指令mov,地址读取指令ldr
mov指令可以把一个寄存器的值赋给另一个寄存器,或者把一个常数赋给寄存器。
mov r1, r2
mov r1, #3
mov指令传送的常数必须能用立即数(立即数是存放在机器码中的,所以对其大小范围有限定)来表示,当不知道一个数能否用立即数来表示的时候,可以使用ldr命令来赋值。ldr为伪指令(使用=的时候),它不是真实存在的指令:如果这个常数能够用立即数来表示,则使用mov指令;否则编译时将该常数保存在某个位置,使用内存读取指令把它读取出来,这种用法是针对大的常数来使用的。
ldr也可以使用标号,ldr r0, _start是根据当前的pc算出_start的偏移,最后使用pc的这个偏移将算出来的_start标号中的值(而不是_start标号的地址)存放到r0当中,这是一个 位置无关码;ldr r0, =_start这个是将_start的运行地址取出来放到r0当中,这时它是一个 位置相关码

3.内存访问指令:ldr、str、ldm、stm
ldr指令既可以是前面的大范围地址地址读取伪指令,也可以是内存访问指令,如果其第二个操作数前面有=时,表示其为伪指令,否则为内存访问指令。
ldr r1, [r2, #4] ;将地址为r2+4的内存单元的数据读取到r1中
ldr r1, [r2], #4 ;将地址为r2的内存单元的数据读取到r1中,然后r2+=4
str r1, [r2, #4] ;将r1的数据保存到r2+4内存中
str r1, [r2], #4 ;将r1的数据保存到r2内存中,然后r2+=4
ldm和stm属于批量内存访问指令,只用一条指令就可以读写多个数据:
ldm{cond}<addressing mode> <rn>{!} <register list>{^}
stm{cond}<addressing mode> <rn>{!} <register list>{^}
<cond>表示指令的执行条件,参见7中的表格:
<addressing mode>表示地址变化模式,有以下四种:
ia(Increment After):事后递增方式
ib:事先递增方式
da(Decrement After):事后递减方式
db:事先递减方式
<rn>中保存内存的地址, 如果后面加上了感叹号!,则指令执行后,rn的值会更新,等于下一个要读写的内存单元的地址。
<register list>表示寄存器列表,对于ldm指令,从<rn>所对应的内存块中取出数据,写入这些寄存器;对于stm指令,则是把这些寄存器的值写入<rn>所对应的内存块中。
^有两种含义:如果<register list>中有pc寄存器,它表示指令执行后,spsr(saved program status register专门用来保存cpsr寄存器状态的一个寄存器,以便异常返回后恢复异常发生时的工作状态)寄存器的值将自动复制到cpsr(current program status register程序状态寄存器)寄存器中,这种情况通常用于从终端处理函数中返回;如果<register list>中没有pc寄存器,^则表示操作的是用户模式下的寄存器,而不是当前特权模式下的寄存器。
指令中寄存器列表和内存单元的对应关系为:编号低的寄存器对应内存中的低地址单元,编号高的寄存器对应内存中的高地址单元。
ldm和stm的例子:
HandleIRQ:
    sub lr, lr, #4  ;计算返回地址,pc=lr+4,当前地址=pc-8
    stmdb sp!, {r0-r12, lr}  ;保存寄存器的值
    
    ldr lr, =int_return   ;设置调用IRQ_Handle函数后返回的地址
    ldr pc, =IRQ_Handle   ;调用中断函数
int_return:
    ldmia sp!, {r0-r12, pc}^   ;中断返回,^表示将spsr的值复制
                               ;到cpsr寄存器中

4.加减指令:add、sub
add r1, r2, #1  ;r1=r2+1
sub r1, r2, #1  ;r1=r2-1

5.程序状态寄存器(cpsr)访问指令msr、mrs
cpsr寄存器用来控制处理器的工作模式、设置中断的总开关。
msr cpsr, r0   ;r0=cpsr
mrs r0, cpsr   ;cpsr=r0,与mov指令搬移顺序相反(mov指令是把后面的赋值给前面的)


6.地址读取指令adr、adrl
adr
这是一条小范围的地址读取伪指令,使用的格式:
ADR register,exper;                             adr r1, mem_cfg     ;mem_cfg为一个标号
在编译源程序时,汇编器首先计算出当前PC到exper的偏移值#offset_to_exper(这个也表示这个命令是位置无关指令),然后会用一条ADD或者SUB指令来替换这条伪指令,例如:
ADD register,PC,#offset_to_exper                                         
注意,标号exper与指令必须在同一代码段。
adrl:
这是一条中等范围的地址读取伪指令,使用的格式:
ADRL register,exper。
在编译源程序时,汇编器会用两条合适的指令来替换这条伪指令。例如:
ADD register,PC,offset1
ADD register,register,offset2  
与ADR相比,它能读取更大范围的地址。注意,标号exper与指令必须在同一代码段。

7.协处理指令MCR、MRC
MCR指令将ARM处理器的寄存器中的数据传送到协处理器的寄存器中。如果协处理器不能成功地执行该操作,将产生未定义的指令异常中断。
指令的语法格式:
MCR{<cond>} p15, 0, <Rd>, <CRn>, <CRm>{,<opcode_2>}
MCR2 p15, 0, <Rd>, <CRn>, <CRm>{,<opcode_2>}
<cond>为指令执行的条件码。当<cond>忽略时指令为无条件执行。MCR2中,<cond>为Ob1111,指令为无条件执行指令。
p15表示CP15协处理器。
<opcode_1>为协处理器将执行的操作的操作码。对于CP15协处理器来说, <opcode_1>永远为0b000,当<opcode_1>不为0b000时,该指令操作结果不可预知。
<Rd>作为元寄存器的ARM寄存器,其值被传送到协处理器寄存器中。<Rd>不能为PC,当其为PC时,指令操作结果不可预知。
<CRn>作为目标寄存器的协处理器寄存器,其编号可能为C0,C1....C15。
<CRm>附加的目标寄存器或者原操作数寄存器,用于区分同一个编号的不同物理寄存器。当指令中不需要提供附加信息时,将C0指定为<CRm>,否则指令操作结果不可预知。
<opcode_2>提供附加信息,用于区别同一个编号的不同物理寄存器。当指令中指定附加信息时,省略<opcode_2>或者将其指定为0,否则指令操作结果不可预知。

MRC指令将协处理器的寄存器中数值传送到ARM处理器的寄存器中。如果协处理器不能成功地执行该操作,将产生未定义的指令异常中断。指令的语法格式:
MRC{<cond>} p15, 0, <Rd>, <CRn>, <CRm>{,<opcode_2>}
MRC2 p15, 0, <Rd>, <CRn>, <CRm>{,<opcode_2>}

8.伪指令

.extern    main
定义一个外部符号(可以是变量,也可以是函数),上面的语句表示本文件中引用的main是一个外部函数。
.text
表示下面的语句都属于代码段。
.global _start
将本文件中的_start标号定义为全局。_start:就是这个标号的位置。

9.BIC(位清除)指令
bic Rd, Rn, Oprand2
对Rn中的值和 Operand2值的反码按位进行逻辑“与”运算,并将最后的运算结果赋值给Rd。
举例:
BIC     R0,   R0  , #0xF0000000
其结果就是将R0寄存器的高4bit清零,所以用法上面就比较简单了,需要把哪些为清零,在Oprand2中就把这一bit写为1即可。

10.汇编指令的执行条件

这些标志位均为cpsr中的标志位,N(negative)、Z(zero)、C(cary)、V(overflow)。影响条件标志位的因素比较多,比如比较指令cmp、cmn、teq以及tst指令等。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值