Using The Assembler 01

By Richard Dimond

Originally published in EUG #18

I have had the suggestion that I should write a BASIC compiler to make writing a machine code program easier. This was done with a program in Electron User (November 1986) but to me this was rather limiting and more confusing than using the assembler.

Also, it did not produce a very satisfactory m/code program. I have even had the idea suggested that it would be nice to write a program in BASIC that would re-write your program in m/code!! This would be very difficult and would also take up far too much memory!

I am not going to attempt to do either of these nor am I going to write a text book on the subject as there are many books available on it already!! These tend to be written in so much detail that they can be rather confusing and better regarded as reference books. For this reason I thought it might be helpful to give details of several routines which will show you how to do some of the BASIC things in m/code and give you a starting point on which you may experiment and learn how to make up simple programs in m/code.

I hope that this will help you to use the assembler and find that it is not so difficult to use as it may seem. I would suggest that you always SAVE the assembler listing before RUNning it as it is easy to slip up and make a mistake - I have learnt a lot from my own mistakes!!

I will assume such knowledge as given in the introduction to m/code in the User Guide and may make reference to these page numbers. However, if there is anything that is not clear to anyone, I will be glad to try and explain it in more detail.

Basically, m/coding is using the registers A, X and Y for storing numbers and manipulating them to perform the task required. There are routines in the computer's memory for doing certain tasks. These are the Operating System routines and for printing to the screen, we use OSWRCH (&FFEE), the Write Character routine. To use this we must load A register with the ASCII value of the character before we call this routine.

To demonstrate this type in:

      >P%=&900 (RETURN)
      >[LDA #ASC"A":JSR&FFEE:RTS (RETURN)
      >CALL&900 (RETURN)

P% is the address to which the code is assembled. This must be an address which BASIC does not use and &900 is usually convenient for short routines but I will discuss other options later. The code must always be preceded by the square bracket. On pressing RETURN, the code is listed and when the code is CALLed, the letter will be printed.

Note the use of the # sign (See page 206 of the manual). It is all too easy to forget this!! It can produce some peculiar results!

I have put the BASIC assembler listing on the disk together with the first routine on the disk and hope that you enjoy adding to this and experimenting. I will give a simple explanation of each routine and, where it is possible, an equivalent BASIC routine.

Do not RENUMBER the program. I have left spaces for you to add routines.

Sections

The sections are for:

  1. Main loop,
  2. Subroutines, and
  3. Data.

The first routine is for printing text to screen.

As it stands, the program will run but will simply list the code for the routine and return to BASIC as the only code in the main loop is the opcode RTS. This is the code for RETURN from subroutine and m/code must always end with this to return to BASIC.

The text that you want to print must be entered in the Data section in the form:-

      .text EQUS" <TEXT> "+CHR$&FF

EQUS tells the computer that a string follows and the CHR$FF signifies the end of the string. The label can be anything you like with the limits of a normal BASIC variable but must always start with a '.'

The address at which the text is stored must first be entered into the print routine.

To do this, you need to add in the main loop

      LDX#text MOD256   
      LDY#text DIV256    \ LoaDY with High byte of text address
      JSRprint           \ Jump SubRoutine

(The '\' is equivalent to REM in BASIC and is ignored - you need not type it, or the comments, in.)

The routine first STores the address into &70 and &71, a zero page address for post-index indirect addressing mode (See page 207 of the User Guide). Since Y register is then loaded with zero, A register is loaded from the address of the start of the string (text address + 0) and is printed to the screen with JSR &FFEE as explained above.

Y register is INCremented and the routine jumps back to the label .prtlp to point to the next character since the byte &FF has not been reached yet. When the string has been printed and A register loaded with &FF the CoMParison is met and the routine branches to the label .endprt and returns to the main loop. This returns to BASIC with the second RTS.

While other types of indexed addressing may be used for printing, the one used here enables you print out several different texts simply by loading the text addresses into &70 using a different label for each. Try adding further text data. For example, text1, text2.

You will see that all these are strung together. So the routine is like PRINT;"...."; as we have not told the computer to move onto a new line. This is done using OSNEWL (&FFE7). So add this after each time the print routine is called.

There is also another Operating System routine for printing to the screen which is a combination of the above routines. This is OSASCI (&FFE3). The difference is that loading A register with &0D (the carriage return value) with OSWRCH returns the print position of the same line not to the next line but with OSASCI it does.

Try entering:

      .text EQUS"<text>"+CHR$&0D+"<text>"+CHR$&FF
With OSWRCH, these will be printed on the same line - the second overprints the first. Now change &FFEE to &FFE3 in the print subroutine and run the program again. The text will then be correctly printed on two lines.

To indent text simply add spaces to the beginning of the beginning of the string but to print at any point of the screen, the equivalent of TAB(x,y) or VDU31,x,y is needed. As will be seen from the use of &0D with OSWRCH, the control codes and any data needed may be used also so that this becomes:

      LDA #31:JSR&FFEE:LDX #x:JSR&FFEE:LDY #y:JSR&FFEE
It is more convenient to make this into a subroutine:
      .tab LDA #31:JSR&FFEE:TXA:JSR&FFEE:TYA:JMP&FFEE
Add this routine in section 2 after the print routine. The last call to OSWRCH is a JMP instruction as the routine includes the RTS which returns to the main loop.

To use the routine, X and Y registers must be loaded with the x and y print co-ordinates in the main loop by:-

      LDX #x:LDY #y:JSRtab
The values are transferred to A register by TXA and TYA by the routine. Try this before calling the print routine.

If you want to underline a title or print a string of the same character, use this short routine in a similar way:

      .uline JSR&FFEE:DEX:BNEuline:RTS
A register should be loaded with the ASC value of the character and X register with the number of characters by:
      LDA #ASC"<char>":LDX #<no of chars>:JSRuline
Here X register is used as a counter and the routine repeats printing until X reaches zero. This is like the STRING$ routine in BASIC.

With similar routines as the above you may be able to make up routines for MODE, COLOUR, GCOL, CLS, and CLG.

I will be covering these and more next time. Keep experimenting!