【SMB源码解析系列】——001.JumpEngine函数
在SMB的源码中大概有不到20处看起来很奇怪的指令,它的格式是通过jsr指令调用一个名为JumpEngine的函数,其后并不是跟随某些后续的逻辑指令,而是通过.dw定义了一系列16位地址。

我们可以看到在jsr指令之前,还会将某个值写入A寄存器。
JumpEngine函数本身代码并不长:

让我们来看看这段函数到底做了什么:
1.将A寄存器的值乘以2,然后写入Y寄存器;
2.从栈中取出2字节数据,分别写入$04、$05,然后将Y寄存器的值+1;
3.通过"后索引间接寻址"方式,将($04),y中的数据写入到$06中,又将($04),y+1处的数据写入$07中;
4.通过"间接寻址"方式,跳转至($0006)处执行代码。
原本我们如果在966行处调用了jsr指令(此时会先将指令所在地址$8234+2=$8236推入栈中),按正常流程应该在跳转至JumpEngine之后某处调用一次rts指令(把栈中的$8236取出并+1得到$8237),然后程序会跳转至$8237处继续执行。
但在第二步,我们将栈中的信息手动取出($8236),存入了$04、$05,并将Y寄存器+1,如果OperMode_Task的值是0的话,此时$04、$05中保存的值是$8236,Y寄存器的值为0*2+1=1,lda ($04),y就相当于是把$8236+1=$8237处的数据取出来写入$06,接着又将($04),y+1也就是$8238处的值取出来,写入$07。
这时我们就发现,968行通过.dw定义的16位地址InitializeGame已经被写入$06、$07中了。
最后通过唯一的一个间接寻址指令jmp ($0006)我们就跳转到了InitializeGame继续执行代码。
程序中的其他地方,可能会修改OperMode_Task的值为1,这样第二步Y寄存器的值最终为1*2+1=3,第三步就是把$8239,$8240处的值(ScreenRoutines)取出来了。目前看来这种方式最长可以通过.dw定义100多个函数地址~
SMB中就是依靠JumpEngine函数,让程序按照某个顺序逐一执行,序列化的完成了整个游戏逻辑的控制。不过我觉得这更像是在射击CPU硬件逻辑时就设计好的一个"语法糖",因为这个函数的思路和指令的实现逻辑结合的实在是太完美无缺了,当然这只是我的个人臆想罢了。
【SMB源码解析系列】——001.JumpEngine函数的更多相关文章
- 【SMB源码解析系列】——003.SMB游戏基本框架
前面有了解到RESET中断相关代码,结尾处通过一句jmp进入了无限循环,之后CPU将会在每一帧PUU进入VBlank状态时,接收NMI中断信号, 跳转至NMI代码处继续执行,直到遇见RTI指令时又返回 ...
- 【SMB源码解析系列】——004.AreaParserTaskControl行列绘制控制程序
前提知识: 任天堂游戏系统的画面分辨率是256*240像素,基本的显示单位是tile,包含8x8=64个像素 根据电视机的制式不同,NTSC制式只显示256*224,也就是32x28个tile,画面的 ...
- 【SMB源码解析系列】——002.RESET中断
跟随代码结尾处的中断向量,我们可以看到RESET中断所在地址为Start标签处. 这部分代码比较简单,从字面便可基本理解. 1.(682~683)状态寄存器设置,sei指令用于禁用IRQ中断,SMB中 ...
- 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新
[原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...
- 【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新
上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方 ...
- 【安卓网络请求开源框架Volley源码解析系列】定制自己的Request请求及Volley框架源码剖析
通过前面的学习我们已经掌握了Volley的基本用法,没看过的建议大家先去阅读我的博文[安卓网络请求开源框架Volley源码解析系列]初识Volley及其基本用法.如StringRequest用来请求一 ...
- 【原】Android热更新开源项目Tinker源码解析系列之三:so热更新
本系列将从以下三个方面对Tinker进行源码解析: Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Android热更新开源项目Tinker源码解析系列之二:资源文件热更新 A ...
- Cwinux源码解析系列
Cwinux源码解析系列
- TiKV 源码解析系列文章(三)Prometheus(上)
本文为 TiKV 源码解析系列的第三篇,继续为大家介绍 TiKV 依赖的周边库 rust-prometheus,本篇主要介绍基础知识以及最基本的几个指标的内部工作机制,下篇会介绍一些高级功能的实现原理 ...
随机推荐
- pytorch seq2seq模型中加入teacher_forcing机制
在循环内加的teacher forcing机制,这种为目标确定的时候,可以这样加. 目标不确定,需要在循环外加. decoder.py 中的修改 """ 实现解码器 &q ...
- (第三篇)SSH网络协议概述
ssh简介原理 windows远程登录,QQ远程协助修电脑 简单说,SSH是一种网络协议,用于计算机之间的加密登录.最早的时候,互联网通信都是明文通信,一旦被截获,内容就暴露无疑.1995年,芬兰学者 ...
- [Qt] 打开Diskmgmt
QProcess mOpenDiskMgmt; QString program = "cmd"; QStringList arguments; arguments << ...
- 虚拟化KVM之安装(二)
安装KVM虚拟化 1.系统基础环境: [root@linux-node1 ~]# ip addr | grep inet | awk '{ print $2; }' | sed 's/\/.*$//' ...
- 理解分布式一致性:Paxos协议之Cheap Paxos & Fast Paxos
理解分布式一致性:Paxos协议之Cheap Paxos & Fast Paxos Cheap Paxos Message flow: Cheap Multi-Paxos Fast Paxos ...
- 【linux题目】第一关
详细的解答:https://github.com/Zoe233/Linux/blob/master/[题目]5.Linux了解程度测试题解析.ipynb 1. 创建一个目录/data 解答: mkdi ...
- TCP连接过程及报文解析
可能大家都听过TCP建立连接时需要经历三次握手和四次挥手的. 那么具体的握手挥手的过程是怎么样的呢? 这篇文章就通过WireShark抓包来了解TCP连接建立和断开的过程. 实验方法: 写一段简单的代 ...
- uniq 只能相邻行去重
uniq只可以将相邻行重复数据进行去重处理: [root@localhost /data/mysql/mysql3306]#last | cut -d ' ' -f 1 | tail -15 > ...
- 单源最短路径:Dijkstra算法(堆优化)
前言:趁着对Dijkstra还有点印象,赶快写一篇笔记. 注意:本文章面向已有Dijkstra算法基础的童鞋. 简介 单源最短路径,在我的理解里就是求从一个源点(起点)到其它点的最短路径的长度. 当然 ...
- muduo网络库源码学习————Timestamp.cc
今天开始学习陈硕先生的muduo网络库,moduo网络库得到很多好评,陈硕先生自己也说核心代码不超过5000行,所以我觉得有必要拿过来好好学习下,学习的时候在源码上面添加一些自己的注释,方便日后理解, ...