【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,本篇主要介绍基础知识以及最基本的几个指标的内部工作机制,下篇会介绍一些高级功能的实现原理 ...
随机推荐
- CentOS6.5环境下搭建Apache httpd服务器
前期准备: 1.CentOS6.5虚拟系统: 2.CentOS6.5 IP地址:192.168.2.99 3.虚拟系统能上外网 下面我们就开始配置: 第一步:安装 首先我们需要把Apache http ...
- Pycharm 操作数据库
view--->Tool Buttons,点击Pycharm右侧的Database 1.连接数据库 2.建立一个表,添加数据 通过以上操作把用户名和密码储存到了数据库中 3.连 ...
- windows下部署.netcore+docker系列四 (部署程序,重点就要来了)
前面的都是为这章做准备,加油把骚年们 PS:C# 项目可以按照流程一步步来,java 偶然其他的可以找下其他的网上资源 1.在 VS2019中 添加docker 支持 (其实也就是追加一个Docker ...
- 8、Flink Table API & Flink Sql API
一.概述 上图是flink的分层模型,Table API 和 SQL 处于最顶端,是 Flink 提供的高级 API 操作.Flink SQL 是 Flink 实时计算为简化计算模型,降低用户使用实时 ...
- xpath进阶用法
一.简介 xpath作为对网页.对xml文件进行定位的工具,速度快,语法简洁明了,在网络爬虫解析内容的过程中起到很大的作用,除了xpath的基础用法之外xpath中还存在着非常之多的进阶用法,本文将对 ...
- php正则匹配到字符串里面的a标签
$cont = preg_replace('/<a href=\"(.*?)\".*?>(.*?)<\/a>/i','',$cont);
- str_pad 和 filter_var
这两个函数都是php内置函数,filter_var可直接过滤,比如邮箱,ip等,str_pad可补充字符串eg: 1 => 001
- Visual Studio 添加图标和版本
在Visual Studio中,如果你创建的是纯C语言的工程,那么给可执行程序添加图标就没有便捷的入口. 但也只是入口不好找了,添加步骤还是比较简单的,以下为具体操作方法: 1. 右键点击C工 ...
- 修改CENTOS7的网卡ens33修改为eth0
1.先编辑网卡的配置文件将里面的NAME DEVICE项修改为eth0 vim /etc/sysconfig/network-scripts/ifcfg-ens33 2.[root@linux-nod ...
- Scala教程之:可扩展的scala
文章目录 隐式类 限制条件 字符串插值 s 字符串插值器 f 插值器 raw 插值器 自定义插值器 Scala是扩展的,Scala提供了一种独特的语言机制来实现这种功能: 隐式类: 允许给已有的类型添 ...