Pascal-M 2k1

Pascal-M 2K1

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!
Contents

Downloads for Windows, Ubuntu and Raspberry PI OS:
Pascal-M 2K1 programs
Pascal-M 2K1 sources

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.

  1. Edit Write the text of the Pascal program
  2. Compile Repeat 1 and 2 until no compilation errors
  3. Load Convert the object M-code of the compiler output to binary code
  4. Link Combine the compiled binary and the 6502 interpreter to an executable KIM-1 program
  5. 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.
Press Link.
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.

You will only have to keep the helloworld.pas and the resulting program runhelloworld.bin and pap, the others can be made again.

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
    Syntax:
    cpascalm2k1 <sourcefile> [V]
    produces sourcefile.err (status) and sourcefile.obp (object) files
    V shows errors on console
  • cpascalmload.exe Loader for Pascal-M 2K1
    Syntax:
    cpascalmload <objectfile>[<loadaddress in hex>]
  • cpascalmlinker.exe Pascal-M linker 2K1
    Syntax:
    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
    Syntax:
    cpascalmdis <objectfile> <loadaddress in hex>


Pascal-M limitations

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

Memory layout

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
                  .
                  .
          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.
Syntax:
pascalmint2k1 [<name of Mcode object>] [debug]

Without the optional debug parameter the Mcode program is executed:

D:\myfiles\development\PascalM\PascalM2k1\pascal interpreter&amp;amp;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;
Break subcommand &gt;?

Available Break commands :

  C = Clear all breakpoints
  D = Show  all breakpoints
  S = Set breakpoint


Compiling and building the programs from source

Prerequisites

  • 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

will produce the pascalmint2k1.bin file required

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

Another platform is a bit more work. Use an assembler or compiler, the interpreter needs to be written for the new target. Take the Pascal interpreter as example, it is well documented.

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
switch.
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