Classic Computer Magazine Archive ANTIC VOL. 8, NO. 3 / JULY 1989

Machine Language Stringer

Save 7 seconds on each BASIC subroutine.

By Andy Barton

Machine Language Stringer takes machine language object code and converts it into string format for use in your own BASIC programs. This BASIC program works on Atari 8-bit computers with at least 48K memory and disk drive.

Most machine language routines in BASIC programs are in the form of string data. This is done partly because strings take up less space than numerical DATA statements. They frequently don't need to be POKEd into a memory location.

When I tried translating a machine language routine in one of my programs into string format, I discovered the best reason for using strings. The string format virtually eliminated the seven seconds used to READ the 144 bytes of data and POKE them onto page 6. I was sold. I dearly hate to wait for slow computers.

I developed Machine Language Stringer to do the near-impossible manual task of taking the object code file of a machine language program (the executable code) and converting it into a set of BASIC program lines that will produce the proper string data.

GETTING STARTED

Type in Listing 1, STRDAT.BAS, and check it with TYPO II. Be sure to SAVE a copy to disk before you RUN it.

If you have difficulty typing the special characters in Line 460, don't type them in. Instead, type Listing 2, check it with TYPO II and SAVE a copy. When you RUN Listing 2, it creates these hard-to-type lines and stores them in a file called LINES.LST

To merge the two programs, LOAD "D:STRDAT.BAS" and then ENTER "D:LINES.LST." Remember to SAVE the completed program before you RUN it.

When you RUN the program, you will be asked for the object file name. If you forget the "D:" or the name is not found you will be asked again. Next you are asked for a starting line number. Be sure you choose one that will not overlap lines in your BASIC program or in this one.

Finally, you are asked for a name for the machine language string (maximum of 2 characters). The program will add a numerical extender to this name, starting with 1. The program will now go about the business of reading the object file and building the BASIC line(s) that will be incorporated into this program using Atari's forced read mode.

When the program is done, there are three more steps for you to take to incorporate the string into your basic program.

1. LIST the new lines to a disk/cassette file, for example:

LIST "D1YOURPRG.STR";l000, 1005.

2. LOAD your BASIC program and ENTER the string data file, for example:

ENTER "D1:YOURPRG.STR".

3. Make a USR comand to run the ML string.

PROGRAM NOTES

There are two numbers that cannot be displayed in a string-34 and 155. 34 is ASCII for a quotation mark and 155 is ASCII for a carriage return (return key). This program handles this problem by creating a separate line that inserts the number into its proper place in the string, for example:

1001 MLl$(72,72)=CHR$(155).

There are two types of machine language programs, ones that are fully relocatable and ones that are fixed at a particular memory location. Jump (JMP) and jump subroutine (JSR) comands use absolute rather than relative addressing and thus require the program to be at the specific location to which it was assembled.

Machine language Stringer accommodates this by creating a final BASIC line which provides a brief machine language string to move the string data to the memory location indicated by the object file, for example:

1006 X=USR(ADR("hh..."), FROM , TO , NO. BYTES)

This line is provided regardless of which type of machine language program you wrote. If your program is fully relocatable, this line can be deleted.

It is possible to create a program that is loaded into two or more separate memory locations. For example, a section of subroutines could be fixed onto page 6 and the main program could be totally relocatable. Machine language Stringer accomodates this by using the numeric extender mentioned above. Each time a new load address is indicated in the object file, the extender is increased by one, creating a new string name. Each string is provided with its own loader.

As mentioned above, for a program to be relocatable it cannot use absolute addressing with jump instructions. I have found no way around this problem with subroutines other then placing them on Page 6 or some other safe, fixed location.

However, there are two tricks I have discovered for JMP instructions. The problem arises when I would use a branch instruction, but find that its range (126 bytes) was too short so I would be forced to use a JMP instrution. The first crude but effective solution involves setting up intermediate branches to one or more areas within range, but outside the flow of the program. Here is an example:

LOOP  LDY #0
PART1 LDA ($D0),Y
      ...
      BEQ PART1
      BNE PART2 ;BRANCHES OVER
BP1   BCS LOOP  ;INTER:MEDLATE BRANCH
PART2 ASL A
      ...
      SEC       ;SET CARRY TO
      BCS BPl   ;FORCE A BRANCH

The second solution is more versatile, using the indirect jump instruction JMP(XXXX). It involves passing the address of the relocateable ML string to the ML program in BASIC's USR command. The ML program then figures the relative distance from the start of the program to the targeted instruction, adds this to the starting address of the string and saves the results on page 6 for the JMP(XXXX) to use. Here are two examples, first in BASIC:

X = USR(ADR(ML$),ADR(ML$))

In ML, this would be:

    IJP1 = $600 ;SAFE STORAGE FOR
    IJP2 = $602 ;INDIRECT JUMP ADDRESS
START * = $5600
      PLA
      PLA ;HI BYTE OF ADDRESS OF ML STRING
      TAX
      PLA ;LOW BYTE OF ADDRESS
      TAY ;SAVE IF MORE THEN ONE JUMP TARGET ;NEEDED
      CLC
      ADC #<TARG1-START
          ;ADD LOW BYTE OF TARGET ADDRESS OFFSET TO ML STRING ADDRESS
      STA IJP1
      TXA
      ADC #>TARG1-START ;ADD HI BYTES
      STA IJPl+1
      TYA ;GET LOW BYTE ;STRING ADDRESS
      CLC ;FOR SECOND TARGET
      ADC #<TARG2-START
      ... ;etc.
TARG1 SEC ;SOMEWHERE IN MAIN PROG.
      ...
      ...
      JMP(IJP1)

You may have to modify the program to get it to work with character set files. This program strips the first two control characters from the file, so you would end up with 1022 instead of 1024 bytes in your character set files.

As always, whenever modifying your programs you should first make backups of the originals, in case problems arise.


Andy Barton has been a regular contributor to Antic since 1984. His machine language game, Exwall, is this month's Super Disk Bonus.

Listing 1: STRDAT.BAS Download

Listing 2: LINES.BAS (not needed)