[转译][马基 杰斯特(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 (子过程调用/返回) 指令
 
                    
                     
                    
                 
                    
                 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号