.enter JSR initialise .restart JSR setupscreen .main JSR plotshapes JSR checkcollisions JSR keyboardscan JSR updatecoordinates JSR checkifdead BNE main loop DEC Iives BNE restart RTS
Although, at this stage, the subroutines have not been defined, it is obvious from their names what they are meant to do. The next task is to write these subroutines, again breaking them down into simpler routines if this is possible.
Since the main loop is the top level in the overall structure, this method is known as 'top-down' approach. Its advantage is that you know what you are aiming at right from the start. You shouldn't need any 'fixes' in the subroutines to make up for the fact that when you wrote them you didn't make them apply to all cases eventually required.
The alternative method is to start by writing the individual routines and then to add the code which joins them together into the final program. The advantage of this method is that all routines can be tested individually before very much effort has gone into the program. Consider how much time would be wasted if you used the first method and completed the whole program except for one routine which proved impossible to write in such a way that it performed satisfactorily.
In practice most people use a mixture of the two methods, so that any demanding routines are written first; then the top-level is written, followed by the rest of the program.
Control is passed to the address given after the CALL statement and any parameters following this address are put into the parameter block starting at &600. The parameter block is of the following format:
&600 | Number of parameters |
&601 | Parameter address (low byte) |
&602 | Parameter address (high byte) |
&603 | Parameter type |
&604 | Parameter address (low byte) |
Type 0 | 8-bit byte |
Type 4 | 32-bit word |
Type 5 | 40-bit floating point string |
Type 128 | ATOM string |
Type 129 | Microsoft string |
Start address of the string
Number of bytes allocated
Current length of string
An example of a CALL statement is
CALL enter,fred,A$
This would cause the machine code from 'enter' to be executed and the parameters 'fred' and 'AS' would be described in the parameter block as follows:
------------------------------------------------- | 02 | C7 | 0E | 05 | DO | 0E | 81 | ?? | ?? | ?? | ------------------------------------------------- 0600 0601 0602 0603 0604 0605 0606 0607 0608 0609
10 REM print hex digits 20 DIM code 100 30 oswrch = &FFEE 4O FOR pass = 0 TO 3 STEP 3 50 P% = code 60[OPT pass 70.enter CLC : ADC #&40 : ] 80 IF flag = FALSE [OPT pass : JSR debug : ] 90[OPT pass 100 BEQ exit : SBC #&10 : ] 110 IF flag = FALSE [OPT pass : JSR debug : ] 120 [OPT pass 130.exit RTS : ] 140 IF flag THEN 360 150[OPT pass 160 # print hex digits 170.print 180 AND #&0F Get bottom four bits 190 CMP #&0A if less then 10 then miss 200 BCC P% + 4 the next instruction 210 ADC #&06 Add 7 (6 + carry) 220 ADC #ASC"0 " ADD ADC (0) 230 JMP oswrch Write the character 240 # print A in hex 250.debug 260 PHA 270 PHA 280 LSR A Exchange top four bits 290 LSR A for bottom four bits 300 LSR A 310 LSR A 320 JSR print Print out first hex character 330 PLA 340 JSR print Print second hex character 350 PLA Restore original value of A 360 RTS Return 370] 38ONEXT pass
The program works by finding out whether or not the four bits corresponding to each hex digit represent a number less than ten. If it is less than ten then the value ASC ("0") is added and the character, which will be a number 0... 9 will be printed. If it is greater than or equal to ten then a number equivalent to ASC ("A-10") is added so that ten will be printed as A, eleven as B etc.
For debugging purposes this program is assembled by typing
15 flag = FALSE RUN
The program can then be executed for various values of A% by typing
A% = &12 : CALL enter
The final version of the program is assembled, without the debugging aids, by typing
15 flag = TRUE RUN
LDX #initial-lives
explains far better what is happening than
LDX #3
Using constants has another advantage - if a value needs to be changed and constants have been used, only the definition of the constant would need to be altered, rather than every occurrence of that value.
Some languages support constants and variables as totally different data types, and make it impossible to change the value of the constant. BASIC does not treat variables and constants differently (except for it's own constants, e.g. PI) and so it is up to the programmer to make sure that any constants defined retain their value. One convention used for this is to prefix all constants with a pound (£) sign as a reminder.
LDY index LDA table, Y
In this example the value of A is dependent upon the value of Y. The example consists of a table of values, starting at 'table'.
Note that the above assembler is directly equivalent to the BASIC 'A=table?index'.
The values in 'table' could be the values of a palette, for example
.table EQUB &3 # Colour 0 is yellow EQUB &1 # Colour 1 is red (default) EQUB &6 # Colour 2 is cyan etc.
Thus lookup tables should be used wherever it is necessary to produce a value from another value, but only when there is no simple realationship between the two.