第六章 更多指令
在这一章中,我们将探索更多的ARM指令,尤其是ADD,SUB,AND,ORR,EOR,BIC这些。这些指令非常相似,都包含一个位移指令,比如:
add r0, r1, r2, LSR# 2 @ r0 = r1 + (r2 逻辑右移 2)
bic r9, r7, r3, ROR#16 @ r9 = r7 &~ (r3 循环右移 16)
你不必非要位移,也可以简单地这样做:
eor r3, r3, r3 @ 清空r3 (EOR是Exclusive OR,异或)
这些指令(实际上大多数ARM指令)的格式都是这样的:
INSTRUCTION DEST, OPERAND2, OPERAND3 [, SHIFTER OP #Number or Register]
整个操作由INSTRUCTION定义,执行在OPERAND2和OPERAND3上面,结果再经过位移,最后赋值到DEST。经过这些操作,只有DEST被改变了。
你可能对这些指令不是很熟悉,所以我们来看看:
ADD/SUB - ADD(加法)和SUBtract(减法)。还一个指令RSB,它交换了减数和被减数:
正常: sub r0, r1, r2 @ r0 = r1 - r2.
交换: rsb r0, r1, r2 @ r0 = r2 - r1.AND - 位域的与操作。
BIC - 这是一条简洁的指令,有点像AND,只是第二个操作数中被置位的位会清空第一个操作数中相应的位。在C里面我们使用&~(一个与操作和一个逆操作)。实际上BIC的意思是BIc Clear(位清零)。
ORR - 位域的或操作
这里再提一下如果你在这些指令后面加了S(如 ANDS, SUBS, ADDS,...),那么就会影响到状态标志。如果你忘记了在一个循环中加S,好比第二章的那个程序,然后要执行条件跳转语句,你最后得到的就是一个死循环。
指令CMP
你在之前看到过这个指令的(译注:第五章),不过我还是要深入说明一下。这个指令对两个参数进行比较(译注:其实就是做减法),然后根据结果设置状态标志,这样接下来你就能做一些条件操作。比如说:
cmp r1, r0 @ 比较r1和r0。这是一条很重要的指令,注意你可以使用位移,比如:
cmp r0, #160 @ 这个我们也看到过类似的,那么这个呢:
cmp r1, r0, LSL#2 @ 比较r1和(r0 逻辑左移 2)。要记住CMP绝不更改任何寄存器,因为它没有DEST部分。
什么指令都能加上条件代码
实际上在ARM指令集中,所有指令都能加上条件代码(译注:就是分支指令中提到的那些),也就是说可以这样:
orrlt r1, r3, r9 @ 如果状态标志显示LT,那么执行r1 = r3 OR r9。如果条件不满足,那么这条指令就被跳过了。
所有指令都适用,没有例外。很有用吧?