NAME

CPU::Z80::Assembler - a Z80 assembler

SYNOPSIS

  use CPU::Z80::Assembler;

  $CPU::Z80::Assembler::verbose = 1;
  $CPU::Z80::Assembler::fill_byte = 0xFF;
  $binary = z80asm(q{
      ORG 0x1000
      LD A, 1
      ...
  });
  $binary = z80asm_file($asm_file);
  $binary = z80asm(@asm_lines);
  $binary = z80asm('#include <file.asm>');
  open($fh, $file); $binary = z80asm(sub {<$fh>});

  $lines  = z80preprocessor(@asm_lines); $line  = $lines->next;
  $tokens = z80lexer(@asm_lines);        $token = $tokens->next;

DESCRIPTION

This module provides functions to assemble a set of Z80 assembly instructions given as a list or as an iterator, or a Z80 assembly source file.

EXPORTS

All functions are exported by default.

FUNCTIONS

z80asm

This function takes as parameter a list of either text lines to parse, or iterators that return text lines to parse.

The list is passed to z80lexer, that in turn calls z80preprocessor to handle file includes, and then splits the input into tokens.

The stream of tokens is passed on to CPU:Z80::Assembler::Parser that parses the input and generates the object image in CPU::Z80::Assembler::Program. Assembly macro expansion is handled at this stage by CPU::Z80::Assembler::Macro.

The assembly program is composed by a list of CPU::Z80::Assembler::Segment, each representing one named section of code. Each segment is composed by a list of CPU::Z80::Assembler::Opcode, each representing one assembly instruction.

The output object code is returned as a string.

If the $CPU::Z80::Assembler::verbose variable is set, an output listing is generated by CPU::Z80::Assembler::List on standard output.

Assembly is done in five steps:

  1. input is preprocessed, scanned and split into tokens

  2. tokens are parsed and converted to lists of opcodes

  3. addresses for each opcode are allocated

  4. relative jumps are checked for out-of-range jumps and replaced by absolute jumps if needed

  5. object code is generated for each opcode, computing all expressions used; the expressions are represented by CPU::Z80::Assembler::Expr.

z80asm_file

This function takes as argument a Z80 assembly source file name and returns the binary object code string.

z80preprocessor

This function takes as parameter a list of either text lines to parse, or iterators that return text lines to parse.

The list is passed to the Asm::Preproc that takes care of file includes and handles the %line and #line lines generated by external preprocessors like cpp or nasm.

The result is a Iterator::Simple::Lookahead of Asm::Preproc::Line objects that contain each of the input lines of the input.

z80lexer

This function takes as parameter a list of either text lines to parse, or iterators that return text lines to parse.

It calls z80preprocessor to split the input into a Iterator::Simple::Lookahead of Asm::Preproc::Line objects representing the source lines of the Z80 assembly language program.

It returns a stream of Asm::Preproc::Token objects for each assembly token in the input.

Each token contains a type string, a value and a Asm::Preproc::Line object pointing at the input line where the token was found.

SCRIPTS

z80masm

  z80masm sourcefile [destfile]

The z80masm program, installed as part of this module, calls the z80asm_file() function to assemble an input source file, generates an output binary file, and produce an assembly listing on standard output.

SYNTAX

Input line format

Instructions are written in ASCII text. Opcodes are separated by new-line or colon : characters. Comments start with ;. Lines starting with # are ignored, to handle files generated by pre-processors.

    ; comment beginning with ;
    # comment beginning with # as first char on a line
    [LABEL [:]] INSTRUCTION [: INSTRUCTION ...] [; optional comments]
    LABEL [:]
    LABEL = EXPRESSION [; ...]

Preprocessing

See Asm::Preproc.

Tokens

The following tokens are returned by the stream:

reserved words

  Asm::Preproc::Token('word', 'word', $line)

All the reserved words and symbols are returned in lower case letters.

strings

  Asm::Preproc::Token(STRING => $string, $line)

Single- or double-quoted strings are accepted. The quote character cannot be used inside the string. The returned string has the quotes stripped.

identifiers

  Asm::Preproc::Token(NAME => $name, $line)

The program identifiers must start with a letter or underscore, and consist solely of letters, underscores and numbers. There is a special case $ identifier that represents the current location counter.

Identifiers are returned with case preserved, i.e. the assembler is case-sensitive for labels and case-insensitive for assembly reserved words.

numbers

  Asm::Preproc::Token(NUMBER => $decimal_number, $line)

Numbers are converted to decimal base from one of the following formats:

  • Decimal numbers are sequences of the digits 0..9, e.g. 159.

  • Hexadecimal number are sequences of the digits 0..9 and letters A..F, prefixed by one of 0x, $ or #; or prefixed by a zero digit, if the number starts by a letter, and suffixed by a H character, e.g. 0xFA21, 0FA21H, 10H, $FA21, #FA21.

  • Binary numbers are sequences of the digits 0..1, prefixed by one of 0b or %; or suffixed by B, e.g. 0b10, 10B, %10.

Z80 assembly

See Asm::Z80::Table for all allowed Z80 instructions, including the undocumented Z80 opcodes and composed instructions.

relative jumps

The DJNZ and JR instructions take an address as their destination, not an offset. If you need to use an offset, do sums on $. Note that $ is the address of the *current* instruction. The offset needs to be calculated from the address of the *next* instruction, which for these instructions is always $ + 2.

A relative jump instruction can always be used. The assembler automatically replaces it with an absolute jump if the distance is too far, or if the given flag is not available, e.g. jr po,NN. A djnz NN instruction is converted to dec b:jp nz,NN if the distance is too far.

stop

This extra instruction (which assembles to 0xDD 0xDD 0x00) is provided for the convenience of those using the CPU::Emulator::Z80 module.

Pseudo-instructions

defb

Accepts a list of expressions, and evaluates each as a byte to load to the object file.

defw

Accepts a list of expressions, and evaluates each as a 16-bit word to load to the object file, in little-endian order.

defm, deft

Accepts a list of literal strings, either single- or double-quoted. The quoted text can not include the quotes surrounding it or newlines. The characters are loaded to the object file.

defmz

Same as defm, but appends a zero byte as string terminator after each string.

defm7

Same as defm, but "inverts" (i.e. bit 7 set) the last character of the string, as string terminator.

equ, =

Labels are created having the value of the address they are created at.

Alternatively labels may be assigned expressions by using equ or =. The expressions use the Perl operators and can refer to other labels by name, even if they are defined further on the file. The $ can be used in the expression to represent the current location counter.

  label      = $ + 8
  otherlabel = label / 2 + 3

org

Tell the assembler to start building the code at this address. If it is not the first instruction of the assembly, the gap to the previous location counter is filled with $CPU::Z80::Assembler::fill_byte. If absent, defaults to 0x0000.

include

Recursively include another file at the current source file.

Macros

Macros are supported. See CPU::Z80::Assembler::Macro for details.

BUGS and FEEDBACK

We welcome feedback about our code, including constructive criticism. Bug reports should be made using http://rt.cpan.org/.

SEE ALSO

CPU::Z80::Assembler::Macro CPU::Z80::Assembler::Parser CPU::Emulator::Z80

AUTHORS, COPYRIGHT and LICENCE

Copyright (c) 2008-2009, David Cantrell <david@cantrell.org.uk>, Paulo Custodio <pscust@cpan.org>

This software is free-as-in-speech software, and may be used, distributed, and modified under the terms of either the GNU General Public Licence version 2 or the Artistic Licence. It's up to you which one you use. The full text of the licences can be found in the files GPL2.txt and ARTISTIC.txt, respectively.

The Spectrum 48K ROM used in the test scripts is Copyright by Amstrad. Amstrad have kindly given their permission for the redistribution of their copyrighted material but retain that copyright (see http://www.worldofspectrum.org/permits/amstrad-roms.txt).

CONSPIRACY

This software is also free-as-in-mason.