[转译][马基 杰斯特(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
移位的位数以及语法
注意:这些规则同样对于
LSL
,LSR
,ASL
,ASR
,ROL
和ROR
指令都适用
立即数移位
最大的可以操作的移位位数是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 指令