[转译][马基 杰斯特(MarkeyJester) 摩托罗拉68000 入门教程] 伍 - 程序流程控制 | 4. SP (Stack Pointer) 栈指针寄存器
注意:本文经过原作者授权转译,转载请标明出处
原文地址:http://mrjester.hapisan.com/04_MC68/Sect05Part04/Index.html
条件允许建议阅读原文,网上非中文资料还是较多,当作锻炼英文岂不美哉
翻译若有不足之处欢迎批评指正
译文:
"那一堆的过去永远比不上一个小小的希望" ---- 查尔斯 舒尔茨 (Charles M. Schulz, 1922-2000),美国漫画家
简介
总会有一种情况,m68k 需要存储一些非常重要的信息,或者说是你想要存储一些重要的信息
栈 (stack) 就是为了这个目的而设计的
栈 (stack)
栈
是一块可以用来临时存储重要信息的内存空间,你可以指定 m68k 的栈的地址在哪,也可以随时地修改栈的地址
地址寄存器a7
被用作栈顶指针 (SP
, Stack Pointer),在 m68k 的内存中由你来指定它的栈在什么地方,有两种方法来设置栈,比如使用a7
:
movea.l #$00100000, a7
或者使用SP
:
movea.l #$00100000, sp
两种都可以,效果是一样的,因为a7
是被用作SP
的,所以a7
就是SP
存储
在上面的例子里,我已经把 m68k 的栈地址设置为100000
,不过,在栈里面,数据是反着存储的,这是一个你把数据存到栈里面的例子 (我用的是sp
,当然你也可以用a7
):
move.w d0, -(sp)
move.l d1, -(sp)
注意,SP
是被当做一个地址寄存器
来使用的,同样也请注意那个-
符号。第一条指令执行后,d0
的一个字
会被保存到栈
里,比如d0
的内容是FF000020
,于是0020
就会被保存到栈
里:
偏移量 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
... | ||||||||||||||||
000FFFD0 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
000FFFE0 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
000FFFF0 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 20 |
00100000 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
... |
如你所见,那个字
被放到0FFFFE
和0FFFFF
的位置。这是因为栈
顶指针在保存0020
之前向后移动了 (栈顶指针减去指令使用的长度,.w
表示的一个字
的长度),于是SP
会变成0FFFFE
紧接着的一条指令把d1
中的数据保存到栈
里,所以我们假定d1
的内容是FEDCBA98
,于是:
偏移量 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
... | ||||||||||||||||
000FFFD0 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
000FFFE0 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
000FFFF0 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | FE | DC | BA | 98 | 00 | 20 |
00100000 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
... |
再一次的,SP
被从0FFFFE
向后移动到了0FFFFA
,同时FEDCBA98
也被保存到了内存里
重新装载
从栈
里面把数据读出来是反着的:
move.l (sp)+, d1
move.w (sp)+, d0
第一条指令会从栈
的0FFFFA
位置读取一个长字
的数据然后保存到d1
里面,于是FEDCBA98
被从栈
里复制出来然后放进d1
里,而SP
向前移动到0FFFFE
接下来第二条指令会从栈
的0FFFFE
位置读取一个字
的数据然后保存到d0
里面,于是0020
被从栈
里复制出来然后放进d0
里,而SP
向前移动到100000
总结
值得注意的是,当你把数据从栈
里加载出来的时候,你只是复制
了数据,也就是说尽管SP
指针向前移动了,但是之前的数据仍然还保存在内存中:
偏移量 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
... | ||||||||||||||||
000FFFD0 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
000FFFE0 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
000FFFF0 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | FE | DC | BA | 98 | 00 | 20 |
00100000 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
... |
这些数据会在你下次往栈
里存数据的时候被覆盖掉
说到 m68k 存储数据,下一节我们会介绍一些能够让 m68k 自动去使用栈
的指令,会让你更好地理解为什么会有栈
这种东西存在
目录
上一篇:[转译][马基 杰斯特(MarkeyJester) 摩托罗拉68000 入门教程] 伍 - 程序流程控制 | 3. BRA (分支) 指令
下一篇:[转译][马基 杰斯特(MarkeyJester) 摩托罗拉68000 入门教程] 伍 - 程序流程控制 | 5. JSR & RTS (子过程调用/返回) 指令