[转译][马基 杰斯特(MarkeyJester) 摩托罗拉68000 入门教程] 肆 - 正负 指令 | 9. DIVU 和 DIVS 指令

注意:本文经过原作者授权转译,转载请标明出处

原文地址:http://mrjester.hapisan.com/04_MC68/Sect04Part09/Index.html

条件允许建议阅读原文,网上非中文资料还是较多,当作锻炼英文岂不美哉
翻译若有不足之处欢迎批评指正

译文:

"当内部没有你的敌人时,外部的敌人就无法伤害你" ---- 温斯顿 丘吉尔 (Winston Churchill, 1874-1965),英国政治家,
攘外必先安内 (雾)

简介

这一节要介绍的指令都是用作除法的,就像乘法有两个MULUMULS一样,除法也有两个,一个用于无符号数而另一个用于有符号数

在继续之前,你必须了解除法的不同的处理方式:

    10 ÷ 3

当把10除以3时,有这两种情况:

  1. 结果是3.3循环 (3.3333333....)
  2. 结果是3余1 (3 r1, 3 remainder 1)

尽管第一个答案很精确,但第二个答案也是正确的,对于DIVUDIVS来说,我们用的是第二种方法,也就是 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中的内容就变成了00010401

目的操作数必须是一个数据寄存器,而源操作数可以是立即数,数据寄存器,内存地址,或是地址寄存器表示的内存地址:

    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中的内容变成了 0000FFFC (-4r0)

注意,如果目的操作数是一个正数,那么余数也是正数,同样的,如果目的操作数是一个负数,那么商也是个负数。当然了,如果余数0000的话,那它就是0000... (余数不为零时的符号与目的操作数的符号相同)

除了有符号/无符号的差别之外,DIVSDIVU并无二致

不合法的情况

除法的过程是很简单,但是在一些特殊的情况下,除法指令会出点问题,比如假设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

posted @ 2020-03-04 10:57  草帽过客  阅读(741)  评论(0编辑  收藏  举报