在讨论CPSR寄存器时,我们已经简要地讨论了条件的话题。当特定条件满足时,借助条件指令, 通过跳转(分支)或执行某些特定指令来控制程序的流动方向。相关条件被描述为CPSR寄存器中的特定位的状态,这些位根据指令计算后的结果实时改变。比如,如果我们比较两个数并且他们相等,就将零标志位置位(Z=1),因为在系统底层发生了a-b=0。在这个例子里两个数是相等的,但如果第一个数字比第二个大,会得出大于结论。而相反的情况下得出小于结论。当然还有很多其他的条件,比如小于等于(LE),大于等于(GE)等等。
下表列出了可能的条件指令,他们的含义以及被检测的状态标志位
我们使用如下代码来实现条件相加指令:
代码中,第一个CMP比较指令执行后触发了N标志位的置位(2-3=-1),这表明r0的值比数字3要小。随后,由于LT条件满足, 即V != N(在CPSR里溢出标志位和负标志位不是同一个),所以执行了addlt指令。由于第二个cmp指令将N标志位清空(因为3-3=0,不需要置位N标志位),将零标志位置位(Z=0),现在V = 0且 N = 0,从而导致LT条件不成立,结果就是第二个addlt没有执行,r0也没改变,程序退出并返回结果3 。
Syntax: IT{x{y{z}}}cond 语法结构:IT{x{y{z}}}cond(译者注:xyz指IT后最多再跟三个大写字母,大写字母可以是T,可以是E,T就是then,E就是else)
cond规定了执行IT语句块里的第一条指令需要满足的条件
x规定了执行的IT语句块中第二条指令需要满足的条件
y规定了执行IT语句块里的第三条指令需要满足的条件
z规定了执行IT语句块里的第四条指令需要满足的条件
IT指令集的结构是:“IF-Then-(Else)”,它的语法结构由两个字母构成:
IT代表If-Then(下一条指令是条件指令)
ITT代表If-Then-Then(接下来的两条指令是条件指令)
ITE代表If-Then-Else(接下来的两条指令是条件指令)
ITTE代表If-Then-Then-Else(接下来的三条指令是条件指令)
ITTEE代表If-Then-Then-Else-Else(接下来的四条指令是条件指令)
Wrong syntax:错误的语法:
以下总结了条件指令和逻辑相反的指令:
用下面的示例代码尝试一下:
. code 32
这段示例代码以ARM状态开始。第一条指令将PC里的地址值加1后传送给r3,接着跳转到分支地址R3。这样做会导致切换到Thumb状态,因为LSB(最低有效位)是1,因此不是4个字节。使用bx指令(分支+切换)达成这个目标,分支指令执行完成后,T(Thumb)标志位被置位,我们现在处于Thumb模式。
. code 16
Thumb模式下首先用R0和立即数10比较。这会将N标志位置位(0-10=-10)。接着我们使用了一个If-Then-Else语句块。这个块会跳过ADDEQ因为Z(零)标志位没有被置位,由于结果等于10,是NE的(not equal不等于0的),接着会执行ADDNE指令。
分支指令(aka跳转)允许我们跳转到另一个代码段运行。当我们需要跳过(或者重复)执行代码段或者跳向特定功能的函数时就显得尤为有用。这方面最好的范例就是IFs和循环。我们先看看IF是什么情况。
上述代码只是简单检查了一些哪个变量初始化的值更大,而且将大数作为返回值。它的类C语言伪代码应该想这样的:
现在我们可以用条件分支指令和非条件分支指令来创建一个循环了。
类C语言伪代码如下:
B / BX / BLX
有三类分支指令。他们分别是:
1.分支指令(B)
a)简单地跳向一个函数
2.分支连接指令(BL)
3.BX指令:分支切换指令和BLX(分支连接切换指令)a) 将(PC+4)保存到LR中并跳转到函数
a) 与B/BL+交换指令集相同(ARM <-> Thumb)
b) 需要用寄存器作为第一操作数:BX/BLX+具体的寄存器
BX/BLX用来从ARM指令集切换到Thumb指令集
这里的诀窍是获取实际的PC当前值,将其增加1,将结果存储到寄存器中,并将分支(+交换)存储到该寄存器。我们看到,加法(add r2, pc, #1)将简单地获取有效的PC地址(当前PC寄存器的值+ 8等于 0x805C),并加1(0x805c+1=0x805d)。然后,如果我们分支指令后面的地址的最低有效位(LSB)为1(这里就是这种情况,因为0x805D=10000000 01011101),意味着地址不是4字节对齐的,则发生状态转换。分支到这样的地址不会引起任何不对中问题。这就是代码在GDB(GEF扩展)的样子:
请注意,上面的GIF是使用较旧版本的GEF创建的,因此很可能看到稍微不同的UI和不同的偏移量。然而,逻辑是相同的。
分支还可以有条件地执行,如果满足特定条件,则分支到某函数。让我们来看一个非常简单的使用条件分支指令BEQ的例子。如果寄存器等于一个指定值,那么这段汇编代码除了把值给到寄存器并分支到另一个函数之外,没有什么特别有趣的地方。
联系客服