如何在ARMSim中循环使用2个条件?

时间:2016-04-08 01:12:56

标签: assembly while-loop arm

我试图在手臂组装中进行插入排序,但我不知道如何使用2个条件进行while循环?我从维基百科得到了这个算法的伪代码,但我在将while循环转换为ARM指令时遇到了麻烦,因为有2个条件。

for i = 1 to length(A)
x = A[i]
j = i - 1
while j >= 0 and A[j] > x
    A[j+1] = A[j]
    j = j - 1
end while
A[j+1] = x
end for

这是我尝试将代码转换为ARM汇编指令,该数组包含20个整数:

MOV R7, #0                             ;intialize index
ForLoop:
CMP R7, #20                            ;check if end of array
BEQ EndFor                        ;exit for loop if done
LDR R1, =array                         ;Load array address
MOV R2, R7, LSL #2                     ;multiply array index r7 by 4 to get array offset
ADD R2, R1, R2                         ;Set R2 to element address
LDR R1, [R2]                           ;R1 = A[R7]

MOV R8, R1                             ;R8 = R1

SUB R9, R7, #1                         ;R9 = R7 - 1

LDR R1, =array                         ;Load array address
MOV R2, R9, LSL #2                     ;multiply array index r9 by 4 to get array offset
ADD R2, R1, R2                         ;Set R2 to element address
LDR R3, [R2]                           ;r3 = A[r9]

WhileLoop:  
CMP R9, #0                             ;while >= 0
BEQ Endwhile
CMP R3, R8                         ;while R3> R8
BEQ Endwhile

LDR R1, =array                         ;Load array address
MOV R2, R9, LSL #2                     ;multiply array index r9 by 4 to get array offset
ADD R2, R1, R2                         ;Set R2 to element address
LDR R3, [R2]                           ;r3 = A[r9]

ADD R9, R9, #1                         ;R9 = R9 + 1
LDR R1, =array                         ;Load array address
MOV R2, R9, LSL #2                     ;multiply array index by 4 to get array offset
ADD R2, R1, R2                         ;Set R2 to element address
STR R3, [R2]                           ;A[R9] = R3

SUB R9, R9, #1                    ;R9 = R9 - 1

B WhileLoop

Endwhile: 
ADD R9, R9, #1                         ;R9 = R9 + 1
LDR R1, =array                         ;Load array address
MOV R2, R9, LSL #2                     ;multiply array index by 4 to get array offset
ADD R2, R1, R2                         ;Set R2 to element address
STR R8, [R2]                           ;A[R9] = R8
ADD R7, R7, #1                         ;increment index
B ForLoop
EndFor:

当我运行程序时,我的代码在while循环中以无限循环运行。任何帮助都将非常感谢。

2 个答案:

答案 0 :(得分:1)

while j >= 0 and A[j] > x
    A[j+1] = A[j]
    j = j -1

将是

while 1
   if (j<0) break;
   if (a[j] <= x) break;
    A[j+1] = A[j]
    j = j -1    

您的代码正在检查j == 0和A [j] == 0而不是

也在你的循环内,你将R9增加到A [j + 1],但不是恢复它 而不是手动计算“+1”,你可以做一个偏移'LDR R3, [R2, #4],这将为你做“+1”

答案 1 :(得分:0)

你的问题是你对这条线路有困难; while j >= 0 and A[j] > x。编译器实现 OR AND 的方式如下,

AND_CASE:
 tst cond1
 bxx  end_loop  ; false 1st condition
 tst cond2
 bxx  end_loop  ; false 2nd condition
 ; true code
 b AND_CASE
end_loop:

OR_CASE:
 tst cond1
 bxx true   ; short circuit (doesn't do 2nd statement)
 tst cond2
 bxx end_loop ; false 2nd condition
true:
 ; true code
 b OR_CASE
end_loop:

对于您的情况,您检查索引然后使用它。

AND_CASE:
 tst reg_j     ; testing index 'j'
 bmi end_loop  ; false
 ; r0 represents some free scratch register...
 ldr r0, [reg_a, reg_j, LSL #2]  ; get the memory
 cmp r0,reg_x            ; compare vs key
 blt end_loop  ; false
 ; true code
 b AND_CASE
end_loop:

验证条件是否适合您的签名。重要的一点是编译器一次测试一个条件,然后根据它是 OR 还是 AND 进行分支;分支的条件只是颠倒了。汇编程序员通常必须做与编译器相同的事情。对于iffor等语句及其条件,每件事都是相同的。

你的基本结构是正确的,但我认为你需要将ldr移动到'测试块'而不是把它包含在其他地方;即第二次条件测试。同样,你需要让你的标志和条件正确。我宁愿不提供这些信息,因为它是写记忆和学习的好练习。