# nesasm_3_2_vs **Repository Path**: flame_cyclone/nesasm_3_2_vs ## Basic Information - **Project Name**: nesasm_3_2_vs - **Description**: 基于nesasm汇编工具, 完善功能 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-08-07 - **Last Updated**: 2025-12-27 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 更新说明 ## 介绍 此仓库基于 [nesasm](http://www.nespowerpak.com/nesasm) 进行功能上的完善与更新. | 功能 | 描述 | | ------------------------------------------------------------ | ------------------------------------------------------------ | | 相对路径逻辑修改 | 使用include incbin等命令时相对路径基于使用命令的文件, 不再是基于程序当前工作目录 | | 绝对寻址优化 | 增加绝对寻址可转变为零页寻址时使用零页寻址(不用显示指定零页寻址) | | 增加STR指令 | STR指令增加长度限制(可选范围0-255) | | 增加FILL指令 | 添加指定填充指定字节和长度 | | 标签长度优化 | 标签长度从32扩展到256 | | 命令行增加 -fill | 指定填充内存 | | 命令行增加 -fns | 指定生成fns函数地址列表文件(原来默认生成且不能控制) | | 命令行增加 -out | 指定输出文件名 | | 命令行增加 -bank 指定全局bank大小 | | | 预处理指令增加 .HEX | 用于指定十六进制编写的字节数据 | | 预处理指令增加 .RDW | 用于指定大头序双字节数据 | | 预处理指令增加 .BASE | 用于指定编译结果放置位置 | | 预处理指令增加 .CHAR_MAP | 用于将字符串宏的字符映射为另一个字符 | | 预处理指令增加
.BANK8
.BANK16
.BANK32 | 用于灵活指定当前Bank块大小 | | 支持中文标签 | | | 兼容65s指令语法 | 兼容65s
() 间接寻址
<取低位
>取高位 | | 文件头增加 电池备份指令 | INESBAT | | 文件头增加 INES2.0 支持 | INESTIM
INESSUBMAP
INESPRGRAM
INESPRGNVRAM
INESCHRRAM
INESCHRNVRAM
| | | | # NESASM v3.2 使用手册 ## 命令行用法 nesasm_3_2.exe [-选项] [-? (帮助)] 输入文件, 例如 ```bat nesasm_3_2.exe demo.asm nesasm_3_2.exe demo.asm -out demo.nes ``` 汇编程序只接受一个输入文件 “输入文件”,该文件将是组装成ROM文件(.NES扩展)可由模拟器直接使用。 还可以生成列表文件 (.LST 扩展名)如果在输入文件中遇到 LIST 指令。 以下是不同选项的说明: | 选项 | 说明 | | ----- | ------------------------------------------------------------ | | -s | 显示区段使用情况。
如果指定了其中一个选项,汇编程序将显示有关 ROM 库使用情况的信息。
使用 “-s” 显示基本信息,“-s” 显示更详细的信息 | | -l # | 控制列表文件的输出:
0 - 完全禁用列表文件,即使LIST 指令用于输入文件
1 - 最低水平;DB、DW 和 DEFCHR 生成的代码不会被倾倒
2 - 正常水平;只有 DEFCHR 生成的代码不会被倾倒
3 - 最大水平;所有代码都转储在列表文件中
默认级别为 2 级. | | -m | 在列表文件中强制展开宏,即使在输入文件中看不到 MLIST 指令. | | -raw | 不会生成 ROM 标头 | | -bank | 指定编译时全局bank大小等级
0: 8KB
1: 16KB
2: 32KB
默认为0级 | | -fill | 内存填充 (00-FF) | | -out | 指定输出文件名 | | -fns | 输出函数地址列表文件 | | | | ## 包含路径 默认情况下,汇编程序在以下情况下查看当前目录加载包含文件,但当它找不到该文件时, 然后使用环境变量“NES_INCLUDE”获取列表包含路径。理想情况下,您需要将此变量设置为您的 'AUTOEXEC.BAT“文件,并让它指向”NES”MagicKit 的目录。 例如:set NES_INCLUDE=c:\magickit\nes ## 符号 支持两种类型的符号:全局符号和局部符号。局部符号前面有一个点“.”,并且仅在两个全局符号之间有效。符号后面可以跟冒号“:”,但这不是必需的。 ## 表达式 汇编程序支持非常复杂的表达式。您可以根据需要使用任意数量的括号级别,并且可以在运算符和数字之间使用空格。 数字可以用三个基数写成:十六进制($7F)、二进制(x0101)和十进制(48)。还支持('A')字符值。 所有常用的运算符都存在: ``` +, -, *, /, %, ^, &, |, ~, <<, >> ``` 以及比较运算符: ``` =, !=, !, <, >, <=, >= ``` 对于优先级,适用与 C 相同的规则。 您还可以在表达式中使用预定义或用户定义的函数。 | 预定义函数 | 描述 | | ---------- | ------------------------------------------------------------ | | HIGH() | 返回值的高字节。 | | LOW() | 返回值的低字节。 | | BANK() | 返回符号的bank索引。如果没有给出符号,或者给出了多个符号,函数将返回错误。 | | PAGE() | 返回标签的页面索引。请参见上方的错误。 | | SIZEOF() | 返回数据元素的大小。 | ### 用户定义的函数 用户定义的函数使用FUNC指令声明,例如: ``` SCR_ADDR .func (\1) + ((\2) << 5) ``` 最多可以使用 9 个参数,即 1 到 9。 要调用函数,只需将参数括在括号内并用逗号分隔即可: ``` stw #SCR_ADDR(10,4)+$2000,<$20 ``` 用户定义的函数可能非常有用,人们经常需要在表达式中一次又一次地使用相同的计算。定义函数将为您节省大量工作,并减少拼写错误。:) 请注意,函数调用可以嵌套,您可以毫无问题地从一个函数调用另一个函数,但是,递归调用将产生错误。 ## 宏 虽然函数对于仅通过函数调用替换常用表达式非常有用,但宏用于用单行代码替换常用指令组。 使用以下命令启动宏定义: ``` label .macro ``` 或者您也可以将标签放在“.macro”关键字之后,如下所示: ``` .macro label ``` 之后跟随宏的主体,该主体由“.endm”指令终止。 例如,让我们定义一个“neg”宏来否定累加器。 ``` neg .macro eor #$FF inc A .endm ``` 宏也可以有参数。在宏体中,您可以通过使用反斜杠字符('')后跟一个数字来引用参数。可以使用9个参数,从1到9。 这是另一个例子: ``` add .macro ; 添加一个值到寄存器A clc ; (处理进位标志) adc .endm ``` 可以使用其他“特殊”参数,以下是您可以在宏中使用的所有可能参数的列表: | 参数 | 描述 | | --------- | ------------------------------------------------------------ | | \1 - \9 | 输入参数 - 最多可以在宏调用中使用9个 | | \\# | 输入参数的数量 | | \?1 - \?9 | 输入参数的“类型”:
ARG_NONE (= 0) = 无参数
ARG_REG (= 1) = 寄存器 -> A, X, Y
ARG_IMMEDIATE (= 2) = 立即数类型 -> #xx
ARG_ABSOLUTE (= 3) = 绝对寻址 -> 标签, $xxxx
ARG_INDIRECT (= 4) = 间接寻址 -> [标签]
ARG_STRING (= 5) = 字符串参数 -> "..."
ARG_LABEL (= 6) = 标签参数 -> 标签 | | \@ | 特殊参数,每个宏返回不同的数字;可用于在宏内定义局部符号。
abs .macro
lda \1
bpl .x\@
eor #$FF
inc A
sta \1
.x\@:
.endm | ## 指令 | 指令 | 描述 | | ---------------- | ------------------------------------------------------------ | | LIST | 启用列表文件生成。您可以稍后使用NOLIST指令暂时停止输出,然后再用LIST重新启动。 | | NOLIST | 停止列出输出。 | | MLIST | 允许在清单文件中进行宏展开。 | | OPT | 请停止在清单文件中扩展宏。
如果您使用“-m”命令行选项,此指令将不会产生任何效果。 | | EQU | 给一个符号赋值。字符 '=' 也有相同的功能。 | | BANK | 选择一个8KB / 16KB / 32KB 的ROM bank,并将位置计数器重置为该bank中最新已知的位置。
当全局bank大小为 8KB时, 有效值范围为0-7663
当全局bank大小为 16KB时, 有效值范围为0-3831
当全局bank大小为 32KB时, 有效值范围为0-1915 | | BANK8 | 选择一个8KB 的ROM bank, 有效值范围为0-7663 | | BANK16 | 选择一个16KB 的ROM bank, 有效值范围为0-3831 | | BANK32 | 选择一个32KB 的ROM bank, 有效值范围为0-1915 | | ORG | 设置程序计数器的位置。
地址的最低13位通知汇编器ROM bank中的偏移量,而最高的3位表示页面索引。 | | BASE | 将程序输出的位置设置在银行尺寸范围内。 | | DB
BYTE | 在当前位置存储一个或多个数据字节。 | | DW
WORD | 存储数据字(小端)。
例如: DW $6502 编译为字节 02 65。 | | RDW
RWORD | 存储数据字(大端)。
例如: RDW $6502 编译为字节 65 02。 | | STR | 存储字符串,第一个字节是字符串的长度。
例如: STR "FlameCyclone" 编译为 0C 46 6C 61 6D 65 43 79 63 6C 6F 6E 65 | | USTR | 存储大写字符串,第一个字节是字符串的长度。
例如: USTR "FlameCyclone" 等同于 STR "FLAMECYCLONE" | | LSTR | 存储小写字符串,第一个字节是字符串的长度。
例如: LSTR"FlameCyclone" 等同于 STR "flamecyclone" | | HEX | 存储以十六进制格式编写的二进制文件。
例如: HEX 78 D8 A9 20 8D 00 20 | | FILL | 填充指定字节并指定长度
例如: FILL $FF,64;在当前位置填充64个内容为$FF的字节数据 | | CHAR_MAP | 指定字符串相关字符映射, 首个参数指定映射起始位置
例如: .CHAR_MAP 'A', $01,$02; 编译 .STR "AB" 将生成 02 01 02 | | DS | 在当前位置保留空间。如果在CODE或DATA组中使用此指令,该空间将填充为零。 | | RSSET | 将RS指令的内部计数器设置为指定值。 | | RS | 给一个符号分配一个值;有点像EQU,但这里分配的值来自内部计数器,分配后,该计数器会增加RS指令中指定的数量。这是一种非常方便的定义结构成员偏移量的方法,以下是一个小例子:
; C:
; --
; struct {
; short p_x;
; short p_y;
; byte p_color;
; } pixel;
;
; ASM:
; ----

.rsset $0 ; 设置RS计数器的初始值
P_X .rs 2
P_Y .rs 2
P_COLOR .rs 1
你可以随后在“像素”结构中使用这些符号作为偏移量。
ldy #P_COLOR
lda [pixel_ptr],Y | | MACRO | 开始一个宏定义。 | | ENDM | 结束宏定义。 | | PROC | | | ENDP | | | PROCGROUP | | | ENDPROCGROUP | | | INCBIN | 将二进制文件包含在当前位置。如果文件大于ROM存储器,将使用尽可能多的连续存储器。
例如: INCBIN, 起始位置, 大小 | | INCLUDE | 请在当前位置包含一个源文件。最多可以有7个级别。 | | INCCHR | 从PCX文件中提取一部分并将其转换为NES 4色8x8图形字符。有三种语法可用:
INCCHR picpcx
不带任何附加参数,该命令将转换整个PCX文件。

INCCHR picpcx,32,4
告诉汇编器仅转换32个字符的4行(一个字符大小为8x8)。

INCCHR picpcx,48,16,32,4
与上述相同,但从坐标48,16(以像素为单位)开始提取字符。 | | DEFCHR | 定义一个字符块(8x8像素)。
该指令接受8个参数(每个参数都存储为8个nybble的32位值),每个参数对应一个像素数据行。
此指令还会重新组织像素数据以符合NES所需的位格式。
请注意,只能使用颜色索引0到3,因为NES瓷砖只有4种颜色。
如果尝试使用更多颜色,将会生成错误。
zero: .defchr $00111110,\
$01000011,\
$01000101,\
$01001001,\
$01010001,\
$01100001,\
$00111110,\
$00000000 | | ZP | 选择零页部分($0000-$00FF)。 | | BSS | 选择RAM部分($0200-$07FF)。 | | CODE | 选择程序代码部分。 | | DATA | 选择程序数据部分
在ZP和BSS部分,您只能分配存储空间,不能存储初始值。 | | IF | 条件汇编指令。
此指令将评估所提供的表达式,然后根据结果打开或关闭条件汇编。
如果结果为空,则关闭条件汇编;如果结果非空,则打开条件汇编。 | | IFDEF
IFNDEF | 这些指令允许条件组装,具体取决于是否定义了标签 | | ELSE | 将条件程序集打开、关闭或反之亦然 | | ENDIF | 终止条件程序集的当前级别。
如果 IF 和 ENDIF 的数量不匹配,则报告错误. | | FAIL | 当汇编程序遇到此指令时,它将中止编译。
可在宏中用于参数错误检测. | ## NES 文件头指令 | 指令 | 描述 | | ------------ | ------------------------------------------------------------ | | INESPRG | 指定 16k prg bank 的数量 (1-3832, 即16-61312 KB). | | INESCHR | 指定 8k chr bank 的数量 (0-3832, 即0-30656 KB). | | INESMAP | 指定使用的 NES 映射器 (0-4095). | | INESMIR | 指定 bank 的 VRAM 镜像。(0: 水平 1: 垂直 2: 四屏) | | INESBAT | 指定 存在电池备份 (0: 不存在 1: 存在)。 | | INESTIM | 指定 CPU/PPU 时序 (0: NTSC, 1: PAL, 2: 多区域, 3: Dendy)。 | | INESSUBMAP | 指定子映射器号 (0-15) | | INESPRGRAM | 指定 PRG RAM 大小 (0: 不存在, 1-15: 存在且大小 = 64字节 左移 1-15 次, 即128字节 - 2048KB) | | INESPRGNVRAM | 指定 PRG NVRAM 大小 (0: 不存在, 1-15: 存在且大小 = 64字节 左移 1-15 次, 即128字节 - 2048KB) | | INESCHRRAM | 指定 CHR RAM 大小 (0: 不存在, 1-15: 存在且大小 = 64字节 左移 1-15 次, 即128字节 - 2048KB) | | INESCHRNVRAM | 指定 CHR NVRAM 大小 (0: 不存在, 1-15: 存在且大小 = 64字节 左移 1-15 次, 即128字节 - 2048KB) | INES 详见: [INES - NESdev Wiki](https://www.nesdev.org/wiki/INES) NES2.0 详见: [NES 2.0 - NESdev Wiki](https://www.nesdev.org/wiki/NES_2.0) ## NSF文件头指令 | 指令 | 描述 | | -------------- | ------------------------------------------------- | | INSFVERSION | 版本, 如 1 | | INSFTOTALSONGS | 总曲目 | | INSFSTARTSONG | 起始播放曲目, 从 1 开始 | | INSFLOAD | 数据加载地址, 如: $8000 | | INSFINIT | 音乐初始化地址, 如: $BF00 | | INSFPLAY | 音乐播放地址, 如: $80D5 | | INSFNAME | 音乐名, 如: "Contra" | | INSFARTIST | 作者, 如: "H. Maezawa, K. Sada" | | INSFCOPYRIGHT | 版权信息, 如: "1988 Konami" | | INSFSPEEDNTSC | NTSC 制式播放速率(每1/1000000秒滴答数), 如: 16666 | | INSFBANKSWITCH | 初始数据块分布, 如: 0,1,2,3,4,5,6,7 | | INSFSPEE | PAL 制式播放速率(每1/1000000秒滴答数), 如: 16666 | | INSFSTANDARD | 制式标准 | | INSFEXTRASOUND | 扩展音源 | NSF 格式详见: [NSF - NESdev Wiki](https://www.nesdev.org/wiki/NSF) ## 例子 ```asm ;====================================================================== ;文件头 NES_16KB_PRG_SIZE = 1 ;16KB PRG大小数量 NES_8KB_CHR_SIZE = 0 ;8KB CHR大小数量 BANK_DATA_MASK = NES_16KB_PRG_SIZE * 2 - 1 ;bank号掩码 ;====================================================================== PRG_DATA_BANK_C000 = NES_16KB_PRG_SIZE * 2 - 2 PRG_DATA_BANK_E000 = NES_16KB_PRG_SIZE * 2 - 1 MAPPER_MIRRORING = 1 ;命名表镜像 0水平 1垂直 ;====================================================================== RESET_BANK = NES_16KB_PRG_SIZE * 2 - 1 RESET_ADDR = $E000 ;主程序起始地址 ;====================================================================== ;====================================================================== .INESPRG NES_16KB_PRG_SIZE ;16KB PRG 数量, $01-$EF8(1-3832),即16-61,312 KB .INESCHR NES_8KB_CHR_SIZE ;8KB CHR 数量,$01-$EF8(1-3832),即0-30,656 KB .INESMAP 4 ;Mapper号 (0-4095) .INESSUBMAP 0 ;子Mapper号 (0-15) .INESMIR 0 ;命名表镜像 (0: 水平 1: 垂直 2: 四屏) .INESBAT 0 ;指定是否存在电池备份 (0: 不存在 1: 存在) .INESPRGRAM 0 ;指定 PRG RAM 大小 (大小 = 64字节 << 计数) .INESPRGNVRAM 0 ;指定 PRG NVRAM 大小(大小 = 64字节 << 计数) .INESCHRRAM 0 ;指定 CHR RAM 大小(大小 = 64字节 << 计数) .INESCHRNVRAM 0 ;指定 CHR NVRAM 大小(大小 = 64字节 << 计数) .INESTIM 0 ;指定时序 (0: NTSC, 1: PAL, 2: 多区域, 3: Dendy) .RSSET $40;内部计数器设置为指定值 FC_Data_L .RS 1;此符号分配后内部计数器 + 1 FC_Data_H .RS 1;此符号分配后内部计数器 + 1 FC_Palette .RS $20;此符号分配后内部计数器 + $20 ;====================================================================== .BANK 0;设置程序所在Bank (限制: 8KB模式 0-7663 16KB模式 3831 32KB模式: 1915) .ORG $8200;设置程序编译地址位置 .BASE $0000;设置程序在中Bank中输出的位置 .INCLUDE "sub.asm" ;引用其他源文件 .INCBIN "sub.bin",$10,$40 ;引用其他文件, 从$10开始, 共$20字节 .STR "FlameCyclone" ;定义一个字符串, 编译结果: 0C 46 6C 61 6D 65 43 79 63 6C 6F 6E 65 .HEX 4E 45 53 1A ;定义HEX数据, 编译结果: 4E 45 53 1A .DW $6502 ;定义双字节数据(小头序), 编译结果: 02 65 .RDW $6502 ;定义双字节数据(大头序), 编译结果: 65 02 .DB $65,$02 ;定义双字节数据编译结果: 65 02 .DS $32;保留32字节数据(用零填充) .RDW $6502 ;定义双字节数据(大头序), 编译结果: 65 02 ;====================================================================== ;测试程序 Test_Proc LDA #$65 STA FC_Data_L LDA #$02 STA FC_Data_H RTS ;====================================================================== .BANK PRG_DATA_BANK_E000;设置程序所在Bank .ORG RESET_ADDR ;不可屏蔽中断处理 Nmi_Program PHA TXA PHA TYA PHA PLA TAY PLA TAX PLA RTI ;====================================================================== ;重启处理 Reset_Program SEI CLD STA $00 LDA #$00 STA $2000 STA $2001 LDA #$80 STA $2000 LDA #$1E STA $2001 .Loop JMP .Loop ;====================================================================== ;请求中断处理 Irq_Program RTI ;====================================================================== ;中断向量表 .ORG $FFFA .DW Nmi_Program .DW Reset_Program .DW Irq_Program ```