These notes are about using an Electron for Assembly Language and BASIC. If your wish is fame and fortune as the definitive 6502 machine code programmer, then read no further. An Electron is a good "value for money" home computer, it is not an Apple Mac.
Minimum equipment required is a basic Electron and tape recorder; given that statement it should be appreciated that the articles will touch on matters related to expansions. A good investment would be the Advanced User Guide, the best investment is to be prepared to read it and the standard User Guide.
Over the next few months a text type program will be written. The method is important, the program incidental. An assembly listing with routines in procedures will demonstrate that assembler need not be difficult to follow and modify.
Efficient programs may be written using a limited number of "commands". The Advanced User Guide shows how to access code written by Acorn's programmers; that code will be used.
Upon RUN, each line of a BASIC program is separately altered into code the micro processor can understand and process. When an assembler program is RUN the assembly language converts it to a block of machine code. To activate that machine code, program control is passed to the entry point by the instruction CALL. Consequently, machine code is faster and consumes less memory.
Acorn BASIC and Assembler interface each with the other to advantage, but BASIC will trample all over machine code, so a safe area must be created for the machine code - like this:-
10MODE6:HIMEM=&5000 20base=HIMEM+1
There is now an area below screen memory and above HIMEM which BASIC cannot impinge upon. Now type:
200P%=base:[OPT3 330EQUS"my string" 340EQUB13 640RTS:]
P% tells the assembler where to start the machine code, the square bracket starts the assembler language, OPT3 tells the assembler to assemble with error reports. EQUS is not a command, it is a statement (Page 149 of the User Guide describes it). When the assembler encounters this statement, a "string" is converted to ASCII character codes and inserted into the machine code. RTS is a command which starts for Return To Subroutine; in this instance it should return the program to BASIC. The reverse square bracket tells the assembler that the listing is complete. Now CALL base and the cat strikes!, dead pigeons abound! The EQUS statement inserts ASCII character codes prior to the machine code RTS.
If CALLed, the first ASCII character code is passed to the accumulator as a machine code command, but it is not a machine code command; the accumulator cannot process it. The program "hangs", this can be seen by a dead cursor. It is a plain line - not flashing. The only way out is the BREAK key then OLD, LIST. With luck the work is not lost, but it is only luck! Moral? Always save the first listing before RUNning it! That first listing is known as the source code. The machine code generated by assembling the source code is called the object code.
There are four statements that will store data in machine code, namely:
- EQUS
- EQUB
- EQUW, and
- EQUD
We shall use all four as time goes by, but data must never be allowed to enter the accumulator as machine code commands. In simple assembler an RTS or similar command should be used as a barrier. By use of the stack it is possible to leapfrog over such data. Should anyone be clever enough to enter machine code by the use of EQUB, EQUW and EQUD then I comment that this is assembly programming and not pure machine coding. Debug the listing by inserting a line:
320RTS
and edit the RTS out of line 640. Now it may be RUN but do not CALL it. Type PRINT$&5002 and press RETURN. The result should be the printout "my string". Also try PRINT$(base+1) - the result should be the same. Note: base is a BASIC variable but it has a known position in the machine code listing. Type the following as one line and then RETURN:
FOR a=&5001 TO &500B:PRINT"&";a;"="?a:NEXT
The output should be a list of hex addresses with the ASCII codes of the string. Note the 13, the code for RETURN (EQUB13). The odd number is 96, try a PRINT~96, the result will be 60, the hex number that tells a machine code program to Return To Subroutine (RTS).
Decimal 96 is ASCII code for the pound sign, but the program did not hang. Assembler commands are fed into the accumulator as numbers, the numbers activate logic gates within the micro processor. This determines whether the accumulator requires data or a further command. RTS does not need data, so the accumulator exits to the calling routine or language. Allowing pure data statements into the accumulator, if followed by a legal command or data may result in (Acorn's famous term for mayhem), "undefined results".
The User Guide uses a form of DIM statement to protect machine code. It is called a byte array. Some books on assembler advocate moving PAGE or HIMEM to provide a safe area. My advice is do not try to use these areas. Set HIMEM then declare the start of the code as in lines 10 and 20. P% may be treated as the program counter, it is not; the program counter is one of the registers of the Electron, but P% expresses the program counter in a way we can understand. P% increments with each command or byte of data. After a source listing has been run, typing in PRINT~(P%+2) will print the last address used plus two to the screen.
A *SAVE filename 5001 <num> (num being the result of PRINT~(P%+2)) will SAVE the machine code.
OPT will be looked at again in the next article. The important things we saw this time were:
The use of EQUS and EQUB, these statements "poked" data into memory. It can be read by BASIC indirection commands such as $, ? or !, base, a BASIC variable actually sets the start of the machine code.
Next time, our program will be enhanced by a simple print routine that will print the string "my string" on screen.
Roy Warner, EUG #3