NESASM 3.2 使用说明

5 篇文章 0 订阅
5 篇文章 0 订阅

更新说明

介绍

此仓库来源于 nesasm , 并对其功能进行完善

功能描述
相对路径逻辑修改使用include incbin等命令时相对路径基于使用命令的文件, 不再是基于程序当前工作目录
绝对寻址优化增加绝对寻址可转变为零页寻址时使用零页寻址(不用显示指定零页寻址)
增加STR指令STR指令增加长度限制(可选范围0-255)
标签长度优化标签长度从32扩展到256
命令行增加 -fill指定填充内存
命令行增加 -fns指定生成fns函数地址列表文件(原来默认生成且不能控制)
命令行增加 -out指定输出文件名
命令行增加 -bank 指定bank大小
预处理指令增加 .HEX用于指定十六进制编写的字节数据
预处理指令增加 .RDW用于指定大头序双字节数据
预处理指令增加 .BASE用于指定编译结果放置位置
支持中文标签
兼容65s指令语法兼容65s
() 间接寻址
<取低位
>取高位
文件头增加 电池备份指令INESBAT
文件头增加 INES2.0 支持INESTIM
INESSUBMAP
INESPRGRAM
INESPRGNVRAM
INESCHRRAM
INESCHRNVRAM

NESASM v3.2 使用手册

命令行用法

nesasm_3_2.exe [-选项] [-? (帮助)] 输入文件, 例如

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
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
HEX存储以十六进制格式编写的二进制文件。
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存储器,将使用尽可能多的连续存储器。
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当汇编程序遇到此指令时,它将中止编译。
可在宏中用于参数错误检测.
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)

例子

;======================================================================
;文件头
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
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值