Assembly 如何在ARMSim中使用2个条件进行while循环?
我正在尝试在arm汇编中执行插入排序,但我不知道如何使用2个条件执行while循环?我从wikipedia获得了该算法的伪代码,但我在将while循环转换为arm指令时遇到了问题,因为有2个条件Assembly 如何在ARMSim中使用2个条件进行while循环?,assembly,while-loop,arm,Assembly,While Loop,Arm,我正在尝试在arm汇编中执行插入排序,但我不知道如何使用2个条件执行while循环?我从wikipedia获得了该算法的伪代码,但我在将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汇编指
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循环中以无限循环运行。任何帮助都将不胜感激
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
1
如果(j你的问题表明你在这一行上有困难;而j>=0和A[j]>x
。编译器实现或和和的方法如下:
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:
验证该条件是否适合您的签名。重要的一点是,编译器一次测试一个条件,然后根据它是还是或和执行分支;这些条件正好与分支相反。汇编程序员通常必须做与compi相同的事情对于if
,for
,etc语句及其条件,一切都是一样的
您的基本结构正确,但我认为您需要将ldr
移动到“测试块”中,而不要将其包括在其他位置;即第二个条件测试。此外,您还需要将您的符号和条件正确。我不希望给出此信息,因为这是一个很好的记忆和学习练习。我们在循环中执行R9=R9+1
和R9=R9-1
,因此j
永远不会达到0。我认为您应该使用另一个变量来存储j+1
,即使按照检查A[j]的方式修复jack3694078指出的错误>x
看起来仍然不正确。对于每个迭代,除了第一次,您似乎在检查中使用上一次迭代中的A[j]
,但由于j
应该在每个迭代结束时递减,从而使上一次迭代中的A[j]
成为A[j+1]
用于本次迭代。为什么对于显然应该是=
和
的测试,您有eq
条件代码,即=
?ARM支持许多索引模式,所以您不需要手动计算A[j]
暂存寄存器中的地址。此外,跟踪寄存器非常重要,不要将一个寄存器用于不同的事情!如果汇编程序支持,最好对寄存器进行“命名”,或者至少保留注释说明寄存器的用途。