[M]ultiple [P]rocessor [M]odule Assembler V1.5 – 2018

MMMMM MMMMM PPPPPPPPPPPPP MMMMM MMMMM MMMMMM MMMMMM PPPPPPPPPPPPPPP MMMMMM MMMMMM MMMMMMMMMMMMMMM PPPP PPPP MMMMMMMMMMMMMMM MMMM MMMMM MMMM PPPPPPPPPPPP MMMM MMMMM MMMM MMMM MMMM PPPP MMMM MMMM MMMM MMMM PPPP MMMM MMMM MMMMMM MMMMMM PPPPPP MMMMMM MMMMMM

https://gitlab.com/bits4fun/mpm

1

Contents

Introduction 7 History 7 Future Mpm developments (V2.x) 8

Compiling Mpm from source code 8 Using Qt Creator 8 Using Mingw on Windows 8 Using Make & GCC on Unix platforms 8 Runtime library dependencies 8

Installing Mpm from binary application package 8 Windows XP and newer 8 MAC OSX 8 9

Mpm filename patterns 9 Source code 9 Error files 9 Object files 9 Static library files 9 Executable files 9 Listing files 9 Source code symbol files 9 Label address (of executable code) map files 9 Exported global label address files 9

Instructing the assembler on the command shell 9 Syntax overview 9 Display syntax of available options and features 10 Getting Mpm help from man pages (Unix only) 10 Specify to disable an option 10 Grouping of enabling/disabling options 10 Compiling sources as object files without linking 10 Create object files, always 10 Creating a static linkable library of modules 10 Compiling sources to executable code 10 First filename is template for compiled output files 10 Split executable code into 16K segments (Z80 only) 11 Creating a CRC-32 checksum of executable code 11 Creating a SHA-256 checksum of executable code 11 Creating Intel Hex output of executable code 11 Linking executable code with calls from a static library 11 Compile only updated source code 11 Using a project file for executable code and libraries 11 Defining source code dependency files (includes) 11 Creating listing files 11 Creating executable address map file 11

2

Exporting global address labels as definition file 11 Change default assembly source file extension 11 Change default object file extension 11 Specify file system search path for INCLUDE directive 11 Specify file system search path for static libraries 11 Specify base address of executable code (ORG) 12 Create address-independent executable code (Z80 only) 12 Override default executable code filename 12 Pre-defined boolean true symbols for source code 12 Enable external line number mode (for LINE directive) 12 Display Mpm's version information 12 Mpm version information for scripts 12 Verbose information while compiling 12

Mpm's use of environment variables 12 MPM_INCLUDEPATH 12 MPM_LIBPATH 12 MPM_STDLIBRARY 12

Macros 12 Introduction 13 Using macros 13 Macro definition 13 Rules of macro definition 13 Macro definition syntax 14 Macro call 14 Macro expansion 15 Macro default parameter arguments 15 Examples 15

Assembler Directive Reference 16 ALIGN 17 ASCII 17 ASCIIZ 17 BINARY 17 BYTE 17 DB 17 DC 17 DEFB 17 DEFC 17 DEFGROUP 17 DEFINE 17 DEFL 17 DEFM 17 DEFMZ 17 DEFP 17 DEFS 18 DEFSYM 18 DEFVARS 18 DEFW 18

3

DL 18 DM 18 DMZ 18 DP 18 DS 18 DV 18 ENUM 18 EQU 18 ERROR 18 EXTERN 18 GLOBAL 19 IF – ELSE - ENDIF 19 INCLUDE 19 LIB 19 LIBRARY 19 LINE 19 LONG 19 LSTOFF 19 LSTON 19 MACRO 19 MODULE 19 ORG 19 SPACE 19 STRING 19 UNDEFINE 19 VARAREA 20 WORD 20 XDEF 20 XLIB 20 XREF 20

Assembler Function Reference 21 $DAY 21 $EVAL 21 $HOUR 21 $LINKADDR 21 $MINUTE 21 $MONTH 21 $MPMVERSION 21 $PC (and $ as program counter) 21 $SECOND 21 $YEAR 21

Z80 CPU Instruction set implementation 22 Optional Z80 mnemonic instruction syntax 22 Using [] as alternate for expression brackets 22 The undocumented Z80 instructions 22 Supporting address-independent executable code 23

Appendix 26

4

Mpm Object file format 26 The standard platform identifier symbol 27

5

Copyright

Copyright (C) 1991-2018, Gunther Strube, [email protected]

This document is part of Mpm. Mpm is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. Mpm is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Mpm; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

1 Introduction The Mpm Macro Cross Assembler currently supports compilation of CPU assembly language and is able to run on any major OS performing cross-compilation of assembly source code files into Z80 CPU executable binaries. Mpm is an assembler and linker combined as one tool.

Mpm is available on all major operating system platforms such as Windows, Mac OS X and Linux, also supporting embedded platforms such as the Raspberry Pi.

Mpm is implemented in Ansi-C supporting executables on 32bit and 64bit architectures. It is designed to be a multi-platform tool, automatically handling file naming conventions and correct code generation, byte ordering, no matter which architecture it is being executed on. Mpm is designed as an easy command line interface compiling source files into stand-alone applications.

Mpm assists the assembly language programmer with these typical high-level features:

Mpm as a command line shell tool, usually integrated into scripts for projects assembler and (static) linking functionality integrated as one tool include file referencing project-oriented modularized source code organisation macros as a way to inline grouped assembly instructions or data-structures support for defining meta data structures project source file-level dependencies compile only updated sources generate object files and libraries for static application linking Z80 CPU code generation

Mpm has been designed with the focus on flexibility and extensibility and is available as Open Source through the GPL v2 license. This document provides all information about Mpm assembler functionality thoroughly explained with examples. This document also provides a reference for easy access to command line options and directives and assembler source code

6 directives.

1.1 H istory Mpm was originally written in SuperBasic running on a Sinclair QL in 1991 to assist the ​ ​ development of Cambridge Z88 applications (compiling code on the QL and transfer the executable binaries to Z88 via serial port). At the time, only proprietary (and very pricey for a Z88 enthusiast) Z80 assembler tools were provided by Cambridge Computer, the company selling the Cambridge Z88 portable computer. The idea was to create a complete development toolset, available for free, enabling the community to make applications for the Cambridge Z88.

It was later ported to Lattice C using the Sinclair QL's C68 C compiler. The final port was done ​ ​ to Ansi C to allow easier compilation on more platforms, beginning with MS DOS and Linux/Unix. After a couple of years, "z80asm" was adopted by the Z88dk (Small-C) project for ​ ​ being the final step of executable code generation to the Small-C compiler on Z80-based systems. z80asm has since then been improved vastly to be a perfect companion for the Small-C compiler tool-chain.

Around 1996, z80asm was forked into Mpm as becoming a more CPU-agnostic assembly language compiler tool. A proof-of-concept were done for the Sony PlayStation 2 hacker community in Denmark, generating Mips R5900 CPU code. This implementation was never released to the public, yet the internal optimisations of data structures and algorithms, general source code & expression parsing and 64bit code generation – were re-integrated for the Z80 CPU target. Mpm has since then been the core tool for the Cambridge Z88 development project on Sourceforge and now on cambridgez88.jira.com and continues to be ​ ​ fine-tuned for today's 64bit operating systems.

1.2 F uture Mpm developments (V2.x) Mpm currently supports it's own object file format and code generation for the Z80 CPU. Future releases will support ELF binary executable output for Z80, Arm (Raspberry Pi as first target) & ​ ​ Mips CPU's (r5900 as first target).

2 Compiling Mpm from source code The source code of Mpm packaged as Zip or Tar.gz can be downloaded from here:

2.1 Using Qt Creator ...

2.2 Using Mingw on Windows ...

2.3 Using Make & GCC on Unix platforms ...

2.4 Runtime library dependencies ...

7

3 Installing Mpm from binary application package Mpm is a command line tool and as such you decide where to install the executable and ensure that it is available via the operating system program search PATH. Mpm is run via a command line shell and is typically integrated into scripts.

Installation packages have been provided for all major platforms.

3.1 Windows XP and newer …

3.2 MAC OSX …

3.3 Linux ...

4 Mpm filename patterns

4.1 Source code …

4.2 Error files …

4.3 Object files …

4.4 Static library files …

4.5 Executable files …

4.6 Listing files …

4.7 Source code symbol files ...

4.8 Label address (of executable code) map files …

4.9 Exported global label address files ...

8

5 Instructing the assembler on the command shell Mpm is executed using the operating system standard command line environment (CLI). On Unix platforms this will be a terminal shell such as Bash. On Windows platforms, it is identified ​ ​ as the command prompt also known as the MS-DOS prompt.

5.1 Syntax overview When executing the assembler from the command line without options, i.e. mpm, a ​ ​ help page is automatically displayed where after control is returned to the operating system command line. The page shortly explains the syntax of option specification and which options are available.

The syntax of the assembler options is a straightforward design. One or more assembler source code filenames are specified, parsed in the order from left to right. Filenames may be replaced by a project file that contains all files to be compiled. The options may be left out (surrounded here with []): mpm [-options]{filenames} | @projectfile

As seen above, [-options] must be specified first, followed by the names of assembler source ​ ​ files.

Filenames may be specified with or without the .asm filename extension which is regarded as ​ ​ the default by Mpm.

At least one source file must be specified and may be repeated with several file names. Only one project file may be specified if no source file names are given. You may use comment lines inside projects files using semicolon.

Options are used to control the assembly process and output. They are recognized by the assembler when you specify a leading minus before the option identifier ('-'). When the assembler is executed options are all preset with default values and are either switched ON or OFF (active or not).

5.2 Display syntax of available options and features -h … ​ 5.2.1 Getting Mpm help from man pages (Unix only) man mpm ... ​ 5.3 Specify to disable an option If an option is to be turned explicitly off, an 'n' is specified before the identification, for example -na to ensure that listing file output is disabled. ​ ​ ​ 5.4 Grouping of enabling/disabling options Upper and lower case letters are distinguished, which means that 'a' is a different command than 'A'. Single letter options without parameters can be concatenated in a single option block.

The following example shows two groupings (each option flag is explained in detail below):

-s -nvdbcgA

9

5.5 Compiling sources as object files without linking …

5.5.1 Create object files, always -j ... ​ 5.6 Creating a static linkable library of modules -x … ​ 5.7 Compiling sources to executable code …

5.7.1 First filename is template for compiled output files (bin and map files) (binary output can be changed with -o option)...

The first specified source file is interpreted as the main executable code base filename, when using -b option. Generated binary output will use the base filename and appended ...

5.7.2 Split executable code into 16K segments (Z80 only) -cz80 … ​ 5.7.3 Creating a CRC-32 checksum of executable code -crc32 ... ​ 5.7.4 Creating a SHA-256 checksum of executable code -sha2 ... ​ 5.7.5 Creating Intel Hex output of executable code -ihex ... ​ 5.8 Linking executable code with calls from a static library …

5.9 Compile only updated source code -d ... ​ 5.10 Using a project file for executable code and libraries …

5.10.1 Defining source code dependency files (includes) …

5.11 Creating listing files -a …

5.12 Creating executable address map file -Map (enabled by default). Disable with -nMap …

10

5.13 Exporting global address labels as definition file -g … ​ 5.14 Change default assembly source file extension -e … ​ 5.15 Change default object file extension -M … ​ 5.16 Specify file system search path for INCLUDE directive -I (multiple)… ​ 5.17 Specify file system search path for static libraries -L (multiple)… ​ 5.18 Specify base address of executable code (ORG) -r … ​ 5.19 Create address-independent executable code (Z80 only) -rz80 … ​ 5.20 Override default executable code filename -o … ​ 5.21 Pre-defined boolean true symbols for source code -D … ​ 5.22 Enable external line number mode (for LINE directive) -C … ​ 5.23 Display Mpm's version information If you need to know the version of Mpm you're using, simply type mpm or mpm ​ ​ ​ -version on the command line. ​ 5.23.1 Mpm version information for scripts …

5.24 Verbose information while compiling -v ... ​ 6 Mpm's use of operating system environment variables The assembler looks into the operating system environment for these three variables, if the equivalent functionality has not been specified on the command line. These environment variables are convenient for shell scripts that might instantiate them for use while the shell script is executing

11

6.1 MPM_INCLUDEPATH Defines the default path of header/include definition files. Multiple paths may specified using operating system specific path separator (“:” in UNIX, “;” in MS-DOS & Windows). Equivalent to the -I command line option. See Specify file system search path for INCLUDE directive on ​ ​ ​ ​ page .

6.2 MPM_LIBPATH ...

6.3 MPM_STDLIBRARY ...

12

7 Macros

7.1 Introduction A macro is a single, symbolic statement that results in a series of substituted statements when it is translated.

A macro can be thought of as simple source code substitution. For example, if macro XYZ is defined as “instr1, instr2, and instr3”, then every time you use XYZ in your source code, the assembler substitutes and assembles “instr1, instr2, and instr3” automatically for you. Macros also can be thought of as “in-line” subroutines, whereby the “CALL SUBR” is replaced by the actual SUBR code for each occurrence (call).

Macros shorten and simplify source programming because you can use a single instruction to represent entire blocks of statements that, otherwise, would be used repetitively throughout a program.

Macros help you avoid the tedium of repeatedly coding and verifying a common sequence of statements. The macro processor also supports parameterizing a block of statements so that variations in the block also can be called out.

7.2 Using macros The formation and translation of macros involves three distinctive steps:

1. Macro Definition. The macro definition associates a macro name with a block of source statements.

2. Macro Call. The macro call names a previously defined macro, and the associated macro body is expanded at the point where the call appears.

3. Macro Expansion. The process of replacing a macro call with a macro body is known as macro expansion.

7.3 Macro definition Macros are defined using the MACRO and ENDMACRO directives. The MACRO directive denotes the beginning of the macro definition; the ENDMACRO instruction denotes the end of the macro definition. The name of the macro and the names of its formal parameters are specified by the MACRO instruction. Statements within the MACRO and ENDMACRO instructions constitute the macro body. Such statements may be assembler instructions, assembler directives or comments.

Macro definitions are frequently kept in a separate source file, and included in the assembled source module using the INCLUDE directive.

7.3.1 Rules of macro definition A macro can be defined anywhere in the source assembly, if it appears before the first source line that calls the macro

A macro cannot contain sub-macro definitions

A macro definition remains in effect for the rest of the source module

A macro definition may contain calls to other macros. Hence, recursive macro calls are allowed within the definition

A macro name must be unique and cannot use predefined names such as assembler

13

directives and CPU instruction mnemonics.

When a macro body is executed, all parameters that affect conditions (IF, etc) must be evaluable, ie. no forward-referenced names.

7.3.2 Macro definition syntax Mpm implements the standard syntax as seen from gas (Gnu Assembler) and zmasm, the standard Zilog Macro Cross Assembler. The following three syntax definitions will be recognized, to allow parsing of difference legacy styles:

macroname MACRO ["("] [Parameter1 [, Parameter2 ] . . .] [")"] ​ ​ statements [MACEXIT] | [EXITMACRO] | [EXITM] ​ ​ ​ ​ ​ ​ statements ENDM | MACEND | ENDMACRO ​ ​ ​ ​

MACRO macroname ["("] [Parameter1 [, Parameter2 ] . . .] [")"] ​ statements [MACEXIT] | [EXITMACRO] | [EXITM] ​ ​ ​ ​ ​ ​ statements ENDM | MACEND | ENDMACRO ​ ​ ​ ​

.MACRO macroname ["("] [Parameter1 [, Parameter2 ] . . .] [")"] ​ statements [.MACEXIT] | [.EXITMACRO] | [.EXITM] ​ ​ ​ ​ ​ ​ statements .ENDM | .MACEND | .ENDMACRO ​ ​ ​ ​

7.4 Macro call A macro call causes the assembler to expand a macro definition by processing the statements of the macro definition body at the point where the macro call instruction appears. Expansion includes replacing the formal parameters in the macro body with the actual parameters specified on the macro call instruction. Parameters are separated with comma:

macroname aParameter1 , aParameter2 ... Brackets can be used to surround the parameters (optional):

macroname (aParameter1, aParameter2 ...) Parameters can be skipped:

macroname aParameter1, , , aParameter4 The macroname must be the name of a previously defined macro. By definition, if ​ ​ macroname is not the name of a previously defined macro, then the instruction is not a macro call and will be interpreted by Mpm as a CPU instruction mnemonic, assembler directive or an address label.

Macro names cannot be used to override existing functionality of assembler

14 directives or CPU instruction mnemonics, contrary to other assemblers such as GAS.

Parameters specify the n actual parameters passed to the macro. Each parameter can be ​ arbitrary strings of ASCII characters, excluding commas (which are used to separate parameters).

There can be any number of parameters, although they must all fit on one source line. The actual and formal parameters are paired positionally.

If more than one parameter is specified, the individual parameters must be separated by commas. If a parameter is to include embedded spaces or commas, then it must be quoted by enclosing it in matched pair macro quotes [ and ] or using “”.

A parameter may be omitted by coding only whitespace, or nothing, in its place. The comma separator can be specified without a parameter, to skip it. A skipped parameter becomes an empty string in the expanded macro body at the parameter placeholder position.

Each macro parameter can also be defined with a default value (see Macro default parameter arguments), which then is used when the parameter is skipped at the macro call.

7.5 Macro expansion …

7.6 Macro default parameter arguments Macros may be specified with default parameter arguments. Default arguments apply to all three macro definitions styles. The syntax below uses one syntax style as an example:

macroname MACRO Parameter1 = , Parameter2 = ​ ​ statements ENDMACRO

can be anything. Each parameter argument is separated with a comma. ​ Optionally, enclose the value with double quote " " or square brackets [ ] to ensure that parsing doesn't conflict with identifying the next macro argument or end of macro arguments.

7.6.1 Examples The following example shows a definition of a macro using default parameters ( brackets are used below for convenience around the arguments, yet are not mandatory):

macro xyz ( par1 = 1, par2 = " (string, embedded) ", par3 = [(constant_name+1)] ) defb \par1\ defm "\par2\" defb \par3\ endmacro

when executing this macro (without arguments):

15

xyz would generate

defb 1 defm " '(string, embedded)' " defb (constant_name+1)

Skipping parameters is allowed too, for example: xyz , , 3 would generate

defb 1 defm " '(string, embedded)' " defb 3

xyz 4 would generate

defb 4 defm " '(string, embedded)' " defb (constant_name+1)

16

8 Assembler Directive Reference ...

8.1 ALIGN …

8.2 ASCII …

8.3 ASCIIZ …

8.4 BINARY …

8.5 BYTE …

8.6 DB …

8.7 DC …

8.8 DEFB …

8.9 DEFC …

8.10 DEFGROUP …

8.11 DEFINE …

8.12 DEFL …

8.13 DEFM …

8.14 DEFMZ …

17

8.15 DEFP …

8.16 DEFS …

8.17 DEFSYM …

8.18 DEFVARS …

8.19 DEFW …

8.20 DL …

8.21 DM …

8.22 DMZ …

8.23 DP …

8.24 DS …

8.25 DV …

8.26 ENUM …

8.27 EQU …

8.28 ERROR …

8.29 EXTERN …

18

8.30 GLOBAL …

8.31 IF – ELSE - ENDIF …

8.32 INCLUDE …

8.33 LIB …

8.34 LIBRARY …

8.35 LINE …

8.36 LONG …

8.37 LSTOFF …

8.38 LSTON …

8.39 MACRO …

8.40 MODULE …

8.41 ORG …

8.42 SPACE …

8.43 STRING …

8.44 UNDEFINE …

19

8.45 VARAREA …

8.46 WORD …

8.47 XDEF …

8.48 XLIB …

8.49 XREF …

9

20

10 Assembler Function Reference May be specified as part of an expression…

10.1 $DAY ..

10.2 $EVAL ..

10.3 $HOUR ..

10.4 $LINKADDR ..

10.5 $MINUTE ..

10.6 $MONTH ..

10.7 $MPMVERSION ..

10.8 $PC (and $ as program counter) ..

10.9 $SECOND ..

10.10 $YEAR ..

21

11 Z80 CPU Instruction set implementation Mpm implements the Zilog Z80 assembler instruction set mnemonic reference syntax. All Z80 rd variations implemented by 3 ​ party vendors are not supported. However, these can be ​ implemented using macros.

Z80 executable code generated by Mpm enforces the 64K address range (16bit address bus).

11.1 Optional Z80 mnemonic instruction syntax We have added some syntactical option on a few Z80 mnemonics. They are: djnz label (the comma is not needed) in F,(C) (special case instruction which only affects the flags)

The instructions below allow additional specification of the accumulator register. Zilog standard convention is to only specify the source operand. Sometimes it is better to specify the accumulator to make the instruction look more clear, and to avoid confusion. After all, Zilog specified it for add, adc and sbc instructions. ​ ​ ​ ​ ​ ​ sub a,r sub a,n sub a,(hl) sub a,(ix+0) sub a,(iy+0) this syntax applies also to and,or,xor & cp instructions. ​ ​ ​ 11.2 Using [] as alternate for expression brackets Explain the ambiguity of indirect addressing syntax colliding when it's needed to do an expression...

11.3 The undocumented Z80 instructions Mpm implements syntax parsing and code generation of the undocumented Z80 CPU instructions. They are as follows, including instructions both IX and IY 8bit registers:

IN F,(C) LD r,IXL r = A,B,C,D,E,IXL,IXH LD r,IXH LD IXL,r LD IXH,r LD IXL,n n = 8bit operand LD IXH,n

SLL A, B, C, D, E, H, L, (HL), (IX+d), (IY+d)

ADC A,IXL ADC A,IXH (also for ADD, AND, CP, DEC, INC, OR, SBC, SUB, XOR)

RLC (IX+d),r r = A,B,C,D,E,H,L (also for RRC,RL,RR,SLA,SRA,SLL,SRL,BIT,RES,SET)

Please read Sean Young's "The Undocumented Z80 Documented" at http://www.z80.info which ​

22 thoroughly explains all instructions.

11.4 Supporting address-independent executable code The Z80 processor instruction set allows only relative jumps in maximum +/- 128 bytes using the JR and DJNZ instructions. Further, there is no program counter relative call-to-subroutine or jump-to-subroutine instruction. If you want a piece of executable code to be address-independent, no absolute address references may be used in jump or call instructions. You can only write small routines using the JR and DJNZ instructions. With a restricted interval of 128 bytes you can imagine the size of those programs. Programming of large applications using address independence is simply not possible on the Z80 processor with the basic instruction set available.

However, there is one solution: before your compiled code is executed, an auto-generated address-relocation is performed in the current RAM location of the loaded code. This is done only once. The downside of this solution is the program uses more space in memory. This is unavoidable since information must be available to define where the address relocation has to be performed in the program. Further, a small routine must be included with the program to read the relocation information and patch it into the specified locations of the program. It is impossible to determine the exact extra size generated with a relocation table. We assume an extra size of approx 3.5K for a typical 16K application program.

You can generate address independent code using the -rz80 option accompanied with the -a ​ ​ ​ or -b option. ​ ​

Requirement: ​ The principle of relocation is in fact self-modifying code. You cannot relocate a program that has been blown into an EPROM or FLASH memory (cannot be modified). You may only execute Z80 relocatable programs in RAM.

One example of utility is to load the compiled machine code in the BBC BASIC application environment of the Cambridge Z88 portable computer. This can easily be interfaced with a DIM statement to allocate memory for the machine code program, and issue a CALL or USR() ​ statement to execute the machine code.

Please note that the linking process with the -rz80 option addresses your code from 0 ​ ​ onwards. This is necessary when the runtime relocation is performed by the relocator (just before your program is executed). This can be examined by loading the address map file into a text editor.

The relocator is built into Mpm. The relocation table is created during the linking phase. When all object modules have been linked and the appropriate machine code generated, the process is ended with first copying the relocator routine into the executable file, then a relocation table and finally the compiled machine code. Any defined base address (ORG) in your code is ignored - this is not necessary for relocatable code...

Two rules must be obeyed when using relocatable code:

1. The IY register must have been set up to point at the address where your program resides. The first code is in fact the relocator which manipulates your code on the basis of the IY register. If IY is not setup properly your machine code program will be

23

relocated for an address it is not resided at. On execution your might then call a random address (on the basis of the random IY register).

2. Don't use the alternate register set for parameter passing between the caller (of your code) in the main code and the relocated program. The following registers are affected by the initial relocation process:

AFBCDEHL/IXIY/...... same ...... /..../afbcdehl different

You still have all the main registers for parameter passing which is more than sufficient for average programming.

When your address-independent code is stored to the file, a message is displayed by Mpm which informs of how many bytes the relocation header consists of. This constant is useful since it informs you of the distance between the relocation header and the start of your code.

The map file automatically reflects the relocation header. All addresses of your code has been modified to include the relocation header. Please note that all addresses in the map file are defined from address 0. When your code is placed in an absolute memory address, and you need to perform a debugging session, you can find your specific label address by adding the constant from the map file to the memory origin of your code.

The built-in relocator routine of Mpm is as follows (source code of the relocator routine, “relocate.asm”, is available as part of Mpm source package):

; ************************************************************************************************** ; ; MMMMM MMMMM PPPPPPPPPPPPP MMMMM MMMMM ; MMMMMM MMMMMM PPPPPPPPPPPPPPP MMMMMM MMMMMM ; MMMMMMMMMMMMMMM PPPP PPPP MMMMMMMMMMMMMMM ; MMMM MMMMM MMMM PPPPPPPPPPPP MMMM MMMMM MMMM ; MMMM MMMM PPPP MMMM MMMM ; MMMM MMMM PPPP MMMM MMMM ; MMMMMM MMMMMM PPPPPP MMMMMM MMMMMM ; ; ZZZZZZZZZZZZZZ 888888888888 000000000 ; ZZZZZZZZZZZZZZ 8888888888888888 0000000000000 ; ZZZZ 8888 8888 0000 0000 ; ZZZZ 888888888888 0000 0000 ; ZZZZ 8888 8888 0000 0000 ; ZZZZZZZZZZZZZZ 8888888888888888 0000000000000 ; ZZZZZZZZZZZZZZ 888888888888 000000000 ; ; ; Copyright (C) 1991-2006, Gunther Strube, [email protected] ; ; This file is part of Mpm. ; Mpm is free software; you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by the Free Software Foundation; ; either version 2, or (at your option) any later version. ; Mpm is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ; See the GNU General Public License for more details. ; You should have received a copy of the GNU General Public License along with Mpm; ; see the file COPYING. If not, write to the ; Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ; ; ; **************************************************************************************************

MODULE relocator

XDEF relocator, SIZEOF_relocator

; ************************************************************************************************** ; ; This routine will relocate a machine code program. ; A relocation table is placed immediatly after the relocation routine. ; ; The program that is to be relocated and executed are placed immediately ; after the relocation table. ; ; The relocation routine expects IY to point at the start address, entry ; of the relocater. The relocater then calculates the correct origin for ; the relocated program. The BBC BASIC on the Z88 also setups the IY register ; during a BBC BASIC CALL command to execute local machine code.

24

; ; After completed relocation, the entry of the relocater is patched to ; JP which jumps directly to the executing program, if the relocated ; code is called again. ; ; The following registers are affected by the initial relocation process: ; AFBCDEHL/IX../...... same ; ...... /..IY/afbcdehl different ; ; As indicated above the outside world cannot use the alternate registers ; as parameter interface to the relocated program - they are smashed by the ; relocater. ; .relocator ex af,af' ; preserve AF exx ; preserve BC, DE, HL push iy pop hl ld bc, #end_relocator-relocator

add hl,bc ; absolute address of relocation table

ld e,(hl) inc hl ld d,(hl) push de ; DE = total of relocation offset elements inc hl ld c,(hl) inc hl ld b,(hl) ; total size of relocation offset elements inc hl push hl ; preserve pointer to first relocation offset element add hl,bc ld b,h ; HL = pointer to current relocation address ld c,l ; BC = program ORG, first byte of program

.relocate_loop ex (sp),hl ; HL = pointer to relocation offset element ld a,(hl) inc hl ; ready for next relocation offset pointer or a jr nz, byte_offset .extended_offset ld e,(hl) inc hl ld d,(hl) ; DE = extended offset pointer to next relocation address inc hl ; ready for next relocation offset pointer jr relocate_address

.byte_offset ld d,0 ld e,a ; offset pointer to next relocation address .relocate_address ex (sp),hl ; HL = pointer to current relocation address add hl,de ; new pointer at memory that contains relocation address ld e,(hl) inc hl ld d,(hl) ex de,hl add hl,bc ; HL = address relocated to program ORG in BC ex de,hl ld (hl),d dec hl ld (hl),e ; update relocated address back to memory

pop de ; DE = pointer to relocation offset ex (sp),hl ; HL = index counter dec hl ; update index counter ld a,h or l ; all addresses relocated? ex (sp),hl ; index counter back on stack push de ; pointer to relocation offset back on stack jr nz, relocate_loop pop af pop af ; remove redundant variables

; relocation of program completed. Patch the entry of the relocater to JP that ; jumps directly to the executing program, if the loaded program is executed again. ; Finish with restoring main registers and then execute program. ; .relocation_finished ld (iy+0),$C3 ld (iy+1),c ld (iy+2),b ; patch entry to JP , the relocated program exx ; swap back to main BC, DE, HL ex af,af' ; and main AF jp (iy) ; execute relocated program... .end_relocator

DEFC SIZEOF_relocator = end_relocator - relocator

; ************************************************************************************************** ; ; The relocation table is placed here by the Mpm assembler. ; The format of the generated table is: ; ; total_elements ds.w 1 ; sizeof_table ds.w 1 ; patchpointer_0 ds.b 1 --+ ; patchpointer_1 ds.b 1 | ; .... | sizeof_table

25

; .... | ; patchpointer_n ds.b 1 --+ ; ; The first patch pointer is an offset from the start of the program (.routine) ; to the first position of a location that contains a relocatable address. ; The following patchpointers are relative offsets from the current relocated ; address to the next. ; If the offset distance is larger than 255 bytes between two relocatable ; addresses, the following patchpointer is used: ; ; 0,<16bit patchpointer> ; ; which denotes the an offset from the current relocated address to the next. ; The 16 bit patch pointer is stored in the low byte, high byte order. ;

.routine ; the machine code to be relocated is placed immediately after the relocation table

26

12 Appendix 12.1 Mpm Object file format The structure of the object file format is designed exclusively for the Mpm. However, it may be useful for other programmers if they wish to use the file format for other purposes. We have included the documentation of the object file structure here. We hope to have designed a simple and straightforward file format. The documentation may be necessary if you want to use the object file format in other tools.

The primary aim of the design has been to maintain structure simplicity and load efficiency during link processing.

The format of the object file is as follows:

0 [ 'MPMRMF01' ] ​ ​ ​ ​ [ File pointer to ] [ File pointer to ] [ File pointer to ] [ File pointer to ] [ File pointer to ]

[ ] [ ... ]

[ ] [ ... ]

[ ] [ ... ]

[ ] [ ] n

The 0 (null) - defines start to total of bytes file length. The above figure has ​ ​ ​ ​ deliberately been split into sections to clarify the file structure, although there is no actual physical separation between the sections in the file; each section is immediately followed by the next.

The file pointers are 32 bit integers stored in low byte - high byte order (Little endian format - Intel notation).

‘MPMRMF01’ watermark ​ The first 8 bytes of any object file begins with this watermark. RMF is the acronym for Relocatable Module Format. This object file format is version ‘01’.

Contains the 32bit ORG address for the linked machine code or FFFFFFFFh for no ORG address defined.

Contains the following:

defines the resulting evaluation type range: ​ 'U': 8 bit integer (0 to 255) 'S': 8 bit signed integer (-128 to 127) 'C': 16 bit integer (-32768 to 65535) 'L': 32 bit signed integer

27

defines the 32 bit relative module code patch pointer to store result. ​ defines byte length of infix expression string. ​ contains the infix expression parsed from the source file. ​

Contains the following:

defines the scope of the name: ​ 'L' is local, 'G' is global, 'X' external library

defines whether it is a: ​ 'A' relocatable address, 'C' a constant'

defines a 32 bit integer (little endian format) ​ defines length byte of the following string. ​ ​ ​

Contains the following which defines library reference names: defines length byte of the following string. ​ ​ ​

Contains a preceding length byte, followed by string

Contains a preceding 32 bit integer identifying the total length of the following machine code block.

12.2Mpm Library file format ​ T.B.D

12.3The standard platform identifier symbol When the Mpm Assembler is running, a standard platform identifier (with value 1) is available. This is very useful, typically for conditional assembly (using IF directives) or other expressions. The identifier reflects the name of the platform:

"MSDOS" - the assembler is running on the MS-DOS or Windows platform of computers "UNIX" - the assembler is running on one of the LINUX/UNIX/MAC OSX platform.

The identifier might be very handy when you need you need to consider platform-specificness in your source code.

28