Pascal-M Compiler Linker Disassembler Loader system
Hans Otten, November 2021 Version 0.9
Applicable license: MIT license. Permission given by Mark Rustad.
Note that this version is still beta quality! Your feedback is appreciated!
- How the Pascal-M system works
- How to use
- Pascal-M limitations
- Command Line versions
- Memory layout
- The debugger
- Build from sources
- Port to other systems
- History and Introduction
- Eror messages from the compiler
How the Pascal-M system works
The Pascal-M system will let you write Pascal programs and execute them on the 6502, e.g. the KIM-1 or the console of the PC.
The Pascal dialect is standard Pascal (no reals for example) as described in the second edition of ‘The Pascal User Manual and Report’. It can (could in older versions!) compile itself.
To get a Pascal program running on the KIM-1 the Pascal-M 2K1 system requires the following steps.
- Edit Write the text of the Pascal program
- Compile Repeat 1 and 2 until no compilation errors
- Load Convert the object M-code of the compiler output to binary code
- Link Combine the compiled binary and the 6502 interpreter to an executable KIM-1 program
- Run Load the Papertape file on the KIM-1 and run it
How to use
Step 1: Write a Pascal program with any text editor on your PC, create ASCII text files.
Save the Pascal source with extension .pas, and keep the editor open. I use Notepad++ on Windows, any editor will do.
Step 2 – 4: Start the PascalM2K1 program, a GUI program, and fill in the name of the Pascal source.
Press Compile and if the Pascal-M compiler sees no errors goto step 3 and press Load else go back to the editor.
Note the load address is needed to tell where the code should go in memory, the default is fine for now.
See the section on ‘Memory layout’.
Step 4 requires to fill in the name of the binary of the 6502 interpreter (default pascalmint2k1.bin, make sure it is found).
Also fill in the name you want for the 6502 program (Binary, a papertape version is produced also).
Fill in the upper memory RAM limit in your KIM-1. the default is for 32K RAM above $2000, max is $9FFF.
Step 5: Take the papertape file via a terminal emulator to the KIM-1 (in TTY mode) and run it from start address $2000
The example file test.pas contains the source:
program ctest ; begin writeln('hello world') ; end.
During the steps of PascalM2k1 many files are produced. If for example you start with helloworld.pas and finally link to runhelloworld.bin the following files will be present:
- helloworld.pas The Pascal source program you have written
- helloworld.lst Listing of the source program with compilation results
- helloworld.obp Px code representation of the Mcode
- helloworld.err Every step produces a file with the status, error or success.
Also shown in the status field in PascalM2k1
- helloworld.bin The Mcode loaded into a binary
- helloworld.prc The Procedure table binary
- helloworld.dlst The disassembled Mcode, see the Debug section
- runhelloworld.bin The runnable program binary
- runhelloworld.pap The MOS papertape version of he runnable program.
Command Line Utilities
The steps described above for PascalM2k1 can also be done with command line utilities. No argument given will prompt for answers.
Help given with -h. Functionality and steps identical to the PascalM2K1 program. Same files produced.
- cpascalm2k1.exe Pascal-M compiler V2k1
cpascalm2k1 <sourcefile> [V]
produces sourcefile.err (status) and sourcefile.obp (object) files
V shows errors on console
- cpascalmload.exe Loader for Pascal-M 2K1
cpascalmload <objectfile>[<loadaddress in hex>]
- cpascalmlinker.exe Pascal-M linker 2K1
cpascalmlinker <binfile from loader> <start adress> <interpreter binary><binary startaddres> <linked program file> <upper memory>
- cpascalmdis.exeDisassembler for Pascal-M 2K1, see the Debug section
cpascalmdis <objectfile> <loadaddress in hex>
Pascal-M is close to standard Pascal, but there are limits due to the P2 origin (close to the second ‘Pascal User Manual and Report’,
recommended as description for Pascal-M) and the limitations to make a small compiler for an 8 bit target.
When you read the compiler source (pascalmcompiler.inc) you will see it is a real language, and can compile itself
(if you strip all enhancements made by me, see SMPASCAL.PAS on the website for the last version that compiles on the KIM-1!)).
This list sums up the important limitations:
- Identifiers are unique in the first 8 characters
- No reals
- Only text files (7 max)
- 16 bit integers
- max store size 32768 bytes
- set max 63 members
- max 100 procedures/functions, call depth max 12
A Pascal-M program requires RAM from $2000 and up.
The upper limit is variable and can be maximum $DFFF.
The memory layout of a Pascal-M 2K1 system is:
Interpreter start $2000 - $2F00 : Pascal-M 6502 interpreter $2F00 - $2FFF : procedure buffer Load address $3000 - + size of M-code&quot; M-code . . heap growing up . . stack growing down - $9FFF = Upper memory (can be $DFFF for a 48K system)
The interpreter starts at $2000, point the monitor there and Go. After the Jump the memory layout is found: first location of M-code (default $3000), end of memory (default $9FFF) and end of M-code/start of heap (dependent on the size of the M-code).
The linker fills these addresses.
Console interpreter and debugger
cpascalmint2k1.exe is a command line Mcode interpreter and debugger.
pascalmint2k1 [<name of Mcode object>] [debug]
Without the optional debug parameter the Mcode program is executed:
D:\myfiles\development\PascalM\PascalM2k1\pascal interpreter&gt;pascalmint2k1.exe test.obp hello world
With the debug parameter a command line drive debugger is started. Use also the Mcode disassembly output to see what is happening in the Mcode machine.
D:\pascalmint2k1.exe test.obp debug Program ctest Loaded PC = 7CFC M-Debug &gt; ? Available debug commands : B = Breakpoint commands C = Show stack contents D = Display store E = Show stack contents G = Continue without debugger H = Show heappointer I = Insert in store M = Show markpointer N = Next instruction executed P = Show programcounter S = Show stackpointer T = Show procedure table X = Exit interpreter PC = 7CFC M-Debug &gt; B Break subcommand &gt; ? Available Break commands : C = Clear all breakpoints D = Show all breakpoints S = Set breakpoint Break subcommand &gt;
Compiling and building the programs from source
- A modern PC and operating system. Windows 10 is where the software has been developed, Raspberry OS /Linux have seen limited tested for now. MacOS may work, untested
- Development (Compile and run everywhere!) with Freepascal and Lazarus IDE (2.x) see https://www.lazarus-ide.org/
Any version above 2.0 will be OK, No OS dependent functions are used a.f.a.i.k.
- The archives with the KIM-1 Simulator sources PascalM2k1sources.zip (or higher version).
- Unpack in a folder, avoid blanks in folder and filenames
- Start the IDE by clicking on the relevant .lpi file.
- Build with Run – Build
The system is made up of main programs that ‘include’ the actual functionality. This way the command line utilities and the GUI pascalM2k1 share the code.
If a change is made to an .inc file both vcalling programs may need attention and tests.
No extra components are used, standard Lazarus will do.
Note that the ‘mode’ of the units is important, the compiler needs mode $delphi.
The 6502 interpreter is living in the folder 6502interpreter.
No special assembler syntax is used, TASM 32 bit for Windows command line is included.
tasm -65 pascalmint2k1.asm -b pascalmint2k1.bin TASM 6502 Assembler. Version 3.2 September, 2001. Copyright (C) 2001 Squak Valley Software tasm: pass 1 complete. tasm: pass 2 complete. tasm: Number of errors = 0
Port to other systems
The Pascal-M system is easy to port to other systems. Another 6502 system is quite easy, adaptations on the assembler source will be:
- Character I/O, replace the KIM TTY in/out (note the ‘echo’ adaptation, so no hardware echo on the KIM-1!) with the relevant character I/O routines of the new target
- Take look at the memory layout of the new target, adapt lower and upper memory address in use. It is possible to let the interpreter be independent in memory from the M-code.
The Pascal-m2K1 does not support this, you will have to manage the binary files and memory management in the interpreter yourself
Introduction and history
How I spent 40 years on getting so far ….
Pascal-M is the name of the Pascal compiler written by Mark Rustad, around 1977.
It was based (and mostly identical) to the portable P2 Pascal compiler, from the ETH Zurich group led by Niklaus Wirth.
The Px Pascal compilers are portable compiler-interpreters, quality compilers and easy to adapt interpreter to new hosts.
The adaptations by Mark Rustad were in the code production, the M-code is byte oriented and more efficient in memory demands.
File I/O was stripped as was floating point. Only chars, integers 16 bit and booleans. Uppercase only. Input/output was for a teletype, so input was either the keyboard or a HSR (High Speed Reader), output a printer or a HSP( High Speed Punch) via a software
Mark Rustad told me he ported the compiler to 6800 and 6809. G.J. van der Grinten did work on the interpreter part for the KIM-1 and wrote a 6502 interpreter.
The Micro Ade editor was adapted to produce Pascal text files.
In 1978 I received from the KIM Club in the Netherlands a version of this Pascal-M system, consisting of a KIM-1 tape with the compiler and interpreter and Micro Ade,
listings of the compiler (in Pascal), preliminary M-code description, the interpreter (in 6502 assembler) and the Micro Ade patches.
It was never made into a product for the KIM club, it was a nightmare to use. From entering text to running a program, all from audio cassette files, it took around an hour.
The old days of papertape and cards were gone already. But the time of cross-compiling or floppy drives connected to the KIM-1 was not there yet.
I got no further than a ‘Hello world’ program once and gave up.
In 1983 I started typing in the source on a PDP-11 with RSX-11M Pascal. And moved on to VAX/VMS with the excellent VMS Pascal. After some years I had the compiler, an interpreter
written in Pascal with debugger and the original 6502 interpreter on tape. This system produced for the second time, in 1986, a running ‘Hello world’ on the KIM-1.
I started expanding the compiler, bringing back P2 functionality like file handling, text files are now supported. Lowercase also. Bugs fixed.
But then I bought a CP/M system and the KIM-1 was put aside. Pascal-M forgotten for several years, Pascal compiler technology not.
I came back in MS-DOS times to the Pascal-M system with the compiler running as a Turbo Pascal (1994, 2003). Then Delphi arrived and the Pascal-M system was brought to live again as Delphi console applications.
In 2020 this was compiled in Freepascal, the compiler was cleaned up (and the original source restored also).
And now in 2021 a Lazarus shell around the steps required to produce a working program was programmed. The 6502 interpreter was finally assembled from source again.
Pressing a couple of buttons is now all it takes to produce a program running on the KIM-1 (and as console on the PC).
The command line utilities are refreshed also. So a ‘Hello World’ takes a a couple of minutes from source editing to running on the KIM-1 (Simulator).
The motivation for the KIM-1 Simulator was mostly for being able to test the Pascal-M system!
Error messages from the compiler
2 Syntax: identifier expected 3 Syntax: Program expected 4 Syntax: &quot;)&quot; expected 5 Syntax: &quot;:&quot; exepected 6 Syntax: illegal symbol 7 Syntax: actual parameter list 8 Syntax: OF expected 9 Syntax: &quot;(&quot; expected 10 Syntax: type specfication expected 11 Syntax: &quot;[&quot; expected 12 Syntax: &quot;]&quot; expected 13 Syntax: end expected 14 Syntax: &quot;;&quot; expected 15 Syntax: integer expected 16 Syntax: &quot;-&quot; expected 17 Syntax: begin expected 18 Syntax: error in declaration part 19 Syntax: error in field list 20 Syntax: &quot;,&quot; expected 21 Syntax: &quot;*&quot; expected 50 Syntax: &quot;error in constant 51 Syntax: &quot;:=&quot; expected 52 Syntax: then expected 53 Syntax: until expected 54 Syntax: do expected 55 Syntax: to/downto expected 56 Syntax: if expected 58 Syntax: ill-formed expression 59 Syntax: error in variable 101 Identifier declared twice 102 Low bound exceeds high-bound 103 Identifier is not a type identifier 104 Identifier not declared 105 Sign not allowed 106 Number expected 107 Incompatible subrange types 110 Tag type must be an ordinal type 111 Incompatible with tag type 113 Index type must be an ordinal type 115 Base type must be scalar or subrange 116 Error in type of procedure parameter 117 Unsatisfied forward reference 118 Forward reference type identifier 119 Forward declared : repetition par. list 120 Function result: scalar,subrange,pointer 122 Forward declared: repetition result type 123 Missing result type in function declar. 125 Error in type of standard function par. 126 Number of parameters disagrees with decl 129 Incompatible operands 130 Expression is not of SET type 131 Test on equality allowed only 132 Inclusion not allowed in set comparisons 134 Illegal type of operands 135 Boolean operands required 136 Set element must be scalar or subrange 137 Set element types not compatible 138 Type must be array 139 Index type is not compatible with decl. 140 Type must be record 141 Type must be pointer 142 Illegal parameter substitution 143 Illegal type of loop control variable 144 Illegal type of expression 145 Type conflict 147 Case label and case expression not comp. 148 Subrange bounds must be scalar 149 Index type must not be an integer 150 Assignment to standard function illegal 152 No such field in this record 154 Actual parameter must be a variable 155 Control variable declared interm. level 156 Value already as a label in CASE 157 Too many cases in CASE statement 160 Previous declaration was not forward 161 Again forward declared 169 SET element not in range 0 .. 63 170 String constant must not exceed one line 171 Integer constant exceeds range(32767) ' 172 Too many nested scopes of identifiers 173 Too many nested procedures/functions 174 Index expression out of bounds 175 Internal compiler error : standard funct 176 Illegal character found 177 Error in type 178 Illegal reference to variable 179 Internal error : wrong size variable 180 Maximum number of files exceeded