<< Home | About Forth | About TurboForth | Download | Language Reference | Resources | Tutorials | YouTube >>


Editor Assembler Option #3 Object Code Loader

Sometimes you may have a requirement to load assembly code in from disk for execution. It's not really necessary, because TurboForth includes an assembler, which makes writing assembly code as easy (and follows the same process) as writing Forth code. However, in the event that you do wish to load external machine code into memory from disk, the EA#3 loader is your friend.

Most TI-99/4A nerds will know that the TI-99/4A Assembler, supplied as part of the Editor/Assembler package, outputs machine code in a format called Tagged Object Code.

Tagged Object Code is a DF80 file that contains the machine code in readable ASCII, though it is in an assembled form; it is not in source-code form. Here's an example of a DF80 Tagged Object Code file:

00000        92000920029200492006B2008B04C0B04C6B020CB0024B30C07F366F       0001
92012B020CB0006B3606B04C1B0200B0100B0202B0008B020CB0024B30C07F333F 0002
92028B020CB0006B3601B0281BFF00B163DB0220B0100B0222B0008B02807F317F 0003
9203EB0600B16F0B0201B0100B2581B1603B0200B003DB100CB0A11B25817F30FF 0004
92054B1603B0200B0020B1012B0A11B2581B1623B0200B000DB100CB02017F341F 0005
9206AB1000B2581B1603B0200B0005B1005B0A11B2581B1602B0200B002B7F337F 0006
92080B8800B2004B1603B0720B2002B1004B0201B0001BC801B2002BC8007F33FF 0007
92096B2004B0644BC500BC820B2000B83D6B020CB8326B045CB0700B04C17F2D6F 0008
920ACB10F1B0200B0100B2440B1303B0A10B0582B10FBB0201B20FCB02007F2EEF 0009
920C2B1000B2580B1305B05C1B0A10B0280B8000B16F9BC051BA081BD0127F2DDF 0010
920D8B0980B0281B2134B13D0B0280B0061B11CDB0280B007AB15CAB04CC7F2AEF 0011
920EEB1E15B1F07B1D15B13C5B0220BFFE0B10C2B2164B2134B2194B21047F294F 0012
92104B3D20B0D00B0000B0000B2E6CB6F39B3273B7778B2C6BB6938B33647F2ABF 0013
9211AB6563B6D6AB7537B3466B7276B6E68B7936B3567B7462B2F3BB70307F280F 0014
92130B3161B717AB2B20B0DFFBFFFFBFFFFB3E4CB4F28B4053B5758B3C4B7F1DFF 0015
92146B492AB2344B4543B4D4AB5526B2446B5256B4E48B595EB2547B54427F2A1F 0016
9215CB2D3AB5029B2141B515AB3D20B0D00B0000B0000BB9C2B270FB04087F2B9F 0017
92172B7E0ABB8C1B3F06B0709B0B60BC3C0B5F01B027BB5B7FBC4BFBC60C7F20DF 0018
92188B0E7DB5DBEBBABDB22BCB037CBC55CB1D20B0DFFBFFFFBFFFFB1B0C7F14BF 0019
9219EB0F1FB1813B1718B000BB091EB1904B0503B0D0AB151DB1A06B12167F2A5F 0020
921B4B0E08B191CB1B07B1402B1B1CB1016B1701B111A7F5FFF 0021
62006KSCAN 62000VBLANK62002KSTAT 7F7E4F 0022
:Asm994a TMS99000 Assembler - v3.010 0023

The contents of the file is interpreted by a loader program. Tags in the file instruct the loader to do things, such as change the address that the next bit of code will be loaded to, etc.

For example, the tag 9 reserves the address following it, so that code is not written there. The tag B writes the following 4 digit hex value to the current loading address. The tag 7 (seen towards the end of the lines above) presents a 4 digit hex check-sum value immediately after it, and so on.

Tagged object code is very versatile. It allows, for example, re-locatable code to be loaded anywhere in memory. It is much more versatile than raw memory-image code, which is generally coded to run from a fixed address, though it is more expensive (i.e. slower) to load.

A simple Tagged Object Code loader is available for TurboForth on block 42 of the companion disk. Load it as follows:

   42 LOAD

Once loaded, it is invoked as follows:

   S" DSKn.filename" #3LOAD

The loader supports the most common tags, such that most assembled source code, assembled with the TI assembler, can be loaded.

At the assembler source code level, the following are supported:

The DEF Directive

DEF causes the loader to create a dictionary entry for the DEF'd word, so that it can be accessed from the Forth environment. The word produced acts like a variable, returning the address of the DEF'd word, as follows:

      AORG >3010
      DEF START    ; creates a word in the dictionary called START

START MOV *R4,R0

If the above code were assembled and loaded via the loader, executing START would not cause the code at START to be executed. Rather, it would return the address of the code beginning at the symbolic label START. So, if one executed the following code in Forth:

   START @ $.

It would display the op-code for the MOV instruction.

Calling Executable Code

Using the DEF directive in assembly source, it is possible to call machine code from the Forth side after it has been loaded from the loader. Recall that DEF'd labels cause words to be constructed in the dictionary which return an address. Therefore that address can be supplied to EXECUTE and the machine code will be executed. However, there is a gotcha. TurboForth uses the Indirect Threading Code (ITC) code method, and as such, a pointer to the machine code needs to be assembled, and the address of the pointer is given to EXECUTE.

Here is a complete example of code that can be assembled with the TI Editor/Assembler package, loaded as an option #3 file, and executed from TurboForth:

          AORG >2000
          DEF DOUBLE

   DOUBLE DATA MYCODE     * _pointer_ to executable code

   MYCODE A *R4,*R4       * add contents of stack to contents of stack
          B *R12          * Return to the TurboForth environment

The above code, when assembled and loaded through the loader, will double any value on the stack. It is called via EXECUTE, for example:

   99 DOUBLE EXECUTE .

TurboForth will duly display 198. An address should be given (using AORG ("absolute origin")) to tell the loader where to load the code. A good area is in the low memory expansion - 8K of RAM from >2000 to >3FFF. This area is, under normal circumstances, unused by TurboForth unless it is specifically told to compile code there.

Video of the Loader

An early video is shown below of the loader loading some machine code in from disk, and running that code from the Forth environment.

10th February 2012


<< Home | About Forth | About TurboForth | Download | Language Reference | Resources | Tutorials | YouTube >>