[转译][马基 杰斯特(MarkeyJester) 摩托罗拉68000 入门教程] 壹 - 基础介绍 | 4. 寄存器
注意:本文经过原作者授权转译,转载请标明出处
原文地址:http://mrjester.hapisan.com/04_MC68/Sect01Part04/Index.html
条件允许建议阅读原文,网上非中文资料还是较多,当作锻炼英文岂不美哉
翻译若有不足之处欢迎批评指正
译文:
"生活就像是一台收银机,那些誓言、思想还有功绩就像是每笔交易,都被登记在册" ---- 富尔顿·约翰·施恩 (Fulton J. Sheen, 1859-1979),美国罗马天主教主教、教育家、作家
简介
在处理器的内部也有一些存储的空间叫做寄存器
,不同类型处理器根据其设计结构和设计目的的不同,各自有着不同类型的寄存器。得益于距离处理器极近,与处理器联系密切,所以对于数据的移动,加减操作,读取写入要比任何其他的存储设备(比如高速缓存,内存,硬盘等) 效率更高,速度更快(由于是集成在处理器内部,造价也更高,存储空间也更小),接下来我们将要康康m68k 中的16 个通用寄存器是干什么的:
数据寄存器
m68k 拥有8 个数据寄存器
,他们分别被命名为:
d0, d1, d2, d3, d4, d5, d6, d7
数据寄存器
被用来在数学层面上存储和修改数据,每个寄存器
都拥有一个长字
大小的存储空间:
寄存器名称 | 存储空间(十六进制) |
---|---|
d0 | 00 00 00 00 |
d1 | 00 00 00 00 |
d2 | 00 00 00 00 |
d3 | 00 00 00 00 |
d4 | 00 00 00 00 |
d5 | 00 00 00 00 |
d6 | 00 00 00 00 |
d7 | 00 00 00 00 |
让我们用之前那条指令来做例子:
move.w #$04F0, d0
这将会把字
04F0
写入寄存器d0
,指令被m68k 执行后,d0
中的内容将会是00 00 04 F0
当然你也可以在任何时候对这些寄存器执行字节
,字
或是长字
的指令(通过指令命令后的.b
,.w
还有.l
来指定),而且大部分的指令都可以支持对寄存器的操作,我们将会在之后再详细说明
地址寄存器
m68k 也拥有8 个地址寄存器
,分别称为:
a0, a1, a2, a3, a4, a5, a6, a7
每个地址寄存器
同样也包含一个长字
大小的存储空间:
寄存器名称 | 存储空间(十六进制) |
---|---|
a0 | 00 00 00 00 |
a1 | 00 00 00 00 |
a2 | 00 00 00 00 |
a3 | 00 00 00 00 |
a4 | 00 00 00 00 |
a5 | 00 00 00 00 |
a6 | 00 00 00 00 |
a7 | 00 00 00 00 |
它们在使用上与数据寄存器
类似,除了有一点:你不能对它们执行字节
长度的指令(只有字
和长字
可以),而且有一些类型的指令 只能 工作在数据寄存器
上而 不能 工作在地址寄存器
上,此处不详细展开,后续会有介绍
这些地址寄存器
被用来存储地址
(也就是之前常说的偏移量
),而且能够写入和读取地址
,比如:
movea.l #$00000039, a0
这条指令会把长字
00000039
写入a0
,所以a0
在指令执行后的内容是00000039
,看起来和数据寄存器
的用法基本一致。而现在我们的a0
里面已经有一个长字
的数据了,就可以根据这点做出另一种操作:
move.b #$44, (a0)
不知你是否留意到,这次我们把a0
加了括号里变成了(a0)
,那么m68k 在看到这条指令的时候并不会把44
放到a0
里,而是会把它放到a0
里面的内容所代表的地址
中,比如此时a0
的内容是00000039
,所以这条指令执行后会把44
放到内存中00000039
的位置:(学习过《计算机组成原理》的同学应该知道,此方式即为寄存器间接寻址
)
偏移量 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
00000000 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
00000010 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
00000020 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
00000030 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 44 | 00 | 00 | 00 | 00 | 00 | 00 |
... |
如你所见,此时的a0
像是一个内存的代理
除此之外,地址寄存器
还有一些其他的功能,比如"索引",比如说(假设a0
里面的内容仍然是00000039
):
move.b #$9B, $04(a0)
这次我们把目的操作数
改成了$04(a0)
,其中$04
就是索引值,这将会把a0
里的内容和索引值$04
相加得到一个新的偏移量
作为目的操作数
,即00000039
+ 04
= 0000003D
,所以内存中0000003D
位置被修改为9B
:
偏移量 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
00000000 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
00000010 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
00000020 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
00000030 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 9B | 00 | 00 |
... |
好了,休息一下,我们再继续
这里有另外一个更直观的例子:
movea.l #$00000010, a0
move.b #$20, $01(a0)
move.b #$40, $02(a0)
move.b #$F0, $0F(a0)
move.b #$0E, (a0)
那么,解释一下就是
- 把
00000010
写入地址寄存器
a0
- 把
20
写入偏移量
00000011
(00000010
+01
) - 把
40
写入偏移量
00000012
(00000010
+02
) - 把
F0
写入偏移量
0000001F
(00000010
+0F
) - 把
0E
写入偏移量
00000010
结果就是:
偏移量 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
00000000 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
00000010 | 0E | 20 | 40 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | F0 |
00000020 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
00000030 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
... |
自增/自减
另一个功能是"自增"和"自减",来康康这个:
movea.l #$00000020, a0
move.b #$B5, (a0)+
move.b #$11, (a0)+
我们又把上面你所知的(a0)
改成了(a0)+
,括号的右边加了个+
号,这,就是"自增":
- 把
00000020
写入a0
- 把
B5
写到a0
中的地址
(把B5
写到内存中的00000020
位置) +
符号会把a0
中的内容自动 +1,此时a0
中的内容是00000021
(00000020
+1
)- 把
11
写到a0
中的地址
(把11
写到内存中的00000021
位置) +
符号把a0
内容 +1,此时a0
中是00000022
(00000021
+1
)
没错,我们刚刚对(a0)
做的改动(a0)+
就是一旦数据被写到对应的地址
(偏移量
)之后,就把a0
的内容 +1
再来康康另一个例子,跟刚才不同的是这次我们用了 move.w 而不是 move.b:
movea.l #$00000020, a0
move.w #$A90E, (a0)+
- 把
00000020
写入a0
- 把
字
A90E
写入到a0
中存储的地址
00000020
(其中A9
写入到00000020
,0E
写入到00000021
) +
符号会把a0
中的内容自动 +2(现在a0
中的内容是00000022
)
为什么这次会 +2 呢,就是因为我们操作了一个字
长度的数据,而一个字
恰好是2 个字节
的长度。同理,如果我们用 move.l 来类似的操作一个长字
的数据,那么a0
中的内容会自动 +4,因为一个长字
是4 个字节
"自减"也很类似,不过是反着的:
movea.l #$00000020, a0
move.b #$2E, -(a0)
可能你注意到这个例子里,有一个-
符号,但是它却在(a0)
的左边而不是右边:
- 把
00000020
写入a0
-
符号会把a0
中的内容自动 -1 (现在a0
中的内容是0000001F
)- 把
2E
写入到0000001F
对于"自减"来说,地址寄存器
总是在指令操作源操作数
之前进行"自减"
好啦,本节就到这里,仍还有一些其他的"索引"方式用于地址寄存器
,但目前为止留给此后的其他章节比较合适
对于自增和自减,我还未遇到诸如(a0)-
或是+(a0)
之类的写法,所以正如原作者所说,仅有(a0)+
和-(a0)
的写法
目录
上一篇:[转译][马基 杰斯特(MarkeyJester) 摩托罗拉68000 入门教程] 壹 - 基础介绍 | 3. 指令集
下一篇:[转译][马基 杰斯特(MarkeyJester) 摩托罗拉68000 入门教程] 壹 - 基础介绍 | 5. MOVE 指令