机器指令翻译成 JavaScript —— No.5 指令变化
上一篇,我们通过内置解释器的方案,解决任意跳转的问题。同时,也提到另一个问题:如果指令发生变化,又该如何应对。
指令自改
如果指令加载到 RAM 中,那就和普通数据一样,也是可以随意修改的。然而,对应的 JS 是事先翻译好的,已经不能改了。如果运行时突然变卦,那相应的 JS 就作废了 —— 如果修改的是跳转指令,甚至会影响已划分的流程。所以为了保守起见,指令被改后进入模拟状态。
因此,我们得监控指令区的修改:
function store(addr, val) {
// 修改指令区
if (0x0600 <= addr && addr <= ...) {
...
}
MEM[addr] = val
}
将存储操作封装成函数,这样就可在写入时做一些判断。如果修改了指令区的数据,则进入解释模式(甚至永远保持解释模式)。
当然,还可以做一个 JIT 引擎,在运行时翻译。不过很复杂,这里就不考虑了。
对存储进行封装,这也是有必要的。之前为了简化问题,将整个地址空间都当做内存,其实是不严谨的。事实上,内存只是地址空间的一部分而已。其他还有屏幕、键盘,以及各种 ABI,都是通过地址交互的。
所以,读写最终都需要一层封装:
function store(addr, val) {
...
MEM[addr] = val;
}
function load(addr) {
...
return MEM[addr];
}
指令变化
如果不修改指令数据,指令是否也会变化?听起来有些匪夷所思。不过,在那个系统资源极度匮乏的年代,总会有些神奇的东西。
我们在第一篇中提到,地址总线是 16 位,最多只能访问 64K 的空间。这是否意味着,程序最大只能做到 64K?
回顾一下,小时候玩的红白机游戏(当然,那时都用卡带,也看不出游戏有多大)。后来有电脑模拟器,就可以看到 NES 文件的大小了。
事实上超过 64K 的多得是,有些「大型游戏」甚至有好几百 K,例如:
光靠 16 位的地址,是如何访问的?为此,前辈们发明了一种叫 Mapper 的黑科技。它内置在游戏卡带芯片里,对 CPU 是透明的。
Mapper 的种类五花八门,但基本思路差不多:用某些特殊地址,来扩展寻址能力。
假设 0x0000 ~ 0x0fff 空间是给卡带的。若把 0x0fff 这个特殊地址设置成 1,这时访问 0x0005,实际访问到的物理位置是 1 * N + 5;如果设置的是 2,再访问 0x0005,对应的物理位置则是 2 * N + 5。这样,就可突破 64K 的限制了。
相当于把特殊地址,当做类似段寄存器的功能。只不过这是卡带自己搞的一套内部方案,CPU 是毫不知情的。
当然,实际情况比这复杂得多。本系列我们讨论的仅仅是指令翻译,并非要实现一个 NES 环境,所以就不考虑了。
结尾
关于 6502 指令翻译成 JavaScript 的可行性分析,就到此为止。
我们之所以要翻译,而不是纯粹模拟,就是为了尝试追求最高效率。不过,就目前的翻译过程来看,仍存在很多可优化的地方。
下一篇,我们尝试利用现有工具,对逻辑进行深度优化。
机器指令翻译成 JavaScript —— No.5 指令变化的更多相关文章
- 【探索】机器指令翻译成 JavaScript
前言 前些时候研究脚本混淆时,打算先学一些「程序流程」相关的概念.为了不因太枯燥而放弃,决定想一个有趣的案例,可以边探索边学. 于是想了一个话题:尝试将机器指令 1:1 翻译 成 JavaScript ...
- 机器指令翻译成 JavaScript —— No.6 深度优化
第一篇 中我们曾提到,JavaScript 最终还得经过浏览器来解析.因此可以把一些优化工作,交给脚本引擎来完成. 现代浏览器的优化能力确实很强,但是,运行时的优化终归是有限的.如果能在事先实现,则可 ...
- 机器指令翻译成 JavaScript —— No.7 过渡语言
上一篇,我们决定使用 LLVM 来优化程序,并打算用 C 作为输入语言.现在我们来研究一下,将 6502 指令转换成 C 的可行性. 跳转支持 翻译成 C 语言,可比 JS 容易多了.因为 C 支持 ...
- 机器指令翻译成 JavaScript —— 终极目标
上一篇,我们顺利将 6502 指令翻译成 C 代码,并演示了一个案例. 现在,我们来完成最后的目标 -- 转换成 JavaScript. 中间码输出 我们之所以选择 C,就是为了使用 LLVM.现在来 ...
- 机器指令翻译成 JavaScript —— No.2 跳转处理
上一篇,我们发现大多数 6502 指令都可以直接 1:1 翻译成 JS 代码,但除了「跳转指令」. 跳转指令,分无条件跳转.条件跳转.从另一个角度,也可分: 静态跳转:目标地址已知 动态跳转:目标地址 ...
- 机器指令翻译成 JavaScript —— No.3 流程分割
上一篇 我们讨论了跳转指令,并实现「正跳转」的翻译,但最终困在「负跳转」上.而且,由于线程模型的差异,我们不能 1:1 的翻译,必须对流程进行一些改造. 当初之所以选择翻译,而不是模拟,就是出于性能考 ...
- 机器指令翻译成 JavaScript —— No.4 动态跳转
上一篇,我们用模拟流程的方式,解决了跳转问题. 不过静态跳转,好歹事先是知道来龙去脉的.而动态跳转,只有运行时才知道要去哪.既然流程都是未知的,翻译从何谈起? 动态跳转,平时出现的多吗?非常多!除了 ...
- 四十年前的 6502 CPU 指令翻译成 JS 代码会是怎样
去年折腾的一个东西,之前 blog 里也写过,不过那时边琢磨边写,所以比较杂乱,现在简单完整地讲解一下. 前言 当时看到一本虚拟机相关的书,正好又在想 JS 混淆相关的事,无意中冒出个问题:能不能把某 ...
- [书籍翻译] 《JavaScript并发编程》第一章 JavaScript并发简介
> 本文是我翻译<JavaScript Concurrency>书籍的第一章,该书主要以Promises.Generator.Web workers等技术来讲解JavaScript并 ...
随机推荐
- 在 ML2 中配置 OVS flat network - 每天5分钟玩转 OpenStack(133)
前面讨论了 OVS local network,今天开始学习 flat network. flat network 是不带 tag 的网络,宿主机的物理网卡通过网桥与 flat network 连接, ...
- NuGet镜像上线试运行
为解决国内访问NuGet服务器速度不稳定的问题,我们用阿里云服务器搭建了一个NuGet镜像,目前已上线试运行. 使用NuGet镜像源的方法如下: 1)NuGet镜像源地址:https://nuget. ...
- .NET 提升教育 第一期:VIP 付费课程培训通知!
为响应 @当年在远方 同学的建议,在年前尝试进行一次付费的VIP培训. 培训的课件:点击下载培训周期:10个课程左右,每晚1个半小时培训价格:1000元/人.报名方式:有意向的请加QQ群:路过秋天.N ...
- 使用C#处理基于比特流的数据
使用C#处理基于比特流的数据 0x00 起因 最近需要处理一些基于比特流的数据,计算机处理数据一般都是以byte(8bit)为单位的,使用BinaryReader读取的数据也是如此,即使读取bool型 ...
- CentOS 7配置LNMP开发环境及配置文件管理
安装并配置MySQL 5.6 从CentOS从7.x开始默认使用MariaDB.MariaDB完全兼容MySQL,包括API和命令行.但是很多时候我们还是会想要安装MySQL,所以不能直接通过yum命 ...
- CoreCRM 开发实录——Travis-CI 实现 .NET Core 程度在 macOS 上的构建和测试 [无水干货]
上一篇文章我提到:为了使用"国货",我把 Linux 上的构建和测试委托给了 DaoCloud,而 Travis-CI 不能放着不用啊.还好,这货支持 macOS 系统.所以就把 ...
- Oracle碎碎念~1
1. 设置SQL*Plus提示符 SQL> set sqlprompt "_user'@'_connect_identifier>" SYS@orcl> 为了对所 ...
- PHP 获取 特定时间范围 类
目录 前序 用途 功能及事项 使用方法 代码及注释 前序: 总体来说,我更应该是一个 android 移动开发者,而不是一个 phper,如果说只做移动端的 APP ,我也不会学这么多,这 2年来, ...
- HTML+CSS 项目总结
在过去的大概一个月的学习,基本掌握了HTML+CSS的用法和特性. 这个星期老师给我们布置了一个PC端的实战项目,并且要求在3-4天内完成,我不惜废寝忘食,在紧迫的时间内大致地完成了,但是有些效果不能 ...
- 6_Win7下Chrome主页被流氓网站hao123.com劫持后的解决方法。
今天安装了一个PDF阅读器,免费的,你懂的,结果自己安装的时候没有将默认的选项取消,就被hao123流氓网站劫持啦. 说实话某免费PDF阅读器还算好的,有一个可以供你选择的项.不想某些软件直接就默认选 ...