Msx Assembly 101: 03 Using YAZE
Recently I found myself spending days (it will be one month with two weeks break in the middle) in a place, where I have an internet connection but not a computer. I do have an iPad with a keyboard, though, and it has SSH- and VNC-clients. Unfortunately, there are too many hops to home and too many hoops to jump (including port-forwarding over reverse SSH tunnel) to use VNC comfortably. This means that I cannot use MSX emulators. However, I wanted to continue my experiments with Z80 programming – over SSH.
What I found is Z80-CP/M emulator YAZE-AG.
Setting up an emulator
If you are using FreeBSD, then there is yaze-ag
package to install. If you
are not using FreeBSD, you are on your own.
After installation, run z80
once to create cpm
subdirectory in your home
directory. You will need to press Enter several times to reach CP/M proper, due
to the things startup script does. Then use command e
to exit an emulator.
Next thing we want to do is to create and connect a disk for our programs. Go
to cpm
subdirectory in your home directory.
Creation of a disk
Go (on your host) to freshly created cpm
directory, run the command cdm
and
enter create user.ydsk
to create an empty disk image; use quit
to exit:
❯ cdm
CP/M Disk Manager 1.11, Copyright 1995 Frank D. Cringle.
Portions copyright (C) Jan 2004 Carl Mascott.
Modified by Andreas Gerlich Jan 2004 to create files for CP/M 3.1 (yaze-ag).
cdm comes with ABSOLUTELY NO WARRANTY; for details
see the file "COPYING" in the distribution directory.
$>create user.ydsk
$>quit
Connecting a disk
Now in the cpm
subdirectory of the home directory, add the following
line to the file .yazerc
:
mount c user.ydsk
To verify that the disk is connected, run z80
again, enter dir c:
in CP/M,
and you should see the message No File
, not some error message about invalid
drive.
Preparing a program
We want to have a program which can be easily compiled both to MSX .rom
file
(meaning cartridge) and to CP/M .com
file (program). The cross-assembler I am
using (asMSX) can do both. I have described how to compile things to cartridge
in my first article. The
things which are different in CP/M programs are:
- Starting address should be
0x100
. - There should be no special header in the file.
- File extension should be
com
. - One should not use MSX BIOS calls but OS calls instead.
- The program should end with
ret
not with infinite loop.
Creation of CP/M program
To create a proper .com
file we can use asMSX’s .MSXDOS
directive. After it
is used, one can use the directive CALLDOS <N>
to call DOS function number N
instead of
ld c, <N>
call 0005h
The list of CP/M functions and their number is easy to find; it is available, for example, here. Notice the function 9 for outputting $-terminated string I have mentioned in the previous installment. I think $-terminated strings are very wrong thing, and this function should not be used.
So let us modify first.asm
so that the compilation will produce .com
-file
for running under CP/M:
.MSXDOS
ld e,'A'
CALLDOS 02h
ret
To check that everything works do the following.
- Compile the program with
asmsx first.asm
. Now you should get the filefirst.com
in the current directory. - Start YAZE with
z80
command. - Change the current drive to C:
C:
. - Copy the compiled file to CP/M with
r <full path to first.com>
. To verify runDIR
, and you should see freshly copiedFIRST.COM
. - Run the compiled program with
FIRST
; it should printA
to the screen. - Exit the emulator with
e
command.
Conditional compilation
Next we will modify our program so it can be compiled both as cartridge .rom
file and as CP/M .com
program.
First, create a file format.asm
and define CPM
variable there:
CPM=1
Now we will modify first.asm
so that it behaves differently in cases when
CPM
variable is defined, and when CARTRIDGE
variable is defined:
.INCLUDE "format.asm"
IFDEF CARTRIDGE
.PAGE 1
.ROM
.BIOS
ENDIF
IFDEF CPM
.MSXDOS
ENDIF
Stop: MACRO
IFDEF CARTRIDGE
@@end:
jr @@end
ENDIF
IFDEF CPM
ret
ENDIF
ENDM
PutChar: MACRO #c
IFDEF CARTRIDGE
ld a,#c
call CHPUT
ENDIF
IFDEF CPM
ld e,#c
CALLDOS 02h
ENDIF
ENDM
PutChar 'A'
Stop
If you compile the program now (asmsx first.asm
) the CP/M program first.com
will be generated, as before. However, if you change format.asm
to state
CARTRIDGE=1
then the cartridge file first.rom
will be created.
Automating things with make
Change format.asm
manually is no fun, so instead we will use Makefile
which
would allow us to simply run make first.com
or make first.rom
. The
Makefile
below is compatible with both BSD and GNU make:
.SUFFIXES: .com .rom
.asm.com:
@echo "CPM=1" > format.asm
@asmsx $<
@rm -f ~tmppre.* format.asm
%.com: %.asm
@echo "CPM=1" > format.asm
@asmsx $<
@rm -f ~tmppre.* format.asm
.asm.rom:
@echo "CARTRIDGE=1" > format.asm
@asmsx $<
@rm -f ~tmppre.* format.asm
%.rom: %.asm
@echo "CARTRIDGE=1" > format.asm
@asmsx $<
@rm -f ~tmppre.* format.asm
clean:
@rm -f ~tmppre.* *.rom *.com *.z80 *.sym format.asm
.PHONY: clean
It is also possible to run make clean
to remove build artefacts. If you are
not interested in GNU make compatibility, you can remove all %.blah
lines. If
you are not interested in BSD make compatibility, you can remove .SUFFIXES
line and .asm.blah
targets.