QL6502: CPU 6502 汇编语言和静态分析工具

您所在的位置:网站首页 电脑汇编语言 QL6502: CPU 6502 汇编语言和静态分析工具

QL6502: CPU 6502 汇编语言和静态分析工具

2024-07-13 22:36| 来源: 网络整理| 查看: 265

QL6502 6502 处理器汇编语言和静态分析工具 项目简介

QL6502 是为 MOS 6502 开发的汇编器和静态分析工具,其前身是作者于 1990 年代开发的 CAXD6502 工具。

MOS 6502 是 MOS 科技公司于 1975 年开发的 8 位微处理器,问世之初就成为市场上性能最强的 8 位CPU,而价格却只有大型芯片公司如 Motorola、Intel 同类产品的六分之一,激起了一系列的的电脑创新项目,并在上世纪八十年代带来了一场个人电脑的革命。 MOS 科技最初授权洛克威尔国际公司(Rockwell International) 和 Synertek 公司为芯片的“第二供货源”, 所以,我们也曾听到如 R6502 的称谓。

CAXD6502 共生于 1990 年代中国大陆兴起的 6502 游戏机市场,它为开发者提供了二进制 ROM 文件的静态分析、反汇编和汇编语言程序开发及程序补丁支持。CAXD6502 从 Intel 80286 的 MS-DOS 下使用 TurboC 2.0 开始开发,中间于 2004 年移植到 GCC 编译环境下。

最新修订和改写的 QL6502 是对早期开发过程的总结和纪念,也作为 FPGA CPU 验证和测试代码的简易开发工具。

功能特性

QL6502 实现 MOS6502 CPU 的汇编和反汇编功能。

通常对一个已有的游戏程序(固件)进行再次开发和功能扩展,首先需要理解原有程序的功能。在没有源代码的情况下,反汇编就成为唯一可行的方式。早期的 8 位处理器其代码功能简单,源程序本身也是使用汇编语言编写的,反汇编分析方法相对有效。当然,随着处理器越来越强大、固件功能越来越复杂,现代的固件都使用 C 语言等高级语言编写,其算法实现时的思维方式也已经脱离了汇编和机器语言,而代码经过编译器优化后更是面目全非,反汇编基本上没有可能,所以现代通常的方法是“正向开发”。

一个机器代码的映像文件至少包含代码和数据,反汇编的作用就是把二进制代码转换为汇编助记符。 但是简单地一对一翻译并不能满足我们分析的要求,因为把数据翻译成无效的助记符,或者把指令的半字设置为跳转入口,都只会得到“垃圾代码”,在九十年代简单文本编辑器的时代,这种过错就意味着多次无意义的清单打印。

QL6502通过指令的模拟执行来识别整个处理器映像的代码和数据区域。 QL6502 首先利用处理器已知的入口(RESET, NMI, IRQ)开始程序指令分析,流过顺序指令流,标识识别的子程序调用和跳转指令及其目标地址和其它的代码入口。通过反复扫描指令,自动识别全部的代码,这个过程可以理解为“虚拟执行”,而最终没有被虚拟执行到的代码部分就全部作为数据输出。

QL6502 通过人工干预的方式对间接转移指令进行处理。

对机器代码分析理解之后,就可以编写汇编代码来实现自己所需要的功能了(扩展开发),这时我们需要的工具就是汇编工具。与通常的汇编工具不同,扩展开发除了把汇编助记符转换成机器指令外,还需要实现一些特别的功能来满足我们的要求。比如:

汇编能够在原来二进制映像的基础上生成代码 可以修改原来的汇编指令,比如跳转到我们扩展程序的入口等 能够在原来映像的“缝隙”或者明确的原来代码未使用的“空白”区域中加入我们的代码 简单的结构化、模块化编程技术

QL6502 与传统的汇编器一样,通过两遍扫描对源文件进行处理。 支持的伪操作包括 ORG、EQU、DB、DW,可以进行 +,- 等数值运算。传统的标号使用如 LABEL: 一类的名字表示,对于组成一个项目的多个源文件之间,用 LABEL::(两个冒号)定义,这种标号可以在整个项目范围内引用。在 CAXD6502 设计之初,我们实现了复杂的表达式计算堆栈以支持在汇编时的常量表达式计算,不过负责任地说,在近十年的开发时间里,我们没有一次遇到那些“数学正确”的表达式计算,所以这一次,我们把这些功能全部删除了。

QL6502 实现 CODE 伪指令。用

CODE start end

来定义一片可放置用户扩展代码的区域(已经分析确认此区域为空白、无效数据区等),后续的代码在这个区域内顺序放置。在一个项目的后续源文件中,只需要使用一个无参数的 CODE 伪指令,就可以继续代码汇编。 如果汇编的代码超出所定义的区域,则产生汇编错误报告并停止汇编。

编译和部署

QL6502 项目使用 CMAKE 工具链构建。 首先,克隆整个项目到 QL6502 文件夹,接着执行以下命令

> cd QL6502 > mkdir build > cd build > cmake -G Ninja .. > cmake --build . -j10

同时,我们还在 example 文件夹中发布了一个最新版本的 ql6502.exe Windows 可执行文件,它可结合以下示例直接使用。

使用 静态分析和反汇编 > QL6502.exe -X QL6502 V1.0 An Assembly Development Tool for 6502 [email protected], 2017.07 - 2024.07, ALL RIGHTS RESERVED This Program is based on CA6502 V3.0, ZhaoYu, ZhangWenCui, 1993.05 - 2004.09 QL6502>

可在提示之后输入命令,命令为单字母,大小写无关,可以用 ? 得到帮助。

接着我们装入一个映像文件 ldt512.bin:

QL6502> ldt512.bin 65536 Bytes data read into code buffer @0x0000

6502 的全部寻址空间是64K字节,但是在实际的系统中,它当然不可能全部都是代码,还有许多存储器空间用于I/O 地址映射。 我们把代码之外的区域称为“无效区域”。在分析之前,我们需要标识出这些区域。这应该是一个很复杂的过程,可能需要对硬件电路、固件代码反复分析才能确定:

QL6502> b 0x0000 0x3fff QL6502> b 0x8000 0xbfff QL6502> b 000000 -- 003FFF : Not Used 004000 -- 007FFF : Used 008000 -- 00BFFF : Not Used 00C000 -- 010000 : Used QL6502>

我们使用 X 命令进行静态分析

QL6502> x 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1 Indirect Entries

QL6502 报告遇到了一个间接跳转指令,我们使用 i 命令查看

QL6502> i (001) L_D425: JMP (0x0030)

于是我们查看这个指令相关的代码,u 命令是反汇编,由于我们不知道这段代码从哪儿开始,只能给一个“猜测”的开始地址,它一定在上面提示的前方位置,可以以字节为单位多试几次。

QL6502> u 0xd410 L_D41A BD 7B D9 LDA L_D97B,X L_D41D 85 30 STA 0x30 L_D41F E8 INX L_D420 BD 7B D9 LDA L_D97B,X L_D423 85 31 STA 0x31 L_D425 6C 30 00 JMP (0x0030) L_D428 A5 57 LDA 0x57 L_D42A 29 10 AND #0x10 L_D42C F0 0F BEQ L_D43D L_D42E AD 4A 08 LDA L_084A

这显示了从地址 L_D97B 开始是一个跳转表,我们可以查看表的内容

QL6502> d 0xd97b Scale - 0 1 2 3 4 5 6 7 - 8 9 a b c d e f 0123456789ABCDEF 00D97B: B7 D9 69 DA 3E ..i.> 00D980: D3 85 DC E4 DC 5D DD DE - DD FC DD 58 DE 8A DE 09 .....].....X.... 00D990: DF 61 DF DF DF 04 E0 60 - E0 B7 E0 30 FF 25 E2 35 .a.....`...0.%.5 00D9A0: E2 90 E2 EB 4E A0 65 51 - E3 84 E4 E5 E4 0E E5 2D ....N.eQ.......- 00D9B0: E5 77 E5 2D E7 A6 E7 20 - 71 C5 20 65 D7 20 28 D4 .w.-... q. e. (. 00D9C0: 20 A3 C5 20 E8 D2 20 7C - 79 20 72 59 20 90 5A A5 .. .. |y rY .Z. 00D9D0: 75 29 80 09 11 85 75 A9 - 00 85 C7 85 70 85 73 85 u)....u.....p.s. 00D9E0: 76 8D BF 03 A2 0C 20 20 - CC A2 00 20 20 CC 20 D4 v..... ... . .

我们经过分析可知 0xd97b ~ 0xd9b6 的内容是跳转指令表,于是我们用 j 命令 (Jump Table) 命令告诉 QL6502 这个跳转表

QL6502> j 0xd97b 0xd9b6

接着再分析

QL6502> x 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Ok.

这次没有遇到间接跳转指令,说明整个程序静态分析完成,我们可以生成反汇编代码文件

QL6502> g dt512.asm 0 0x0xffff

注意其中的无效区域已经被 B 命令标识出来了。我们生成的文件局部看是这样

L_4D1B: DB 0x20,0x21,0xF0,0xA6,0x9C,0xB5,0x80,0x29 ; .!.....) L_4D23: DB 0x0F,0xC9,0x07,0xA9,0x31,0x8D,0x66,0x10 ; ....1.f. L_4D2B: DB 0xA9,0x01,0x85,0xA1,0x60 ; ....` L_4D30: JSR L_D7A7 ;Subrutine .......... L_4D33 LDA 0xA1 L_4D35 BNE L_4D3C L_4D37 LDA #0x49 ; I L_4D39 JSR L_F4A3 L_4D3C: RTS L_4D3D: JSR L_D8DF ;Subrutine .......... L_4D40 LDA L_2000 L_4D43 AND #0x80 L_4D45 BNE L_4D61 L_4D47 LDA L_0731 L_4D4A CMP #0x02 L_4D4C BEQ L_4D62 L_4D4E BCS L_4D6D L_4D50 CLC L_4D51 LDA L_0730 L_4D54 ADC #0x01 L_4D56 STA L_0730 L_4D59 LDA L_0731 L_4D5C ADC #0x00 L_4D5E STA L_0731 L_4D61: RTS

数据用 DB 标识,子程序入口使用 ;Subrutine 说明,跳转的入口使用 L_4D3C:( 一个冒号)标记,一般的指令地址如 L_4D51 (没有冒号)表示后面的指令位于 CPU 地址 0x4D51 处。

汇编工具

Ql6502 可以对单个源文件进行汇编,而对于有多个源文件组成的项目来说,最方便的方法是定义一个项目管理文件,比如这个 ABC.MAK 文件

-OOUT512.bin -LIN512.bin A.ASM B.ASM C.ASM D.ASM X.ASM

其中每个文本行对应一个描述项目, -OOUT512.bin 为输出 ROM 映像文件名称, -LIN512.bin 输入映像文件名称。 而带有扩展名.ASM 的文件为我们编写的小汇编源文件,一个项目中包含的全部源文件需要逐一列出。 我们使用以下命令可以自动完成整个项目的汇编操作:

QL6502 ABC.MAK

QL6502 将读入二进制文件 IN512.bin, 逐个汇编源文件,形成输出文件 OUT512.bin。下面是一个实际工作的例子

Load file : IN512.bin Write File : OUT512.bin Total 2404 Lines in 13 Files Built. 目标硬件平台

QL6502 不涉及特定的目标硬件平台(目标单板)。 在实际的工作中,我们通常使用 EEPROM 编程器读取 ROM 映像,汇编之后的代码生成目标映像后,再使用 EEPROM 编程器写入各种存储器如 27C64,7527C256,27C512 等。 由于不同设计者使用的地址映射方案不同,在烧录之前可能需要做不同的程序文件切割和打包处理。在 QL6502 项目中,我们包含了一个实际使用的处理程序,如果只关注学习 6502 人汇编/反汇编器的实现方法,可忽略这些内容。

说明

QL 是秦岭(汉语拼音 QinLing)的缩写。 秦岭是长江流域与黄河流域的一个分水岭,生长着一些世界独有的野生动植物。

协议

QL6502 遵循 MIT 开源协议。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3