我正在编写程序使用子程序DIVU进行无符号整数除法。 子程序将R1作为除数,将R0作为除数。只要除数不等于0,输出应该是R0剩余R1,进位标志为0.我的程序有问题,我想确保没有这个子程序行为不当的情况。我尝试过的每一个输入都给出了正确的输出,但是我想知道是否有人发现这个代码会有任何我看不到的问题。
DIVU PUSH {R2} ;store R2 Value
MOVS R2,#0 ;move 0 to R2 for quotient
CMP R0,#0 ;Compare divisor to 0
BEQ SETCARRY ;if divisor = 0 go to SETCARRY
WHILE CMP R1,R0 ;Compare R1 to R0
BLT ENDWHILE ;if dividend<Divisor End loop
ADDS R2,R2,#1 ;Add 1 to quotient
SUBS R1,R1,R0 ;Dividend - divisor
B WHILE ;branch to start of while
ENDWHILE
MOVS R0,R2 ;move quotient to R0, so R0 remainder R1
POP {R2} ;revert R2 to value before subroutine
PUSH {R0,R1} ;push R0 and R1
MRS R0,APSR ; Set C flag to 0
MOVS R1,#0x20 ; ""
BICS R0,R0,R1 ; ""
MSR APSR,R0 ; ""
POP {R0,R1} ;revert R0 and R1 to answer
QUITDIV BX LR ;Go back to program
SETCARRY
PUSH {R0,R1} ;Store R0 and R1
MRS R0,APSR ; Set C flag to 1
MOVS R1,#0x20 ;""
ORRS R0,R0,R1 ;""
MSR APSR,R0 ;""
POP {R0,R1} ; Revert R0 and R1 to answer
B QUITDIV ;Go back to program
答案 0 :(得分:1)
一个问题是,在除数为零的情况下,您永远不会pop r2
,因此您最终会在r2
中以可能意外的值返回,并且sp
指向错误的地方。
另一种方式是,无论哪种方式你根本不接触进位标志 - 即APSR的第29位,而你的0x20
掩码正在修改第5位(Thumb执行状态位),取决于你所处理的处理器模式,如果你试图将非零写回来,你可能会被忽略或者可能会产生不可预测的行为。
那就是说,你可以在修复它的同时摆脱一半的代码。在大多数架构版本中,您特别允许直接写入标志位,而不存在an immediate form of MSR
存在的读 - 修改 - 写序列。因此,清除标志只是MSR APSR_nzcvq, #0
的一种情况,单独设置进位标志将是MSR APSR_nzcvq, #0x20000000
。