目次
はじめに
このページはbyuu氏作のアセンブラであるxkasの使い方+αについての説明が書かれています。
少なからず65C816の知識が必要となるので65C816プログラミングで勉強しておきましょう。
参考資料
xkasはROMデータを書き換えるので空きスペース以外の場所...つまりオリジナルで使われている部分を上書きすることもあります。
オリジナルで使われている部分がどこかを理解するのに少しは役に立つものを置いておきますね。
ROM MAP
ROMの空きスペース
PCアドレス | SNESアドレス | 長さ | 説明 |
$03:4B64 | $06:C964 | 1,692 bytes | $FFで埋まってる |
$03:7739 | $06:F539 | 2,759 bytes | $FF〃 |
$03:A379 | $07:A179 | 1,159 bytes | $FF〃 |
$03:C426 | $07:C226 | 218 bytes | $FF〃 |
$07:72F0 | $0E:F0F0 | 3,856 bytes | $00〃 |
$07:F190 | $0F:EF90 | 4,208 bytes | $00〃 |
ROMの空きスペースを探してくれるツールこちら
Asarには空きスペースを自動で探してそこに処理を書く機能があります。
使い方
-
xkasに用いるROMとASMファイル(+読み込みに必要な外部ファイル)をxkasと同じ階層(同じフォルダ)におく。
+メモ帳を開きそこにxkas (ASMファイル名).asm (ROMファイル名).smc @pause
と書き、名前を付けて保存→(適当なファイル名).batとバッチファイルの形で保存する。
ROM名に空白があると反映されないので注意
- batファイルをダブルクリックで起動させる。
-
おしまい
ちなみに、@pauseは勝手にコマンドプロンプトを閉じないようにするだけのものなので入れなくてもいいです。
binファイルを生成する場合は、xkas (ASMファイル名).asm (生成binファイル名).bin @pause
と書けばアセンブルしてくれます。ただし、xkasはROMに書き込むこと前提らしく、生成されるbinファイルは32kb(アセンブルしたasmの記述以外は皆$00)になってしまします。
なので自分でヘキサエディタを用いて必要な部分を抜き取る手間がかかります。これは新型(v1.2)で解決されています。
xkasのあれこれ
TRASMがasmをbinに翻訳することに強いのに対し、xkasはコードを指定場所に書き込むことに特化してるアセンブラです。
xkasにはASMの表記に加え特別な文法があります。このことについて説明します。
ですが暗記しなければならないものではありません、メモ書き程度に見ましょう。
記述するもの
それに関する説明 となっています。
…実のところ使えないものが大半です。いや、効果はあるんですが普通にやったほうが楽っていうw
romの情報に関する説明
hirom
hiromのアドレッシングを用いることを示します。SMWでは通常必要 ありません。
lorom
loromのアドレッシングを用いることを示します。SMWではこちらを用います。
header
romにheader(romの最初の$200bytes)が含まれることを示します。SMWでは必須です。
特殊な命令に関する説明
; コメント
特殊ではないですが;コメントです。この記号から後ろの文字はコメント扱いされます。~外部ファイル内(asm,txt)でもコメントになります。バシバシ書いちゃいましょう。
NOP #3
(命令) (回数)とやると(回数)分NOPが実行されます。
(回数)は#(10進数),$(16進数)で指定します。
使えるのはNOP,ASL,LSR,INC,INX,INY,DEC,DEX,DEYなどです。しかしLDA #0とやってもLDA #$00と勘違いされてしまいます。
(LABEL名): (例1) JMP LABEL1 RTS LABEL1: 処理 (例2) JMP LABEL2 RTS LABEL2() 処理
ラベルです。(例1)のようにBEQやJMPなどの移動命令の移動先に指定してあげます。
ラベルには2バイト文字...つまり「あ」とかの全角文字は使えません。また半角であっても数字からは始められません。
というかコメント外に2バイト文字があるとアセンブラ的によくないです。 (←全角スペース)など見落とすと厄介なので気をつけましょう。
(例1)(例2)ともやっていることは変わりません。ラベルの終りが:か()かの違いだけです。
ラベルの終わりには必ず:か()をつけます。
rep 10 : NOP
rep (回数) : (命令)とやると、(命令)を(回数)分実行します。↑の例ではNOPを10回実行します。
(回数)は#,$で記述します。無表記の場合10進数となります
つまりバイナリでEAが10回書き込まれるわけです。なぜEAかというと65C816のNOPの命令がバイナリではEAだからです。~
rep 5 : LDA #$10
このように、アドレッシングモードも付け加えられます。このときLDA #$10が5回分なのでA9 10が5回分書き込まれるわけです。
他の命令はどうなのかはバイナリ&ASM一覧を見ましょう。
fillbyte $00 : fill 10
fillbyte $aa : fill bb(a,bには数値)とやると、その場所からbb回分、aaが書き込まれます。
今までのもの同様#,$で回数を表記し、無表記の場合10進数となります。
↑の例では10回分$00が書き込まれるわけです。なんとなくrepと似ていますね。
org $8000 : padbyte $00 : pad $8010
fillbyteとほぼ同じですが、↑の例の場合SNESアドレスで $00:8000-$00:800Fまで$00と書き込まれます。
orgについては、下のアドレス指定の説明を見てください。
db / dw / dl / dd
バイナリデータとしてそのまま書き込まれます。xkasではdcbが使えないのでこちらを用いましょう。
dbは8bit dw-16bit dl-24bit dd-32bitで指定します。
ちなみにb-byte w-word l-long d-dwordという意味です。いろんなとこで使われるので覚えておいて損はないです。指定方法は以下の通りです。
db $01,$02,$03,$04 dw $0001,$0002,$0003,$0004
dbは8bitなのでこのように1byteずつになります。カンマで区切ってあげましょう。同様にdwは16bitなので2bytesです。
この場合、バイナリデータが直接書き込まれるのでファイルには
01 02 03 04 01 00 02 00 03 00 04 00
と書き込まれますね。
db $01,"test",$04
このように""(ダブルクォーテーション)で括ることで文字列を入れることもできます。
この場合バイナリ文字でtestと出るので01 74 65 73 74 04となります。
74 65 73 74がtestの文字列になるからですね。アスキーだっけ?こういう文字って...
db $01,test,$04 test = $00
一見前の例と同じように見えますがかなり違います。この結果は01 00 04と書き込まれられます。
""で括っておらず、testという文字列で見なされないので、後で指定したtest = $00が認識され、testは$00に置き換えられてしまうのです。
(1) testA = $00 (2) $00 = testA (3) testA equ $00 (4) testA=$00
定義です。一般的には(1)...左のもの(testA)に右の物($00)が代入される形をとります。
ほとんどのプログラミング言語でそうですが"="は等しいという意味ではなく代入を意味してます。
(ちなみに等しいを現すのは"=="です。といってもxkasはおろか、他のアンセブラも認識してくれないでしょうw)
話が逸れました、他にも(2)...下の右の物(testA)に左のもの($00)が入るという指定方法
があります。
(3)は(1)と同じですが、使う人はまぁいないでしょうw意味はどちらも変わらないのでお好きな方をお使いください。
ただし例外があり(4)のように=をくっつけてしまうとうまく働きません。
![名前] = "命令 : 命令 …" ![名前]()
定義その2です。このようにやると![名前]()としたところから、テーブルである![名前]の命令が実行されます。
またラベルとは違い、必ず!から始めなければなりません。
説明だけでは解り辛いので例を見てみましょう↓
(例1) !DATA = "PHA : PHX : PHY : PHK" !DATA() (例2) !DATA2 = "LDA #$00 : STA $19 : RTS" !DATA2()
解り易くなったでしょうか?(例1)では!DATA()とした所からPHA,PHX,PHY,PHKの順番に実行されます。
また(例2)のようにアドレッシングモードを付け加えることもできます。
普通に命令を書いたほうが早いので使い道がほぼないですがASMの始まり/終りのスタックの処理などで使ってやってください。
LDA #$02 : STA $19
書き方は(命令) : (命令)です。(命令)が3つでも4つでも大丈夫です。
普通は命令毎に改行しないと起こします。それを可能にするのが:(コロン)です。
ラベルと勘違いされるので、必ず:の間に半角スペースを入れてください。
↑の例の様に簡単な流れを見やすくするのに便利です。
print "(文字列) ",(接尾文字)
(文字列)の後ろには半角スペースを必ず入れます。
コンソールウィンドウ(コマンドプロンプトなどで開くウィンドウのこと)に (文字列) (接尾文字)による数値 を表示させます。
ですが実際に(文字列)がROMに書き込まれるというわけではありません。これはデバッガに用いられるものなのです。
また(接尾文字)には以下の3つの文字が使われます。
pc - 現在のSNESアドレス位置 bytes - print〜と表記するまでに使用された命令bytes opcodes - print〜と表記するまでに使用された命令
まだ、よくわからないと思います。サンプルです。
LDA #$00 RTS org $1FFE00 print "INIT ",pc
↑INIT 1ffe00と表示されます。SNESアドレスがorgのアドレス指定によって$1FFE00になるからです。
orgについてはこちら
LDA #$00 RTS org $1FFE00 print "INIT ",bytes
↑INIT 3と表示されます。LDA #$00はA9 00 RTSは60で合計3bytes分だからです。
LDA #$00 RTS org $1FFE00 print "INIT ",opcodes
↑INIT 2と表示されます。命令のみ見られるのでLDAとRTSで合計2bytes分だからです。
使い道?デバッガとかbliteのxkas版でOFFSETの指定とか...
macro (マクロ名)(id)
(処理)<id>
endmacro %(マクロ名)(数字)
一番難しいであろうマクロの説明です。重要ではないのでさらっと見てください。
指定方法は上の通り...て言ってもよくわからないでしょう。こんな感じに使います。
macro MACRO_1(id) LDA <id> STA $19 endmacro %MACRO_1(0) (いろいろな処理) %MACRO_1(2)
$19はマリオの状態ですね。macro〜endmacroの中にある命令は書き込まれません。
%MACRO_1とやることで、macro MACRO_1(id)〜endmacroの中身を実行します。
ではそのあとの(0),(2)はなんでしょうか?
これは<id>とやったところに(0),(2)が入ります。
つまり、%MACRO_1(0)とやると、その場所から
LDA #0 STA $19
となるのです。(2)の場合は#2になりますね。
(id)や<id>のidの文字はどちらも一緒ならなんでもOKです。
macro MACRO_2(id0,id1) LDA <id0> LDY <id1> STA <id1> STY <id0> endmacro %MACRO_2($00,$01)
IDの部分は複数指定する事が可能です。
LDA #$02 {STA $19} RTS
なんなんだこれは!なんか意味分からんのが出てきたぞ!
…安心してくださいxkasで当てると{}は空白に置き換えられます ←{ で始めたり} で閉じない...つまり片方だけでも大丈夫
だからといってコメントになったわけではないので、
{うはwwwこめんとwwwおkwww} RTS
なんて絶対にしないこと! だけど
main(){ LDA #$02 STA $19 RTS
} なんてやるとカッコイイし見やすいよね!
incbin filename.bin
外部ファイルを読み込みます。binファイルを読み込みたいときはincbin (ファイル名).binとやります。
asmと同じフォルダ階層にないとエラーを吐きます。binファイルの内容がそのままバイナリで書き込まれます。
この命令をした場所からバイナリデータの書き込みが始まるので、外部ファイルが長すぎると他のデータを上書きしてしまいます。
incsrc (ファイル名).asm/incsrc (ファイル名).txt
とやればasmやtxtの読み込みもします。
この場合ファイルはbin化され、バイナリデータとして読み込まれます。
つまりファイルにVipという文字列があった場合56 69 70と書き込まれるのです。
アドレス指定に関する説明
org $07F300
org $(アドレス) とすると$(アドレス)がPCアドレスに変えられ、その場所から書き込みが始まります。
つまり↑の例ではSNESアドレス$07:F300(即ちPCアドレス$03:F500)から書き込みが始まります。
!CODE_OFFSET = $1ACE00 org !CODE_OFFSET
このようにテーブルも使えます。例ではSNES $1A:CE00(即ちPC $0D:5000)から書き込みが始まりますね。
!CODE_OFFSET = $1ACE00 org !CODE_OFFSET+$08
このようにするとSNES $1A:CE00+$08 = $1A:CE08(即ちPC $0D:5008)から書き込みが始まります。
もちろん-(マイナス)も使えます。RATSタグを使うときのアドレス調整に便利です。
ラベルを用いての計算はスペースを入れるとエラーを吐きます。
計算
xkasは計算にも大分対応しています。計算に数字だけでなくラベルも使えます
↓使えるもの一覧です。右の計算式は例です。
!Levelnum = $000105 + 和 !Levelnum+$01 = $000105 - 差 !Levelnum-$02 = $000103 * 積 !Levelnum*$08 = $000828 / 商 !Levelnum/$0A = $00001A >> 左シフト 65C816でいうASL つまり2倍 << 右シフト 65C816でいうLSR つまり1/2倍 & AND | OR ^ XOR ~ NOT
ただ計算は左→右の流れになっていることに気を付けてください。
1*2+3 = 5 1+2*3 = 9
簡単ですね。掛け算での優先順位は関係なく、とにかく左から右へと計算されるのです。
まとめ
では今までやってきたもののまとめをします。簡単なものから説明していきます。
header lorom !SFX = $1F org $0093C1 db !SFX
アドレスの指定とテーブル、dbを使っています。それぞれがどういう意味かわからないなら再確認しましょう。
今までの話が理解できていればこの例ではSNES:$93C1(PC:15C1)に$1Fが入ることがわかります。
PC $15C1はNintendo Presentsの効果音です。(デフォルトは$01...だっけ?)
つまりこれはNintendo Presentsの効果音を$01→$1FにするASMとなるわけです。
テーブルの応用です。
!DATA_A = $10 !DATA_B equ $1558,x LDX #!DATA_A LDA !DATA_B
これはXに16進数で10、Aに$1558 + Xが入ります。
DATA_Aの前に#があるので#$10となるのです。またテーブルのDATA_Bのようにアドッレッシングモードも指定できます。
LDX $10となりRAMの$10の値がXに入ります。つまり$10がFFならばXにFFが入ることになりますね!
RATSタグ
!CODE_OFFSET = $1ACE00 !MAIN_CODE_SIZE = END_OF_FILE-Codestart org !CODE_OFFSET-$08 db "STAR" ; \ dw !MAIN_CODE_SIZE-$01 ; | RATSタグ生成 dw !MAIN_CODE_SIZE-$01^$FFFF ; / Codestart: LDA #$02 STA $19 RTL END_OF_FILE:
RATSタグの生成+マリオの状態固定処理です。RATSタグについてはこちら
これにはアドレスの指定や計算などが用いられています。
RATSタグは8bytes使用するので!CODE_OFFSETから8bytes分引き、うまい具合に!CODE_OFFSETのアドレスから望みの処理が来るようにしています。
RATSタグには処理の長さが必要なので、処理の終わり(END_OF_FILE)から始まり(Codestart)のアドレスを引き、長さ(!MAIN_CODE_SIZE)を求めています。
あとは65C816の基本が備わっていれば解読できるはずです。
続いてマクロの応用です。
;;;;;;;;;;;;;;;;; macro RATS_start(id) db "STAR" dw RATS_Endcode<id>-RATS_Startcode<id> dw RATS_Endcode<id>-RATS_Startcode<id>^#$FFFF RATS_Startcode<id>: endmacro macro RATS_end(id) RATS_Endcode<id>: endmacro ;;;;;;;;;;;;;;;;;;; org $xxxxxx %RATS_start(0) (処理) %RATS_end(0) ;;;;;;;;;;;;;;;;;;; org $yyyyyy %RATS_start(1) (処理) %RATS_end(1)
RATSタグを複数持たせなければならないときにはRATSタグの生成にマクロを使うと便利になるでしょう。
とりあえず使えそうな物はほとんど挙げ終わった。もうちょっと種類あるけど、正直こっちもワカンネ(´A` )
マクロの変数を使った「&」演算は無理(?)っぽい
xkas用ASMの自作
ルーチンの書き換え
xkasを使う理由は何といってもオリジナルのデータを上書きできることです。
それによって例えば、オリジナルのファイアボールのデータ(以後ルーチン)を弄って追加効果を持たせるとかできます。
オリジナルのデータを上書きするのにこんなやり方があります。(というか大体この方法)
↓この様なオリジナルのデータがあるとします。 STZ $1000 ; \ LDA #$10 ; | この部分を書き変えることにする STA $1001 ; / 次の処理...LDA #$30
これを適当なROMの空き場所に飛ばしそこで処理をさせるのです。例えば上の部分をこのようにします。
JML $1ACE00 ; ROMの空き場所...PC $0D:5000 NOP #4 ; #$FF : STA $1001の部分が余ってしまったのでNOPで補完する org $1ACE00 ; 空き場所で処理を行う STZ $1000 ; \ LDA #$10 ; | オリジナルデータの処理 STA $1001 ; / LDA #$20 ; \ 追加処理 STA $1002 ; / JML $(次の処理のアドレス)
STZから始まる部分をSNES $1A:CE00に飛ばし、そこでオリジナルの処理+追加処理を行っているのがわかります。
例のようにJM~で空き場所に飛んだ場合同じJM~で変えた部分の次の場所まで戻してあげましょう。
JM~はメインルーチンを飛ばします。メインがRT~で終了しちゃったらマズイでしょ。
JS~はサブルーチンのジャンプなのでRT~とやればサブルーチン先から返ってくるので必要ないです。
自作その1
ちょうどいい練習材料がありました。これを元にxkas用ASMを作っていきましょう。
少しでいいのでこれを読んで理解しておきましょう。
まずはromの情報とROMの空き場所を指定します。
header lorom !CODE_OFFSET = $1ACE00 ; PC $0D:5000 <- 空き場所
これでいいですね。空き場所はお好きにどうぞ
資料を読むとROMのPC $00:15DA~ 空き場所に飛ばすように書き換えればいいようです。
org $0093DA ; PC $00:15DA JSL !CODE_OFFSET NOP #2 ; NOP*2で補完
こうなりますね。続いて、空き場所での処理を書きます。
org !CODE_OFFSET LDA $0100 ; \ ゲームモード。ロゴ画面以外はBLACKへ。 BNE BLACK ; / これをしないとMARIO STARTなどにも影響。 LDA #$FF ; \ STA $0701 ; | 色の設定 LDA #$7F ; | これは真っ白の設定。 STA $0702 ; / RTL ; return BLACK: STZ $0701 ; 色を真っ黒に STZ $0702 ; RTL ; return
最後にRATSタグを追加して終了です。完成品はこうなります。
header lorom !CODE_OFFSET = $1ACE00 ; PC $0D:5000 <- 空き場所 org $0093DA ; PC $00:15DA JSL Codestart ; JSL !CODE_OFFSETとやるとRATSタグまで入ってしまう NOP #2 ; NOP*2で補完 ;;;;;;;;;;;;;;;;;;;;;;;;;;;; !MAIN_CODE_SIZE = END_OF_FILE-Codestart org !CODE_OFFSET-$08 ; !CODE_OFFSETから処理が始まるように調整 db "STAR" ; \ dw !MAIN_CODE_SIZE-$01 ; | RATSタグ生成 dw !MAIN_CODE_SIZE-$01^$FFFF ; / Codestart: LDA $0100 ; \ ゲームモード。ロゴ画面以外はBLACKへ。 BNE BLACK ; / これをしないとMARIO STARTなどにも影響。 LDA #$FF ; \ STA $0701 ; | 色の設定 LDA #$7F ; | これは真っ白の設定。 STA $0702 ; / RTL ; return BLACK: STZ $0701 ; 色を真っ黒に STZ $0702 ; RTL ; return END_OF_FILE:
挿入してみましょう。ロゴ時に背景が真っ白だったら成功です。
その他
エラーメッセージ
まんまエラーメッセージとその対処法です。エラーを起こすとコマンドプロンプト上にその詳細が現れます。asmでのエラーはこんな記述です。
error: ファイル名.asm: line 数字: エラー内容
(ファイル名).asm内の(数字)行目が(エラー内容)のミスを犯してるということです。(エラー内容)について見ていきましょう。
'名称' は、内部コマンドまたは外部コマンド、 操作可能なプログラムまたはバッチ ファイルとして認識されていません。
asmファイルとは関係ない部分のエラーです。batファイルの記述ミスなどが原因です。
error: [ファイル名.拡張子] not found
こちらも関係ないエラーです。エラーが出たファイルをxkasと同じ階層に置きましょう。
label [ラベル名] not found [分岐命令 ラベル名] 例) label [LABEL00] not found [BEQ LABEL00]
ここからasm内のエラーです。必要なラベルが見つかりません。
negative branch too long, exceeded bounds [分岐命令 ラベル名]
分岐ジャンプが長すぎます。分岐により飛べる範囲はB**は1byte(+:$01-$7F/-:$80-$FF)、J*Rは2bytes分です。
invalid opcode or command [名称]
表記ミスです。コメント外に変な記述が含まれていたり、命令が間違っているかもしれません。
よくあるミス
REP #$20 LDA #$0001
誤翻訳されLDA #$01と見なされる場合があります。
REP #$20 LDA.w #$0001
に直しましょう。.wはwordを表しているので16bit分になるのです。
他にも.b(8bit)/.l(24bit)/.d(32bit)があります。これらはすべて小文字で指定します。
LABEL1 LDA #$00
一つのラベルとして誤翻訳されてしまいます。ラベル名のあとには必ず:か()をつけましょう。↓
LABEL1: LDA #$01
xkas_v12について
新しくバージョンUPしました。DLは同じくCのToolsのカテゴリから。
どう変わったのか
・SNESに加えGBAで用いられているアセンブリ言語のアセンブルもできるようになりました。が、ここでは関係ありませんね。
・asm → bin のみの生成が上手にできるようになりました。(なぜ「上手に」かは通常版のbinの生成方法のあたりを参照)
・書式が変化しました...一部の書式が変化しました。(旧型のxkas向けのasmと互換性がないです。)
書式の違いから慣れるのに苦労しますが、人によっては慣れると使いやすいかもしれません。自分は旧版ですが。
書式
xkas.exeの中に必要なファイルを置いて以下のバッチファイルを作りましょう。(コマンドプロンプトより楽でしょうし)
-
binファイルの生成
xkas (生成したいbinファイル名).bin (アセンブルするasmファイル名).asm
-
smcに書き込む
xkas (書き込みをしたいsmcファイル名).smc (書き込むasmファイル名).asm
もちろんbinファイルなど外部ファイルの読み込みをする場合は、そのファイルも同じフォルダに入れてください。
ROMの情報に関する説明
arch snes.cpu; lorom
SNESのCPUを用いり、ROMはloROMであるとうことです。SMWではこの記述は必須です。
header noheader
上はROMに$200bytesのヘッダがある。下はないことを示します。SMWでは上の記述が必須です。
binのみの生成の場合あまり必要ないです。
書式が変わった命令
//コメント
コメントです。高級言語でよく用いられているコメント方式になりました。旧版同様に;(セミコロン)にしないように。
また、 /* コメント */の形はとれません。
LDA #$00 ; STA $19 ; RTS
1行に複数の命令は;(セミコロン)を用います。旧版同様に:(コロン)にしないように。
; 一つの命令の定義 define (定義名) "(命令)" ;--以上が定義、下の記述で定義したものを現す-- {定義名} ; 複数の命令の定義 define (定義名) "(命令); (命令)" ;---- {定義名} ; 命令に数値指定がある場合 define (定義名) "(命令); (命令)" define (数値の定義名) (数値) {add} {数値の定義名} ;---- {定義名}
定義です。見ただけじゃパっとしませんね。数値指定する命令が複数あるとうまくいかないみたい…情報求めます。
↓使用例です。
define add "CLC; ADC" define health_bonus $12 define health_bonus2 $34 ;---- {add} #{health_bonus} // ? {add} #{health_bonus2} // ? {add} {health_bonus} // ? {add} {health_bonus},x // ?
まず最初にCLCとADCの複数定義ということを定めています。ADCは数値指定が必要なので、適当な数値をいれます。
例では数値に$がついてますが、$は16進数であるという表明でしたよね。同様に何もない場合は10進数、%は2進数となります。
?はCLC ; ADC #$12となります。#は数値の直接指定でしたよね。
?はCLC ; ADC #$34となります。このように(数値の定義名)を複数使うことも可能です。
?はCLC ; ADC $12となります。直接指定ではないので(数値)の値のRAMが指定されます。
?はCLC ; ADC $12,xとなります。このようにすればアドレッシングモードも使用できます。
ただし定義の段階では数値指定もアドレッシングモードの指定もできません。
(ラベル名): .(サブラベル名):
上は旧版同様ラベルです。もちろん半角文字のみです。
新版ではサブラベルが使えるようになります。必ず最初に.(ピリオド)をつけます。半角文字のみです。
B**やJ**のジャンプ命令でサブラベルに飛びたい場合、たとえばBRAの場合 BRA (ラベル名).(サブラベル名)とします。
↓使用例です。例中にコメントしてあるもので解説の代わりとします。
LDA $14 // フレームカウンタを読み込む BEQ TIMER.ZERO // 0だったのでラベル[TIMER]のサブラベル[ZERO]に移動 CMP #$01 // 1で比較 BEQ TIMER.ONE // 1だったのでラベル[TIMER]のサブラベル[ONE]に移動 CMP #$02 // 2で比較 BEQ TIMER // 2だったのでラベル[TIMER]に移動 CMP #$03 // 3で比較 BEQ TIMER.THREE // 2だったのでラベル[TIMER]のサブラベル[THREE]に移動 LDA #$FF // \ 適当な処理 STA $1000 // | (例として$1000にFFをストア) RTS // 終了 TIMER: // ラベル[TIMER] RTS // 終了 .ZERO: // ラベル[TIMER]のサブラベル[ZERO] STZ $1000 // (例として$1000に0をストア) BRA TIMER.THREE // ラベル[TIMER]のサブラベル[THREE]に飛びます .ONE: // ラベル[TIMER]のサブラベル[ONE] LDA #$01 // \ STA $1000 // | (例として$1000に1をストア) RTS // 終了 .THREE: // ラベル[TIMER]のサブラベル[THREE] DEC $1000 // (例として$1000をDEC) RTS // 終了
正直そんなに使い道がないような気がします...
Asarだと…
Asarだと旧バージョンのxkasに近い文法になります。
これはCから適当にasmファイルをダウンロードしてきて中身を見てみるとよろしい。ここで解説するよりそっちの方が身に付きます。
分からないことがあったらここのコメント欄か、Discordの日本語改造マリオコミュニティで質問すれば誰かが答えてくれるかもしれない。