[转译][马基 杰斯特(MarkeyJester) 摩托罗拉68000 入门教程] 肆 - 正负 指令 | 9. DIVU 和 DIVS 指令
注意:本文经过原作者授权转译,转载请标明出处
原文地址:http://mrjester.hapisan.com/04_MC68/Sect04Part09/Index.html
条件允许建议阅读原文,网上非中文资料还是较多,当作锻炼英文岂不美哉
翻译若有不足之处欢迎批评指正
译文:
"当内部没有你的敌人时,外部的敌人就无法伤害你" ---- 温斯顿 丘吉尔 (Winston Churchill, 1874-1965),英国政治家,
攘外必先安内 (雾)
简介
这一节要介绍的指令都是用作除法的,就像乘法有两个MULU
和MULS
一样,除法也有两个,一个用于无符号数
而另一个用于有符号数
在继续之前,你必须了解除法的不同的处理方式:
10 ÷ 3
当把10
除以3
时,有这两种情况:
- 结果是3.3循环 (3.3333333....)
- 结果是3余1 (3 r1, 3 remainder 1)
尽管第一个答案很精确,但第二个答案也是正确的,对于DIVU
和DIVS
来说,我们用的是第二种方法,也就是 m68k 所使用的方法:
10 ÷ 3 = 3 r1
这里大家都清楚3 r1
中的3
就是商
(quotient),而1
是余数
(remainder)
DIVU 指令
DIVU (Unsigned DIVide) - 无符号除
这条指令会用目的操作数
中的长字
除以源操作数
中的字
,结果被分为商
和余数
两部分,其中余数
被放到目的操作数
中的高位字
中,而商
会被放到目的操作数
中的低位字
中
如果商
的长度比一个字
要长,那么目的操作数
保持不变
例子
divu.w #$0002, d0
假设d0
的内容是00000803
,那么这条指令就是用d0
中的长字
除以字
0002
00000803 ÷ 0002 = 0401 r0001
答案是401
r1
(商
是0401
,余数
是0001
),于是d0
中的内容就变成了0001
0401
目的操作数
必须是一个数据寄存器,而源操作数
可以是立即数,数据寄存器,内存地址,或是地址寄存器表示的内存地址:
divu.w d1, d0
divu.w $00000010, d0
divu.w (a0), d0
对于源操作数
你不能直接使用一个地址寄存器:
divu.w a0, d0 ✖
最后,指令指定的长度只能是字
(.w
),你不能使用字节
或者长字
DIVS 指令
DIVS (Signed DIVide) - 有符号除
这条指令和DIVU
几乎相同,除了一点,那就是源操作数
和目的操作数
都会被当成有符号数
而不是无符号数
,所以这条指令可以像除以正数那样的去除以负数
例子
我们假定d0
的内容是FFFFFFF8
:
divs.w #$0002, d0
于是把d0
中的长字
FFFFFFF8
除以字
0002
FFFFFFF8 ÷ 0002 = FFFC r0000
这里FFFFFFF8
会被当成负数,而商
FFFC
也会被当成负数,所以事实上是这个效果:
-00000008 ÷ +0002 = -00000004
所以d0
中的内容变成了 0000
FFFC
(-4
r0
)
注意,如果目的操作数
是一个正数,那么余数
也是正数,同样的,如果目的操作数
是一个负数,那么商也是个负数。当然了,如果余数
是0000
的话,那它就是0000
... (余数不为零时的符号与目的操作数
的符号相同)
除了有符号
/无符号
的差别之外,DIVS
和DIVU
并无二致
不合法的情况
除法的过程是很简单,但是在一些特殊的情况下,除法指令会出点问题,比如假设d0
的内容是00040000
,然后执行下面这条指令:
divu.w #$0004, d0
然后:
00040000 ÷ 0004 = 10000 r0000
注意到没有,这时的商是10000
,对于无符号数来说最大的商
是FFFF
(一个字
的长度),如果你得到了一个比FFFF
还要大的商
,那么除法指令不会把结果放到d0
中,d0
将会保持00040000
不变,m68k 会当作无事发生
同样的规则对有符号数也适用,大于0000FFFF
的正数或是小于FFFF0000
的负数都会被无视
再来康康另一个除法指令不能处理的例子:
divu.w #$0000, d0
我们知道在数学规则中,你不能把一个数除以0
,因为无法计算结果,如果你尝试去除以0
,m68k 就会在这条指令停下,然后去运行一个除0异常处理程序
(我们会在以后的章节介绍异常处理,所以现在搞不明白也没关系)
对我来说,如果除0异常
发生了的话,直接把结果设成0
貌似也没什么不好,不会阻止程序运行也符合程序的逻辑,当然这只是我的个人见解,你懂的
目前来说,我不是很赞成这种忽视
除0异常
的做法
家庭作业
到目前为止,你应该了解了:
- 有符号和无符号数
- 移位
- 循环移位
- 乘法和除法指令
那么这里有一系列的指令:
move.w #$0010, d0
mulu.w #$0003, d0
neg.w d0
ext.l d0
asr.l #$01, d0
ror.w #$01, d0
ext.l d0
divu.w #$0002, d0
d0
初始内容是00000000
,请尝试算出在这些指令执行完了之后d0
的内容是多少,你可以随时的使用十六进制计算器
,这些指令只是为了测试你清楚了这些指令的用法,而不是为了测试你的数学计算能力
目录
上一篇:[转译][马基 杰斯特(MarkeyJester) 摩托罗拉68000 入门教程] 肆 - 正负 指令 | 8. MULU 和 MULS 指令
下一篇:[转译][马基 杰斯特(MarkeyJester) 摩托罗拉68000 入门教程] 肆 - 正负 指令 | 10. 家庭作业答案 - 4