📄 em78 byte2mulasm.txt
字号:
;QIUYINGDOCUMENT
; EM78 双字节的乘法
;----------------------------------------------------------------
; (R22:R23)*(R24:R25)-->(R20:R21:R22:R23)
mul_sub:
clr r20
clr r21
mov a,@16
mov count,a
bc psw,c
rrc r22
rrc r23
mul_r1:
jbs psw,c
jmp mul_r2
mov a,r25
add r21,a
jbc psw,c
inc r20
jbc psw,c
jmp mul_r0
mov a,r24
add r20,a
jmp mul_r2
mul_r0:
mov a,r24
add r20,a
bs psw,c
mul_r2:
rrc r20
rrc r21
rrc r22
rrc r23
djz count
jmp mul_r1
ret
说明:
因为咱们ELAN没有带进位的加法,所以可能会出现一个隐藏的错误,上面给出的程序是正确的,
确实可以正常运行,理论解释也能解释明白,下面分析一个错误,详细叙述如下。
有几个地方是需要注意的,第一,高低位相加的时候,有一种情况,原来寄存器的数值是0xff
如果执行 inc 指令,那么会变成 0x00,而且进位c会置一,但是因为后面还有一条加法指令
add r20,a ,这个加法的结果是肯定不会超过0xff (因为这里是0+ 1~0xff之间的数),所以
这条add指令之后的结果进位c铁定会变成0,那么结果出错了
试试用 0xffff × 0xffff 就会遇到这种情况。
假设 r24r25 放被乘数,而且在运算过程中r24 r25 中的数值都比较大,加上0xff之后都会溢出
如果按照普通的C51单片机教程的乘法思想来编写的话,很容易会形成下面的程序(当然,那个编程
思想是正确的,只是说转换成ELAN语言的时候会容易犯错误。)
看下面的错误的程序:
mov a,r25 ; 加上低位
add r21,a
jbc psw,c ; 假设溢出了,高位加1
inc r20 ; 执行inc,r20变成0x00
mov a,r24 ; 加上高位
add r20,a ; 执行这指令之后 psw中的c会变成0
对上面的程序举个例子,假设r24=0xff ,r25=0xff ,r20=0xff ,r21=0xff
这个极端的例子来说明问题,看看程序执行之后会产生什么问题
mov a,r25 ; 加上低位
add r21,a
f f
+ f f
--------- 结果应该是3位的,最高位1保存在psw的c里面
1 f e r21的结果结果为 0xfe
;-----------------------------------------------------------------
jbc psw,c ; 假设溢出了,高位加1
inc r20 ; 执行inc,r20变成0x00
因为上面计算结果溢出,所以c为1,所以执行 inc 指令
f f
+ 1
-------
1 0 0 r20的结果为 0x00,溢出的 1 保存在psw的c当中
;-----------------------------------------------------------------
mov a,r24 ; 加上高位
add r20,a ; 执行这指令之后 psw中的c会变成0
0 0
+ f f
-------
0 f f 由于add指令是影响psw的c位的,这个运算之后将c清掉了
本来是 ff + 1 + ff = 1ff 的运算,由于 c位被清掉了,变成
ff + 1 + ff = 0ff ,可见以上的程序是有隐藏错误的,并不是所有的计算
都会出错,只是遇到上面说的情况的时候就会出错,一般表现为很大的两个数乘法的时候
出现,一个比较郁闷的隐藏错误。解决办法很简单,分开两种情况处理就OK了。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -