6502でアセンブラ短歌

6502/コモドール64でアセンブラ短歌を詠むために,アセンブラ環境を構築する方法を 説明します.

なおここではFreeBSDでの例を主に説明します.UbuntuやCentOSなどの GNU/Linuxディストリビューションでも,同様の手順でできるかと思います. apt-getなどでインストールできるツールを探してそれを利用するのが楽で いいでしょう.

目次

6502アセンブラ

■ 各種のアセンブラ

まずは6502向けのコードを出力できるアセンブラが必要です. これにはZ80で説明した,asl/tpasm/asmxが利用できます.

GNUのbinutilsを使いたいところなのですが,どうもbinutilsは6502に対応していない ようです.なのでasl/tpasm/asmxのいずれかを利用するのが楽でよさそうです.

以下では一応,ひととおり使いかたを説明します.

■ サンプルコード

アセンブルのサンプルに,以下のコードを利用します. コモドール64のROMのSTROUTというルーチン($AB1E)の機能を利用して 「Waka」と出力するものです.(松田さんに作っていただきました.謝々)

■ asl

以下でアセンブルしてベタバイナリを生成できます.

% asl -cpu 6502 6502.asm -o 6502.p
% p2bin -r \$-\$ 6502.p 6502.bin

■ tpasm

以下でアセンブルしてベタバイナリを生成できます.

% tpasm -P 6502 6502.asm -o srec 6502.srec
% objcopy -I srec -O binary 6502.srec 6502.bin

■ asmx

以下でアセンブルしてベタバイナリを生成できます.

% asmx-6502 -o 6502.srec 6502.asm
% objcopy -I srec -O binary 6502.srec 6502.bin

コモドール64エミュレータ

■ viceについて

コモドール64のエミュレータとしてviceがあります. FreeBSDのportsにもなっています.他にも frodo というのがあるようです.

viceはコモドール64のROMを利用しています. このROMはライセンスがちょっと不明瞭な気がします. なので一応,ライセンス回避のためにROMを利用せずにプログラム実行する 方法をここでは説明します.

■ パッチ当てしてビルドする

サンプルプログラムではROMが持っているSTROUTルーチンを利用しています. これは文字列出力ルーチンですが,単にサブルーチン呼び出し命令で 0xAB1E という アドレスを呼び出すことで実現しています.

ということはこのAB1Eへのジャンプをラッチしてそれっぽい動作をすれば, ROMを利用することなくSTROUTの動作を実現することができます.

で,こんなパッチを作成してみました. AB1Eへのジャンプを検出すると渡された文字列を標準出力に出力するものです.

以下のようにパッチ当てしてビルドします.

~>% tar xvzf vice-2.4.tar.gz
~>% cd vice-2.4
~/vice-2.4>% cat ~/kernal_stub.c >> src/6510core.c
~/vice-2.4>% ./configure
~/vice-2.4>% make x64 (or gmake x64)
  ※ パッチがC64以外のことを考慮していないので,x64のみ生成する
~/vice-2.4>% cd src
~/vice-2.4/src>% ls x64
x64
~/vice-2.4/src>% 

■ ダミーのROMを作成する

以下のようにして,ダミーのROMイメージを作成します.

必要なのはBIOSに相当するkernal,BASICインタプリタのbasic,キャラクタコードの chargenです.とりあえずすべて空のもので構いません.

~/vice-2.4/src>% dd if=/dev/zero of=kernal bs=1024 count=8
~/vice-2.4/src>% dd if=/dev/zero of=basic bs=1024 count=8
~/vice-2.4/src>% dd if=/dev/zero of=chargen bs=1024 count=4

■ プログラムの用意

作成したkernalを,以下のように修正します.

  1. バイナリエディタでkernalを開いて,オフセット 0x1ffc の位置を「00 E0」 のように書き換えます.これがリセットベクタになります.
  2. kernalの先頭に,上で作成したプログラムのベタデータ(6502.bin)の内容を そのまま書き込みます.具体的には,以下のバイト列を書き込みます.
    a9 00 48 a9 41 48 aa a9  4b 48 8a 48 a9 77 48 ba
    e8 8a a0 01 20 1e ab 28  28 28 28 28 60
    

■ 実行する

以下で実行します.

~/vice-2.4/src>% ./x64 -kernal kernal -basic basic -chargen chargen -console
いろいろログが出てわかりにくいのだけど,以下のように文字が出力されています. 「Waka」と出力されています.(大文字小文字が逆転しちゃってますが...)
77 w 41 A 4b K 41 A 

■ キャラクタ出力する

これでいちおう文字列出力は確認できるのですが,ちと寂しいので キャラクタをビットマップ出力してみます.

そのためにはビットマップデータのchargenが必要なのですが,とりあえず 適当に作ってみたので,以下をダウンロードしてください. 単なるビットマップデータなので,自作することは難しくはありません.

~/vice-2.4/src>% cp ~/chargen.bin .
パッチの「BITOUT」の部分を有効にします.
~/vice-2.4/src>% vi 6510core.c
                 → #define BITOUT を有効にする
~/vice-2.4/src>% cd ..
~/vice-2.4>% gmake x64
~/vice-2.4>% cd src
~/vice-2.4/src>% 

以下のように chargen.bin を指定して実行します.

~/vice-2.4/src>% ./x64 -kernal kernal -basic basic -chargen chargen.bin -console
今度は以下のように出力されるはずです.
       w
   wwwww
 www    
wwwww   
    ww  
wwwww   
 wwwwww 
      ww
        
 AA     
  AAAAA 
   A  AA
   A AAA
   AAA  
 AAAA   
AA      
        
        
KKKKKKKK
   KK   
   KKK  
  KK KKK
KKK    K
K       
        
 AA     
  AAAAA 
   A  AA
   A AAA
   AAA  
 AAAA   
AA      

■ vice解析

参考までに,viceのソースコードの解析結果を簡単に.

以下のように動作しています.

  1. 起動すると src/6510core.c の DO_INTERRUPT() が呼ばれる.
  2. DO_INTERRUPT() でリセット割り込み(IK_RESET)が処理され, JUMP(LOAD_ADDR(0xfffc)) が実行される.
  3. 0xfffcはkernal上のオフセット0x1ffcに相当する.そこに配置されている 2バイトが読まれ,そこにジャンプする.よってそこにエントリポイントの アドレスを書いておけばそこから実行開始できる.
    ※ kernalは0xe000以降に配置される(src/c64/c64mem.c:mem_bank_read()参照) なのでオフセット0x1ffcはメモリ上の0xfffcに相当する.
  4. jsr命令による関数コールが行われると,src/6510core.c の以下の部分が 呼ばれる.JSR()はマクロになっていて,スタックやPCの操作をしている.
              case 0x20:            /* JSR $nnnn */
                JSR();
                break;
    
このためkernalのオフセット0x1ffcの位置に飛び先のアドレス(今回は0xe000)を 書いておき,kernalの先頭に実行したいプログラムを書いておけば, 起動直後にそこにジャンプして実行されることになります.

■ オリジナルのchargenを作成する

chargenはキャラクタの単なるビットマップなので,それっぽいものならば 割と簡単に作成できます.

私はbitmapというツールで1文字ずつxbm形式で作成し,スクリプトで結合して データ化しました.参考までに以下で配布します.無保証ですがどうぞご自由に.

以下のスクリプトが含まれています.
メールは kozos(アットマーク)kozos.jp まで