我根本没有写过大会的经验,所以我觉得这个问题很容易回答。
有这个简单的循环:
mov r0,#3
loop:
do some instructions
...
last-instruction
subs r0,r0,#1
bne loop
afterloop:
如果我理解得很好,这个循环应该从3减少到0并停止(如果我错了,请纠正我。)
然而,在最后一次迭代中,当r0 == 0时,我想跳过last-instruction
并退出循环。如果r0等于0,我认为必须有一些cmp
然后跳转到afterloop
。但我想可能有一些更简单的方法来实现这一目标。
修改 还有一个问题 - 如果有更多指令要跳过怎么办?
在C中它看起来像这样:
int i = 3;
while (1) {
foo();
if (i == 0) break;
skipped_func();
--i;
}
答案 0 :(得分:4)
除非最后一条指令依赖于r0和/或修改CPSR,否则将subs
线移到最后一条指令之前一步,并使最后一条指令以NE条件为条件。像这样:
mov r0,#3
loop:
do some instructions
...
subs r0,r0,#1
last-instructionNE
bne loop
afterloop:
如果最后一条指令是mov
,请将其设为movne
。如果是str
,请将其设为strne
。等等。
如果最后一条指令已经有一个“s”后缀,那么这将不起作用 - 修改标志。如果是,它将破坏零标志,bne
将无法按预期工作。另外,如果最后一条指令依赖于减少之前的r0值,它也必须在subs
之前执行。
在ARM上,与英特尔不同,几乎每条指令都可以成为条件,而不仅仅是B(牧场)。除非它实际上是拇指。
编辑重新:编辑:您可以通过这种方式生成多条指令。或者,您也可以使用跳转复制相同的逻辑。像这样:
mov r0,#3
loop:
do some instructions
...
subs r0,r0,#1
bz afterloop
last-instructions
b loop
afterloop:
这绝对是“英语”式的装配风格。有些人声称它更容易理解。对于2-3条条件行,我不会打扰。对于10岁以上,我愿意。在中间有一个灰色区域。 :)
Bz
和be
是同义词。这种逻辑更清晰 - 你隐含地将r0与0进行比较。
在这种情况下,最后的指令可能会破坏他们想要的所有标志。从r0读取仍然会给你已经减少的值。