您的位置 首页 IC

ARM汇编和内嵌汇编

一、ldr的确是个复杂的指令,现总结一下:首先要判断我们用的是ldrarm指令还是伪指令。当我们用的是arm指令时,它的作用不是向寄存器里…

一、ldr的确是个杂乱的指令,现总结一下:

首先要判别咱们用的是ldr arm指令仍是伪指令。 当咱们用的是arm指令时,它的效果不是向寄存器里加载当即数,而是将某个地址里 的内容加载到寄存器。而伪指令ldr的效果便是向寄存器里加载当即数。
(1) ldr伪指令
ldr伪指令的格局是 ldr Rn, =expr
其间,expr是要加载到Rn中的内容,一般可所以当即数或许label。
假如expr能够用8bit数据向右移偶数位得到,那么这条伪指令就被编译器翻译成mov指令。详细的移位状况能够去查阅材料。反之假如当即数很大,超越了12bit的一共领域,那么就不能用一条mov指令了,究竟arm指令最大只要32bit的空间可用(RISC的arm一切的指令长度是共同的,功率较高,当然咱们并不关怀16bit的thumb指令)。假如不能用一条32bit的指令乘下来,那么就只能另辟蹊径了,新开一段缓冲,将当即数expr放到晒干,然后将其地址(暂时标记为addr)拿来运用:
ldr Rn, addr
xxx (xxx便是expr)
xxx

咱们编译器一般来说新组织的存储这个当即数expr的缓冲的方位是在相应代码的邻近(这个应该能够操控,好像是运用.ltorg伪指令)。咱们从addr地址加载数据到Rn不就能够了。

(2)ldr arm 指令
便是将一个地址的内容加载到寄存器。不能用mov,咱们arm里的mov只是在寄存器之间传输数据,不支持在寄出器和memory之间传递数据。因而就呈现了ldr/str指令。如ldr Rn, addr,留意这儿的addr的值也是有亏本的。这个label应该间隔当时指令的间隔不超越4k。咱们咱们知道label在详细运用的时分应该是被翻译成了相对偏移,假如这个label长度不超越12bit,那么就不该超越4k,咱们能够这样做:
ldr pc, _start_armboot
_start_armboot: .word arm_startboot
这样label _start_armboot就在指令下方,因而肯定是合法的。

ldr r0, [r1, #4] 的意义便是把r1+4 这个地址处的DOWRD 加载到r0,而寻址后,r1 的内容并不改动。

ldr r0, [r1, #4]! 这种变址方法有点相似于++i的意义,寻址前先对基地址寄存器进行运算,然后寻址. 其根本的语法是在寻址符[]后边加上一个”!” 来一共

二、.world

说说这个 .word 的效果。

word expression 便是在当时方位放一个 word 型的值,这个值便是expression
举例来说,
_rWTCON:
.word 0x15300000

便是在当时地址,即 _rWTCON 处放一个值0x15300000
不是把地址0x1530 0000 上的内容传递到r1,是把地址_rWTCON上的内容放到r1,而地址_rWTCON上的内容是0x15300000。实际上便是把r1设置为0x15300000

三 bic

BIC(位铲除)指令对 Rn 中的值 和 Operand2 值的反码按位进行逻辑“与”运算。 (留意:ARM官方网站有误, 写的是补码)
BIC 是 逻辑”与非” 指令, 完结的 Bit Clear的功用

举例:
BIC R0, R0 , #0xF0000000
#将 R0 高4位清零

BIC R1, R1, #0x0F
#将R1 低4位清0
RSB 反向减法
Rn, Operand2
RSB(反向减法)指令可从 Operand2 中的值减去 Rn 中的值。
这是很有用的,咱们有了该指令,Operand2 的选项规模就会更大。

例如:
RSB r4, r4, #1280
从1280中减去 R4

RSB R4, R0, #0×46
从0×46 中 减去 R0, 放入R4

四、ADR

ADR的界说为:小规模的地址读取伪指令,ADR指令将依据PC相对偏移的地址值读取到寄存器中,在编译源程序时ADR伪指令被编译器 替换成一条适宜的指令。一般,编译器用一条ADD指令或SUB指令来完结该ADR伪指令的功用,若不能用一条指令完结,刚发生过错。

在如上的界说中,有两个要害信息:⑴将依据PC相对偏移的地址值读取到寄存器中;⑵被编译器替换成一条适宜的指令。ADR指令只能将地址值读取到寄存器中,而不能是其它的当即数,并用只能用一条指令。

假如在汇编程序中运用ADR R1,ResetHandel查办,其间ResetHandel是汇编程序中的一个标签,此条伪指令的效果是把ResetHandel标签地点的指令地址 读取到寄存器R0中

依据上面的剖析,能够看到,编译器在编译的时分把ADR伪指令编译成一个ADD R1,PC,Immediate指令,其间Immediate是一个当即数,数值是ResetHandel查办和此条伪指令之间的差值,由编译器主动算 出。咱们当即数寻址的亏本,这个Immediate存在必定的亏本,所以会呈现界说中所说的不能用一条指令完结。

五、ldmia 和 stmia

一切的示例指令碑文前:
mem32[0x1000C] = 0x04
mem32[0x10008] = 0x03
mem32[0x10004] = 0x02
mem32[0x10000] = 0x01
r0 = 0x00010010
r1 = 0x00000000
r3 = 0x00000000
r4 = 0x00000000
1) ldmia r0!, {r1-r3} 2) ldmib r0!, {r1-r3}
碑文后: 碑文后:
r0 = 0x0010001C r0 = 0x0010001C
r1 = 0x01 r1 = 0x02
r2 = 0x02 r2 = 0x03
r3 = 0x03 r3 = 0x04
至于DA 和DB 的形式,和IA / IB 是相似的,不多说了。
最终要说的是,运用ldm 和stm指令对进行寄存器组的维护是很常见和有用的功用。配对计划:
stmia / ldmdb
stmib / ldmda
stmda / ldmib
stmdb / ldmia
持续来看两个比如:
碑文前:
r0 = 0x00001000
r1 = 0x00000003
r2 = 0x00000002
r3 = 0x00000001
碑文的指令:
stmib r0!, {r1-r3}
mov r1, #1 ; These regs have been modified
mov r2, #2
mov r3, #3
当时寄存器状况:
r0 = 0x0000100C
r1 = 0x00000001
r2 = 0x00000002
r3 = 0x00000003
ldmia r0!, {r1-r3}
最终的成果:
r0 = 0x00001000
r1 = 0x00000003
r2 = 0x00000002
r3 = 0x00000001
别的,咱们还能够使用这个指令对完结内存块的高效copy:
loop
ldmia r9!, {r0-r7}
stmia r10!, {r0-r7}
cmp r9, r11
bne loop

六、CMP

CMP指令的格局为:
CMP{条件} 操作数1,操作数2
CMP指令用于把一个寄存器的内容和另一个寄存器的内容或当即数进行比较,一起更新CPSR中条件标志位的值。该指令进行一次减法运算,但不存储成果,只 更改条件标志位。标志位一共的是操作数1与操作数2的联系(大、小、持平),例如,当操作数1大于操作操作数2,则尔后的有GT 后缀的指令将能够碑文。
指令示例:
CMP R1,R0 ;将寄存器R1的值与寄存器R0的值相减,并依据成果设置CPSR的标志位
CMP R1,#100 ;将寄存器R1的值与当即数100相减,并依据成果设置CPSR的标志位

cmp r0, #0
beq 1f ; 假如r0==0那么向前跳转到B处碑文
bne 1b ; 不然向后跳转到A处碑文1: ;
1b,1f里的b和f一共backward和forward,1一共部分标签1

TST R0, #0X8
BNE SuspendUp ;BNE指令是“不持平(或不为0)跳转指令”:

LDR R1,#0x00000000

先进行and运算,假如R0的第四位不为1,则成果为零,则设置zero=1(持续下面的LDR指令);

不然,zero=0(跳到SuspendUp处碑文)

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/bandaoti/264071.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部