[转译][马基 杰斯特(MarkeyJester) 摩托罗拉68000 入门教程] 肆 - 正负 指令 | 6. LSL, LSR, ASL 和 ASR 指令

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

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

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

译文:

"我们正生活在一个观念转变的时代。父母不负责任,家庭分崩离析。" ---- 戈登 欣克利 (Gordon B. Hinckley, 1910-2008),美国宗教领袖,作家

简介

在上一节我们了解了"移位",以及"逻辑移位"和"算术移位"的区别。在这一节我们来康康一些具体的移位指令,由于它们大多拥有类似的使用规则,所以我把它们放在了同一节里面一并来讲

如果你们觉得看这一节有困难的话,请给我提意见或是建议,我将会尝试着去改进

我的邮箱地址在 目录 可以找得到

LSL 指令

LSL (Logical Shift Left) - 逻辑左移

这条指令会把目的操作数中的内容做逻辑左移,移动的位数取决于源操作数

例子

先用我常常使用的那个最基本的例子吧:

    lsl.b      #$02, d0

这条指令会把d0中的字节向左移动02位。现在我们假定d0的内容是000004B2,由于移动的是字节,所以只有B2会被修改,B2的二进制是:

    1011 0010

在左移02位之后,会得到:

  < 1100 1000 <

1100 1000在十六进制是C8,保存到d0里,所以d0的内容就变成了000004C8

再来康康另一个例子:

    lsl.w      #$04, d2

这条指令会把d2中的向左移动04位。现在我们假定d2的内容是00F0FEDC,由于移动的是,所以只有FEDC会被修改,FEDC的二进制是:

    1111 1110 1101 1100

在左移04位之后,会得到:

  < 1110 1101 1100 0000 <

FEDC变成了EDC0,所以此时d2的内容是00F0EDC0

移位的位数以及语法

注意:这些规则同样对于LSLLSRASLASRROLROR指令都适用

立即数移位

最大的可以操作的移位位数是08位,最小的是01位,如果你想要移位位数超过08位,那你只需要把指令拆成两个指令先后执行即可,比如想要左移0C位:

    lsl.l      #$08, d0
    lsl.l      #$04, d0

从上面可以看出,第一条指令先左移了08位,然后第二条指令又左移了04位,加起来就是总共左移了0C位。当然了,是存在其他的更快捷的指令,不过最好是留在以后再说

现在如果你想要仅仅左移01的话,只需要像这样写:

    lsl.w      d0

此时汇编程序会把指令自动转换位:

    lsl.w      #$01, d0

有些人习惯于不写#$01,大概是想要省去一些打字的力气,谁知道呢。对于我个人来说,我总是会写上#$01。不过这要看你自己的习惯,写不写事实上是一样的

寄存器移位

你可以使用一个数据寄存器用来表示移位的位数,比如:

    lsl.l      d0, d1

在这个例子中,d1的内容会被左移,位数取决于d0里的数字,假设d0的内容是0000010F

源操作数来说,只有一个字节会被当做移位的位数,因为d0的内容是0000010F,所以其中的0F会被当做位数。所以d1中的长字会被左移0F

你可以移位的最大位数取决于你的指令所使用的长度:

  • 字节 (.b)最大允许移动$08
  • (.w)最大允许移动$10
  • 长字 (.l)最大允许移动$1F位 (此处应为$20位?)

如果源操作数字节要比最大的移位位数要大的话,就会默认按照最大的移位位数来移位,比如:

    lsl.b      d0, d1

如果d0里的字节09或是更大的数的话,那么d1会按照.b的最大移位位数而只移动08

内存移位

当在数据寄存器上使用移位指令时,你可以用字节或是长字长度的指令,而且可以一次移动超过01位,但是对于内存移位来说,你只能使用的长度,而且只能一次移动01位:

    lsl.w      $00FF0000
    lsl.w      $20(a0)
    lsl.w      (a0)+
    lsl.w      -(a0)

注意:在内存移位中,没有源操作数,如果你这样写的话:

    lsl.w      #$01, $00FF0000
    lsl.w      #$01, $20(a0)
    lsl.w      #$01, (a0)+
    lsl.w      #$01, -(a0)

你的汇编程序有可能会报错,不过有些汇编程序可能没那么敏感,不过最好在内存移位时还是不要指定移位长度01

当然,你也不能直接把这个指令直接用在地址寄存器上:

    lsl.w      #$04, a0   
    lsl.l      a0         
    lsl.l      d0, a0     

LSR 指令

LSR (Logical Shift Right) - 逻辑右移

这条指令会把目的操作数中的内容做逻辑右移,移动的位数取决于源操作数

例子

    lsr.b      #$02, d0

这条指令会把d0中的字节向右移动02位。现在我们假定d0的内容是000004B2,由于移动的是字节,所以只有B2会被修改,B2的二进制是:

    1011 0010

在右移02位之后,会得到:

  > 0010 1100 >

0010 1100在十六进制是2C,保存到d0里,所以d0的内容就变成了0000042C

再来康康另一个例子:

    lsr.w      #$04, d2

这条指令会把d2中的向右移动04位。现在我们假定d2的内容是00F0FEDC,由于移动的是,所以只有FEDC会被修改,FEDC的二进制是:

    1111 1110 1101 1100

在右移04位之后,会得到:

  > 0000 1111 1110 1101 >

FEDC变成了0FED,所以此时d2的内容是00F00FED

ASL 指令

ASL (Arithmetic Shift Left) - 算术左移

这条指令会把目的操作数中的内容做算术左移,移动的位数取决于源操作数

例子

这和LSL指令大致相同:

    asl.b      #$02, d0

这条指令会把d0中的字节向左移动02位。现在我们假定d0的内容是000004B2,由于移动的是字节,所以只有B2会被修改,B2的二进制是:

    1011 0010

在左移02位之后,会得到:

  < 1100 1000 <

1100 1000在十六进制是C8,保存到d0里,所以d0的内容就变成了000004C8

由于逻辑左移和算术左移的结果是一样的,所以这条指令和LSL指令的效果是一样的

其实当然还是有区别的LSL指令会清除V状态字,而ASL指令会根据结果来设置或是清除V状态字,然而V状态字是CCR (Conditional Code Register, 状态寄存器) 的一部分,我们会在之后教程里会提到的一个快速对照表里详细的解释,所以现在搞不清楚没关系

ASR 指令

ASR (Arithmetic Shift Right) - 算术右移

这条指令会把目的操作数中的内容做算术右移,移动的位数取决于源操作数

例子

这和LSL指令大致相同:

    asr.b      #$02, d0

这条指令会把d0中的字节向左移动02位。现在我们假定d0的内容是000004B2,由于移动的是字节,所以只有B2会被修改,B2的二进制是:

    1011 0010

在左移02位之后,会得到:

  > 1110 1100 >

1110 1100在十六进制是EC,保存到d0里,所以d0的内容就变成了000004EC

注意:MSB之前是1,所以移位之后它仍是1

再来康康另一个例子:

    asr.w      #$04, d2

这条指令会把d2中的向右移动04位。现在我们假定d2的内容是00F07EDC,由于移动的是,所以只有7EDC会被修改,7EDC的二进制是:

    0111 1110 1101 1100

在右移04位之后,会得到:

  > 0000 0111 1110 1101 >

7EDC变成了07ED,所以此时d2的内容是00F007ED

由于MSB之前是0,所以移位之后它仍是0

目录
上一篇:[转译][马基 杰斯特(MarkeyJester) 摩托罗拉68000 入门教程] 肆 - 正负 指令 | 5. 移位
下一篇:[转译][马基 杰斯特(MarkeyJester) 摩托罗拉68000 入门教程] 肆 - 正负 指令 | 7. ROL 和 ROR 指令

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