【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,本篇主要介绍基础知识以及最基本的几个指标的内部工作机制,下篇会介绍一些高级功能的实现原理 ...
随机推荐
- Scala教程之:Option-Some-None
文章目录 Option和Some Option和None Option和模式匹配 在java 8中,为了避免NullPointerException,引入了Option,在Scala中也有同样的用法. ...
- tcpdump常用抓包命令
主要语法 过滤主机/IP: tcpdump -i eth1 host 172.16.7.206 抓取所有经过网卡1,目的IP为172.16.7.206的网络数据 过滤端口: tcpdump -i ...
- C# 基础知识系列- 14 IO篇 文件的操作
0. 前言 本章节是IO篇的第二集,我们在上一篇中介绍了C#中IO的基本概念和一些基本方法,接下来我们介绍一下操作文件的方法.在编程的世界中,操作文件是一个很重要的技能. 1. 文件.目录和路径 在开 ...
- openlayers3中Overlay用法
Overlay 从名字看,是覆盖图.覆盖物的意思,主要的用途就是在地图之上再覆盖一层,用以显示额外的可见元素,可见元素一般是 HTML 元素,利用 overlay,可以将可见元素放置到地图的任意位置, ...
- 获取系统DPI、系统显示比例等
using System; using System.Drawing; using System.Runtime.InteropServices; namespace XYDES { public c ...
- Mark一篇介绍Java垃圾回收和JVM参数设置的文章
贴出原文连接:重磅!Java 内存管理白皮书,读完它,java 内存管理的问题完全 NO Problem! 读了一遍,对并行的垃圾回收还不是很理解,先mark,消化消化再学习. 文章说的一些JVM设置 ...
- js特效:鼠标滑过图片时切换为动图
效果展示 事前准备 一张普通的静态图+与其对应的gif图. 实现思路 获取图片的src,改变其后缀,使其变成与之对应的gif图片.(很简单有木有= =) 具体实现 编写html代码 <div c ...
- python(文件操作)
一.文件操作 1.tell()方法返回文件的当前位置,即文件指针当前位置. UTF-8 编码格式,一个中文占3个字符 GBK 编码格式,一个中文占2个字符 #写入前文件内容如下 "" ...
- python(索引/切片)
一.索引 1.索引值从左到右-->从0开始,索引值从右到左-->从-1开始 取值格式var[index] >>> name = "xinfangshuo&quo ...
- 自定义Element父子不关联的穿梭树
Element自身是有一个Transfer穿梭框组件的,这个组件是穿梭框结合checkbox复选框来实现的,功能比较单一,自己想实现这个功能也是很简单的,只是在项目开发中,项目排期紧,没有闲功夫来实现 ...