目标
- 实现并理解栈:从硬件角度理解栈的物理基础,从软件角度理解栈的逻辑概念
- 实现所有栈相关的指令(CALL、RET、RETI、RST、PUSH、POP…)
- 实现跳转相关的指令(JR、JP…),满足流程控制需求
知识点
- CALL指令讲解
- 功能:父函数调用一个子函数
- 实现:将当前PC的值压入栈中后(以备后续RET指令使用),让PC跳转到指定的地址
- RET指令讲解
- 功能:从子函数返回调用它的父函数
- 实现:从栈中弹出一个值,并让PC跳转到该值(前面备的就用上了),这样PC就会回到父函数执行完子函数的地方,去执行下一条指令
- 栈的生长方向:从高地址到低地址
在GameBoy的CPU初始化函数中
|
|
可以看到SP指针被初始化为0xFFFE,是相当大的一个地址,这意味着栈可以最大程度地往0x0的方向生长(Stack RAM就是High RAM,FF80h-FFFEh,共127字节)
- 栈的逻辑概念
- 存储一系列相同的元素、对元素可以进行push和pop的一个数据结构
- 栈的物理基础:地址和寄存器
- 地址提供元素的存储,SP寄存器标识了栈顶地址(更本质的说法是下一个要被pop的元素位置)
- gameboy的CPU(8080)栈只依赖SP寄存器
- 更复杂的CPU(如8086)提供BP和SP寄存器,可以有更复杂的栈逻辑
- 围绕SP寄存器构建的CPU指令(PUSH和POP),enable了栈的功能
寄存器和地址的物理基础使得CPU的栈指令成为可能,汇编语言得以栈式地管理元素。高级编程语言中的函数调用机制,在底层就是利用CPU的栈指令(类似我们实现的CALL指令)实现的。