Using The Assembler Language 05

By Roy Warner

Originally published in EUG #07

Load the program. It needs to be Lines 10 to 160 plus PROCprt and PROCdata. It is saved on this disk as "U.7USING1".

       10MODE6:HIMEM=&5800
       20PROCconstants
       30PROCdata
       40PROCprt
       50CALLgo
       90END
       95:
      100DEFPROCconstants
      110base%=HIMEM+1
      150ENDPROC
      160:
      180DEFPROCprt
      190FOR pass=0TO3STEP3
      200P%=base%:[OPT pass
      240.go:LDX#0
      250.loop:LDAdata,X:JSR&FFEE
      260INX:CMP#0:BNEloop
      270RTS
      280]:NEXT:base%=P%+1
      290ENDPROC
      295:
      300DEFPROCdata
      310FOR pass=0TO3STEP3
      320P%=base%:[OPT pass
      330.data
      340EQUS"my string"
      350EQUB13
      360EQUB10
      370EQUB0
      640]:NEXT
      650base%=P%+1
      660ENDPROC

The program is in four clearly defined parts: 1) lines 10 to 95, 2) lines 100 to 160, 3) lines 180 to 295 and 4) lines 300 to 660.

Each of the parts, one to four, are to be *SPOOLed as "prog", "cons", "print" and "data". If using tape, be careful not to overwrite an earlier file.

Change the following lines:

       10MODE4:HIMEM=&4000
       30PROCprt
       40PROCdata
       50CALLscrn1

and RENUMBER 1,1. *SPOOL lines 1 to 7 as "prog" then DELETE 1,7 (RETURN), RENUMBER 10,10 and add the line 25temp=&70.

Now RENUMBER 100,1 and *SPOOL lines 100 to 104 as "cons" then DELETE 100,104. RENUMBER 200,10 then change the following lines:

      230.prt
      240LDA#ASC"A":JSR&FFEE

Delete 250 and RENUMBER 200,1. Now *SPOOL lines 200,208 as "prin1" and DELETE 200,208 (RETURN). RENUMBER 300,10, change line 330 and add 335:

      330.scrn1
      335JSRprt:JMPexit

Now change line 370 to:

      370EQUB&FF

Add a line:

      375.exit:RTS

RENUMBER 300,1 and *SPOOL as "data".

*EXEC each back in turn to remake the program [which is kept on this disk as "U.7USING2"]. RUN the program and it should clear the screen, assemble, print a capital A and then return to BASIC. If it does, then the structure is correct.

Sequence is:- line 5 CALLs scrn1 at line 303, line 304 Jumps SubRoutine prt at line 203, line 204 prints the A; line 205 Returns to SubRoutine (Line 304) and the next command is to JMPexit at line 309 where "exit" is followed by an RTS which returns the program to BASIC.

If it does not do that, then check your editing.

Once satisfied, do not RENUMBER or alter any line numbers. Type NEW and press RETURN.

Prin1 is to be edited so that other routines wishing to output to the screen may jump to it by means of the JSR instruction.

The command JSR pokes the Program Counter onto the stack, RTS pulls that value from the stack thereby returning to the correct place in the program. We shall utilise that series of events. Post indexed addressing is used to find the text to be printed, further, so as to be able to cope with large blocks of text and/or VDU commands. The limitation of a count restricted to 256 is overcome.

*EXEC prin1 and alter to the following; then *SPOOL as prin2.

      200DEFPROCprt
      201FORpass=0TO3STEP3
      202P%=base%
      203[OPT pass
      204.prt
      205LDA:STAtemp:PLA:STAtemp+1
      206LDY#0:BEQprt2
      207.prt1:LDA(temp),Y:CMP#&FF
      208BEQprt3:JSR&FFE3
      209.prt2:INCtemp:BNEprt1
      210INCtemp+1:BNEprt1
      211.prt3
      212LDAtemp+1:PHA:LDAtemp:PHA
      213RTS
      214]:NEXT
      215base%=P%+1
      216ENDPROC

At lines 205 and 212 the STACK is used. Post indexed addressing is at line 207. Lines 209 and 210 do the counting.

The Stack will be dealt with now, the remainder in a later article.

The Stack - What is it and what does it do?

The stack is a storage area that extends from address &100 to &1FF. The Electron Operating System uses it to store data when it RUNs your programs, so it should be used with care. The first rule is: it is a "Last In First Out" store.

The second rule is: if you pull any data for your use, push it back as soon as it is finished with.

A stack is best illustrated with a demo. Try this ("U.7DEMO"):

       10DIM stack%40
       20ptr%=stack%
       30FOR i%=1 TO 10
       40PRINT"Give me a Letter"
       50a=GET
       60!ptr%=a
       70ptr%=ptr%+4
       80NEXT
       90FOR i%=1 TO 10
      100ptr%=ptr%-4
      110VDU!ptr%
      120NEXT

(It is not error trapped so be sure only letter keys are typed!)

Run it and type "Roy Warner" or "Will Watts". That is a FILO stack. I did know how to spell words backwards, but it would have spoilt the demo!

That is the bare bones of a stack; the variable ptr% (short for pointer) moves up and down the stack in blocks of four, because as we all know in Acorn BASIC an integer number uses four bytes of storage space!

The Electron's stack in page one is very similar to our byte array "stack%", except that it stores the data a byte at a time, the stack pointer is set initially to &1FF, a byte is pushed onto the stack and the pointer decrements to the next empty address. Push a byte from the stack and the pointer increments to the last used address and the data is copied.

Taking data from a stack does not erase it, incoming data overwrites the old. The mechanics of stack manipulation do not interest us. Some 6502 experts advocate using the lower end of the stack as programmer's temporary storage area. Well don't! Acorn's programmers use the bottom of the stack for storing error messages!

A JSR will push the program counter value onto the stack. The value is greater than 256 so it is stored in two bytes; that is, the program counter DIV 256 and the program counter MOD 256. The DIV result is the high byte and the MOD result the low byte. The data is stored on the stack from the top downwards so the high byte goes on first then the low byte.

PLA "PulLA" takes a byte off the stack and puts it in the accumulator. PHA "PusHA" puts the byte in the accumulator onto the stack.

At line 304 ("U.7USIN2"), the JSR pushes the program counter value onto the stack. Line 205: the first PLA puts the low byte of the program counter into the accumulator then STA puts it into "temp". The second PLA and STA stores the high byte in "temp+1".

The two-byte program counter value of JSRprt is now stored in zero page at &70 and &71. That is almost right but the value we need is the next one where the "m" of "my string" is stored, so line 206 forces a branch to "prt2" where the content of &70 is incremented.

By post indexing the data "my string" is fed into the accumulator and printed. The address in temp is upcounted by lines 209 and 210.

The delimiter &FF forces a branch to "prt3" at line 211. The value in "temp+1" (high byte) is put back onto the stack and the stack pointer decremented by the PHA command. The next PHA puts the low byte from "temp" into the next address. RTS at line 213 pulls the data off the stack and "pops" it into the program counter. The program resumes at the address following the delimiter &FF.

Put the procedures together with a few *EXECs and remove the JMPexit from line 304. SAVE it then RUN it. The program prints the text and jumps over "my string" and the EQUB13, EQUB10 and EQUB&FF to the label "exit" and via the next RTS back to BASIC.

Experiment by adding after the .JSRprt at line 304, the following

      :EQUB12:EQUB31:EQUB4:EQUB10

RUN and there is now control of the output (VDU12,31,4,10).

Plenty of time to the next issue so why not have a shot at a reverse colour, text window. In their own procedures, of course. Part Four Operating System CALL was JSR&FFE3. Each time it meets a carriage return it adds a NewLine character.

Roy Warner, EUG #7