アセンブリ言語でHello World書いてみた (z80sim on Mac OS X [M1])
はじめに
「電子立国 日本の自叙伝」という昔のドキュメンタリー番組の中で出てきたCPUの話を見ていて、自分でもCPUを触りたくなったので、とりあえずエミュレーター上でHello, World!
を書き出してみることにしました。普段はフロントエンドを書いたりサーバサイドを書いたりときどきAWSを触ったりしています。
誰かの役に立てば幸いです。
得られる結果と使うコード
z80simのエミュレータの中のメモリ上にHello, World!
がたくさん書き込まれます。それだけです。
使うコードは以下のコードです。
すごい書き方をしてますが、使ったアセンブラだと.db
というディレクティブをアセンブルできないみたいでした。よくわからんのでとりあえず直書きしています。
メモリの0x9000番地に以下のプログラムをロードして、メモリの0x0000番地からHello, World!
を100回ループして書き込むというコードです。シンプル!
ORG 9000H
LOC_BEGIN: EQU 0H
init
LD BC, LOC_BEGIN
LD D, 0
JP loop
RET
loop
LD A,'H'
LD (BC),A
INC BC
LD A,'e'
LD (BC),A
INC BC
LD A,'l'
LD (BC),A
INC BC
LD A,'l'
LD (BC),A
INC BC
LD A,'o'
LD (BC),A
INC BC
LD A,','
LD (BC),A
INC BC
LD A,' '
LD (BC),A
INC BC
LD A,'W'
LD (BC),A
INC BC
LD A,'o'
LD (BC),A
INC BC
LD A,'r'
LD (BC),A
INC BC
LD A,'l'
LD (BC),A
INC BC
LD A,'d'
LD (BC),A
INC BC
LD A,'!'
LD (BC),A
INC BC
INC D
LD A,D
CP 100
JP C,loop
RET
END
環境 【使った8bit CPU(z80)エミュレーター】
自分はこの↓の本を読みながらやっていたのですが、
この本でz80が紹介されていたのでz80でググったら以下の動画が出てきました。そのためここのインストラクション通りにアセンブラとエミュレータをコンパイルしていきました。
↓ここから z80pack-1.29.tgz
をダウンロードして展開しました。(1.37はなんかコンパイルに失敗してしまうのと、コンパイルを無理矢理直して動くようにしたけどHALT命令が無視されるっぽくてよくわからんかったので1.29の方を入れました)
いい感じにmakeしてz80asm
と、z80sim
という2つの実行ファイルを作れたら、環境が手に入ったということになります。
モニタとOSについて
昔は「モニタ」と呼ばれる機能を使って、メモリの中身やCPUの中のレジスタの値がどうなっているかをのぞいていたみたいです。
本の中では、「BASIC言語でモニタを書こう!」と書いてありましたが、ぼくはz80simを持っていてすでにモニタに相当する部分はあるので、BASIC言語部分は飛ばしながら読んでました。
それで、なんかこの「モニタ」が徐々に進化してOSと呼ばれるようになっていったみたいでした。
z80simでの「モニタ」の簡単な使い方
?
でいろいろ見れます。主に r(バイナリ読み込み)
と g(実行)
と d(ダンプ)
と x(レジスタ表示)
を使いました。
こんな感じです
アセンブル方法
asmファイルは、z80asm
でアセンブルできます。コマンドは
$ ./z80asm -v -fm -l test.bin src/helloworld.asm
こんな感じです。実行すると test.bin
と test.lis
ファイルができます。
test.bin
はバイナリです。バイナリはバイナリエディタで見るのがいい気がします。
test.lis
では、どのようなバイナリになるのかの対応を見ることができるみたいです。すごい!
アセンブルは別に z80asm
でやらなくても、自分の手と頭を使って機械語に変換してもOKみたいです。自分の手と頭で変換することをハンドアセンブルというみたいです。
↓ここのz80命令セットを見ながら自分で変換できます(原理的には)
実行方法
z80sim
を起動したら実行ファイルをロードして、ロードしたところのメモリアドレスから実行すると実行できます
>>> r test.bin
Loader statistics for file test.bin:
START : 9000
END : 9044
LOADED: 0045
>>> g 9000
Op-code trap at 0540 dd 52
PC A SZHPNC I IFF BC DE HL A'F' B'C' D'E' H'L' IX IY SP
0542 27 000101 00 11 1390 9090 0598 0000 050d f6af 8d8d 0000 0000 e06b
>>> d 0000
Adr 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f ASCII
0000 - 48 65 6c 6c 6f 2c 20 57 6f 72 6c 64 21 48 65 6c Hello, World!Hel
0010 - 6c 6f 2c 20 57 6f 72 6c 64 21 48 65 6c 6c 6f 2c lo, World!Hello,
0020 - 20 57 6f 72 6c 64 21 48 65 6c 6c 6f 2c 20 57 6f World!Hello, Wo
0030 - 72 6c 64 21 48 65 6c 6c 6f 2c 20 57 6f 72 6c 64 rld!Hello, World
0040 - 21 48 65 6c 6c 6f 2c 20 57 6f 72 6c 64 21 48 65 !Hello, World!He
0050 - 6c 6c 6f 2c 20 57 6f 72 6c 64 21 48 65 6c 6c 6f llo, World!Hello
0060 - 2c 20 57 6f 72 6c 64 21 48 65 6c 6c 6f 2c 20 57 , World!Hello, W
0070 - 6f 72 6c 64 21 48 65 6c 6c 6f 2c 20 57 6f 72 6c orld!Hello, Worl
0080 - 64 21 48 65 6c 6c 6f 2c 20 57 6f 72 6c 64 21 48 d!Hello, World!H
0090 - 65 6c 6c 6f 2c 20 57 6f 72 6c 64 21 48 65 6c 6c ello, World!Hell
00a0 - 6f 2c 20 57 6f 72 6c 64 21 48 65 6c 6c 6f 2c 20 o, World!Hello,
00b0 - 57 6f 72 6c 64 21 48 65 6c 6c 6f 2c 20 57 6f 72 World!Hello, Wor
00c0 - 6c 64 21 48 65 6c 6c 6f 2c 20 57 6f 72 6c 64 21 ld!Hello, World!
00d0 - 48 65 6c 6c 6f 2c 20 57 6f 72 6c 64 21 48 65 6c Hello, World!Hel
00e0 - 6c 6f 2c 20 57 6f 72 6c 64 21 48 65 6c 6c 6f 2c lo, World!Hello,
00f0 - 20 57 6f 72 6c 64 21 48 65 6c 6c 6f 2c 20 57 6f World!Hello, Wo
かっこいい!!!
コードについて
↓ここにファイルを置いたので、ごにょごにょするといいかもしれません。人に見せるように作っていないので、デタラメな感じになっていますがご了承ください。
得られた成果
とにかくほぼ全部の演算をアキュムレータでやらないといけないっぽくて、普段何気なく書いてたことがすべてできなくて、ずっと「ひえ……」という感じで何もできない感がすごかったです。(たとえば割り算は実装しないと使えないとか)
Cであれなんであれ、高級言語を日常的に使えるぼくたちは守られていたんだなということをとても感じました。
ゲームボーイがz80カスタムっぽくてちょっと似てるらしいので、機会があれば触りたいです。
Discussion