原程序如下:
; K. Venkat
; Texas Instruments Inc.
; July 2006
; Built with IAR Embedded Workbench Version: 3.41A
;*******************************************************************************/
public div_hamacher
RSEG CODE
div_hamacher:
; R12 has dividend ; R14 has divisor
mov.w #16,R11
clr.w R13
start: rla.w R12
rlc.w R13
bis.w #1, R12
sub.w R14,R13
jge loc1 ;应该改为 jc loc1
add.w R14,R13
bic.w #1, R12
loc1: dec.w R11
cmp.w #0,R11 ;此比较多余,因为dec指令影响状态位z
jnz start
ret
END
这段程序依官方限制的数值(如果有提示的话)计算是没有问题的,比如说600÷400,结果是正确的:商为1、余数为200;但是,如果被除数是60000、除数是40000,这个程序就不会给我们正确的答案的,因为有条指令用错了。要避免这个错误,如果是用C编程的,只好乖乖地按官方提示的那样限制除数不能大于多少多少。而我们在复杂的应用里能很严肃的限定我们的被除数和除数吗?显然是很困难的。问题出在哪里呢?在jge loc1,这个jge是个有符号数的跳转指令,凡有符号数在单片机应用里都是非常危险的,一不小心就会让你想破了头都不知道程序问题出在哪里!这条指令如果改用jc loc1,一切烦恼就都没有了,随便怎么除都OK。
第2个bug其实可以忽略:dec.w R11后面有个跳转jnz start,当R11=1时,执行完dec就会让SR寄存器的“Z”位置位,中间加了条cmp.w #0,R11完全是多余的,虽然不影响程序执行的正确性,但是浪费了时间,在执行效率上是有瑕疵的。
Susan Yang:
谢谢您的反馈!请问能给出程序的详细出处吗?我们来测试一下,谢谢