[转译][马基 杰斯特(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 指令
浙公网安备 33010602011771号