2个版本

0.1.1 2019年12月21日
0.1.0 2019年12月21日

#102 in 模拟器

GPL-3.0+

130KB
2K SLoC

ch8asm

开源的Chip-8汇编器

概述

ch8asm,发音类似于单词"chasm",是一个简单易用且易于学习的Chip-8复古视频游戏平台的汇编器。它使用简单的语法,只需一两天就能轻松掌握。

安装

在终端中输入以下命令来安装 ch8asm

cargo install ch8asm

用法

要使用 ch8asm,请在终端中键入 ch8asm <源文件>,将 <源文件> 替换为您的Chip-8源代码文件的路径。假设没有出错(错误将在下面描述),您将看到一条消息说您的文件已正确汇编。然后,您可以使用您选择的模拟器运行生成的二进制文件。如果您还没有Chip-8模拟器,您可以使用我的模拟器Cookie,可以在这里找到。

出了点问题...

当您尝试汇编游戏时,如果没有看到消息 Successfully assembled <source file> into <binary file>,则 ch8asm 将显示一条错误消息,说明汇编二进制文件时出错的原因。以下是一些可能的错误消息及其最可能的解决方案

"无法获取标签 XXXX 的地址"

这条消息表示您试图在不定义标签(例如 XXXX)的情况下使用它。请确保在标签定义后加上冒号。

"XXXX 指令的参数错误"

这条消息表示您在一个不支持该寄存器(通常是 I 寄存器)的指令中使用了错误的寄存器。请确保您使用正确的指令参数,如下所述。

"未知字符 X"

这条消息表示您在源代码中意外地放入了 ch8asm 不认识的字符。转到错误消息中提到的行号,查找任何多余的字符。

"未知指令 XXXX"

这条消息表示您不小心拼错了指令或试图发明一个新的指令。转到错误消息中提到的行号,检查您的代码是否有正确的拼写。

"预期 XXXX,发现 XXXX"

此消息表示您的代码中存在位置不正确的符号。转到错误消息中提到的行号,并根据错误消息更正您的代码。

"跳转类型错误 XXXX"

此消息表示您不小心拼写了一个用于 SKIP 指令的条件。检查有效条件的表,并更正您的代码以使用有效的条件。

"二进制数太大"

这仅仅意味着您的游戏比Chip-8芯片上的可用内存大。遗憾的是,唯一的方法是重写您的游戏以生成更小的二进制文件。有关此方法的说明超出了本文档的范围,可能在网上找到。

处理器信息

Chip-8处理器有十六个通用寄存器,编号从 V0VF。每个寄存器可以存储一个字节,可以随意操作。然而,寄存器 VF 被多个指令用作标志寄存器,并且只能用于该目的。

Chip-8还有一个名为 I 的“索引”寄存器。其主要用途是用于数据存储和精灵绘图操作时的内存寻址。它可以存储从0到4095的值。

Chip-8还有4096(0x1000)字节内存。其中,地址0x050到0x0A0保留用于内置字符集,二进制文件从地址0x200开始加载到内存中。所有其他地址都可以供您的游戏使用。

Chip-8还有两个内置定时器,称为 延迟定时器声音定时器。两者都可以通过代码设置,并在设置为非零值时以60Hz的频率计数到0。延迟定时器可以读取,而声音定时器则不能。当声音定时器不为零时,将播放声音。

数据类型

ch8asm 的汇编语言有四种主要数据类型。它们是

  • 十进制文字(以 # 符号开头)
  • 十六进制文字(以 $ 符号开头)
  • 二进制文字(以 % 符号开头)
  • 标签(以 _ 符号开头)

十进制和十六进制文字可以是0到4095之间的任何值,而二进制文字只能是一个字节长。二进制文字的一个用途是使用它们来绘制精灵。将二进制文字排列成1s代表所需的像素,附加到标签定义中,然后您可以在代码的其他部分使用该标签来表示您的精灵。

标签有两种类型: 定义引用。定义向 ch8asm 提供了游戏代码中某个位置的名字,而引用允许定义在代码中使用以引用该位置。定义总是后跟冒号,而引用则从不跟冒号。

以下示例代码片段在屏幕左上角绘制一个笑脸

;this is a definition
_spr:
	%00000000
	%01000010
	%00000000
	%01000010
	%00100100
	%00011000

mov I, _spr ;this is a reference
mov V0, #0
mov V1, #0
draw V0, V1, #6

作为旁注,您可以使用分号来注释代码。注释从分号开始,直到行尾。

指令

以下是ch8asm支持的指令列表。所有指令和寄存器均不区分大小写,参数之间必须用逗号分隔。在本文档中,通用寄存器用VXVY表示,索引寄存器用I表示,常量值用NNNNN表示,具体取决于常量的大小,标签用_lbl表示,其中lbl是标签的实际名称。

绘图指令

  • CLS - 清除屏幕。
  • DRAW VX, VY, H - 在坐标(VX, VY)处绘制高度为H像素的精灵。精灵从内存位置开始读取,该位置由I指向。为了便于碰撞检测,如果任何像素从开启变为关闭,则将VF设置为1,否则设置为0。
    起始地址为I指向的位置。为了便于碰撞检测,如果任何像素从开启变为关闭,则将VF设置为1,否则设置为0。
  • SCH VX - 将I设置为指向与VX值对应的十六进制字符,其中VX必须在0到15的范围内(包含0和15)。

控制指令

  • JMP _lbl - 无条件地将程序流程跳转到_lbl
  • CALL _lbl - 在_lbl处调用子程序。
  • RET - 从子程序返回到调用代码
  • SKIP.condition args - 如果conditionargs为真,则跳过下一个指令。有关有效condition的列表,请参阅下表。
  • JPC (_lblNNN) - 无条件地跳转到参数加上V0

跳转条件

条件 参数 真值条件
EQ VXVYNN 参数相等
NE VXVYNN 参数不相等
KD VX 按键VX被按下
KU VX 按键VX未被按下

操作指令

  • MOV dest, src - 将src的值存储在dest中。如果dest指的是I寄存器,则src必须是一个常量或一个标签。src不能是I寄存器。
  • ADD dest, (VXNN) - 将第二个参数加到第一个参数上,并将结果存储在第一个参数中。如果第二个参数是常量,则dest不能是I寄存器。此外,如果加法时发生溢出,则将寄存器VF设置为1。如果没有发生溢出,则将VF设置为0。
  • OR VX, VY - 将VX设置为自身与VY按位或。
  • AND VX, VY - 将VX设置为自身与VY按位与。
  • XOR VX, VY - 将VX设置为自身与VY按位异或。
  • SUB VX, VY - 将VX设置为VX减去VY。如果发生借位,则将VF设置为0,否则设置为1。
  • SUBN VX, VY - 将VX设置为VY减去VX。如果发生借位,则将VF设置为0,否则设置为1。
  • SHR VX - 将VX的最低有效位存储在VF中,并将VX按位右移1。
  • SHL VX - 将VX的最高有效位存储在VF中,并将VX按位左移1。

其他指令

  • RAND VX, NN - 将与NN按位与的随机字节存储在VX中。
  • GDL VX - 将延迟定时器的当前值存储在VX中。
  • KEY VX - 停止执行,直到按键被按下,并将其存储在VX中。
  • SDL VX - 将延迟定时器设置为VX
  • 设置声音定时器为 VX
  • BCD VX - 将 VX 的二进制编码十进制表示存储在从地址 I 开始的内存中。
  • RDP VX - 将寄存器 V0VX 的值存储在从地址 I 开始的内存中。
  • RLD VX - 从从地址 I 开始的内存读取数据到寄存器 V0VX

进一步阅读

您可能希望阅读有关 Chip-8 的 维基百科页面 以获取有关处理器及其功能的更多信息。

许可协议

ch8asm 使用 GNU 通用公共许可证,版本 3。

结束语

我们始终欢迎反馈和建议,因此如果您有任何想法,请直接在 GitHub 上发起拉取请求或提交问题。感谢使用 ch8asm,祝您编程愉快!

依赖项

~225KB