[转译][马基 杰斯特(MarkeyJester) 摩托罗拉68000 入门教程] 贰 - 基本指令 | 2. SUB 指令(减)
注意:本文经过原作者授权转译,转载请标明出处
原文地址:http://mrjester.hapisan.com/04_MC68/Sect02Part02/Index.html
条件允许建议阅读原文,网上非中文资料还是较多,当作锻炼英文岂不美哉
翻译若有不足之处欢迎批评指正
译文:
"如果人们不肯相信数学很简单的话,他们可能只是没意识到生活有多难" ---- 冯 诺依曼 (John Louis von Neumann, 1903-1957),计算机之父
简介
SUB (减) - 二进制减法
这条指令能把目的操作数
减去源操作数
,结果再放回到目的操作数
中,而源操作数
保持不变
例子
这显然是add
指令的反操作,比如下面这个例子:
subi.b #$10, d0
这会把字节
10
从数据寄存器d0
中减去:
- 如果
d0
里原本是00000010
,那么指令执行后d0
里的内容会变成00000000
- 如果
d0
里原本是0000002E
,那么指令执行后d0
里的内容会变成0000001E
- 如果
d0
里原本是000000E4
,那么指令执行后d0
里的内容会变成000000D4
- 如果
d0
里原本是00000008
,那么指令执行后d0
里的内容会变成000000F8
当然别忘了,我们只是在减一个字节
,所以:
- 如果
d0
里原本是00001014
,那么指令执行后d0
里的内容会变成00001004
- 如果
d0
里原本是222222FC
,那么指令执行后d0
里的内容会变成222222EC
- 如果
d0
里原本是33333301
,那么指令执行后d0
里的内容会变成333333F1
上面所有的指令都遵循这么一个规则,就是只有最右边那个字节
被修改了
在来康康一个用字
的例子:
subi.w #$0200, d0
这会把字
0200
从数据寄存器d0
中减掉:
- 如果
d0
里原本是00000500
,那么指令执行后d0
里的内容会变成00000300
- 如果
d0
里原本是00004B20
,那么指令执行后d0
里的内容会变成00004920
- 如果
d0
里原本是4444310F
,那么指令执行后d0
里的内容会变成44442F0F
当然同样的,只有最右边的字
会受到影响
别的例子
你可以从寄存器里减掉另一个寄存器的内容:
sub.l d0, d1
这条指令会把d1
里的内容减掉d0
里的内容:
- 如果
d0
里原本是010000F0
,d1
里原本是02000100
,那么指令执行后d1
里的内容会变成01000010
你也可以把内存中的数据做减法:
sub.w d0, $0000102E
这会把d0
中的一个字
复制出来,然后用内存中地址为$0000102E
位置的数据减去它,再放回$0000102E
中。如果d0
中的内容是09920022
,内存中$0000102E
和$0000102F
位置的字节
分别是00
和2E
,那么002E
- 0022
= 000C
,00 0C
就会被写入到内存中$0000102E
和$0000102F
的位置:
偏移量 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
... | ||||||||||||||||
00001000 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
00001010 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
00001020 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 0C |
00001030 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
... |
你也可以把寄存器中的数据减去内存中的数据:
sub.b $00001040, d0
如果d0
中的内容是00121080
,内存中的数据是:
偏移量 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
... | ||||||||||||||||
00001030 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
00001040 | 70 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
00001050 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
00001060 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
... |
70
会被从内存中复制出来,然后由d0
中的字节
80
减去,指令执行后d0
的内容会变成00121010
和加法指令add
一样,你也不能从一个内存地址减去另一个内存地址的数据:
sub.b $00000120, $00000124 ✖
不过这里同样也有类似的解决方法:
move.b $00000120, d0
sub.b d0, $00000124
如你所见,我们先把内存中00000120
中的数据放到一个数据寄存器里,然后再从内存的00000124
位置中减去这个数据寄存器中的内容
同样的你也可以使用地址寄存器来做寄存器间接寻址:
sub.w d1, $72(a0)
sub.l $40(a0), d4
sub.w d5, (a1)
subi.b #$98, (a0)+
sub.w a1, d0
然而你也一样不能通过地址寄存器的间接寻址从内存中去减内存的数据:
sub.w (a0), (a1)
✖
sub.l (a0)+, $10($a2)
✖
sub.w $9E(a4), -(a3)
✖
sub.b $10(a0), $10(a6)
✖
减 立即数
跟加法指令一样,如果源操作数
是立即数
,你必须使用subi
指令,而不是sub
指令 (其中i
表示立即数
)
subi.b #$20, d0
同样的汇编程序在汇编代码的时候会自动把需要用到subi
的地方的sub
修改为正确的写法
目录
上一篇:[转译][马基 杰斯特(MarkeyJester) 摩托罗拉68000 入门教程] 贰 - 基本指令 | 1. ADD 指令(加)
下一篇:[转译][马基 杰斯特(MarkeyJester) 摩托罗拉68000 入门教程] 贰 - 基本指令 | 3. SWAP 指令