A9 7E
Note that the data is stored in the memory as the byte directly after the command byte.
4A
8D 62 FE
8D 78 00
However, there is an addressing mode for just this sort of situation. By using ZERO PAGE ADDRESSING the processor knows we are using zero page and we only have to send one byte of data to the processor. Thus the example above becomes:
85 78
This means that if we store all our frequently used variables in zero page we can access then slightly faster and with a saving of one byte of program per command. The assembler does this automatically - if it is faced with an absolute addressing command with an address in zero page, it automatically uses zero page addressing.
9D 35 64
B9 00 09
85 7A
96 90
6C 30 02
61 70
91 84
For example, take the assembly code program:
LDX #&80 .loop DEX BNE loop RTS
If we assembled it at address &2000 onwards and then looked at it we would find the following:
Address byte 2000 A2 \ LDX # 2001 80 \ &80 2002 CA \ DEX 2003 D0 \ BNE relative 2004 FD \ &2002-&2005=-3=&FD 2005 60 \ RTS
(a branch backwards)
INC &70 BNE nocarry INC &71 .nocarry RTS
becomes:
Address byte 2000 E6 \ INC 2001 70 \ &70 2002 D0 \ BNE 2003 02 \ &2006-&2004=2 2004 E6 \ INC 2005 71 \ &71 2006 60 \ RTS
(a branch forwards).
Notice that the assembler OPT command has an option so that you can see an assembled listing of the code as it is assembled. This can be enabled by using OPT3 for the second pass. Below is the second of our example programs and the print-out it produces.
10 HIMEM=&2000 20 FOR pass%=0TO3 STEP3 30 P%=&2000 40 [OPT pass% 50 INC &70 60 BNE nocarry 70 INC &71 80 .nocarry RTS 90 ] 100 NEXT 2000 OPT pass% 2000 E6 70 INC &70 2002 D0 02 BNE nocarry 2004 E6 71 INC &71 2006 60 .nocarry RTS
78A0 01 20 E3 FF 20 E3 FF A9 78A8 00 A2 07 20 E3 FF CA D0 78B0 FA A9 04 A0 C0 4C F4 FF 78B8 C9 30 90 33 C9 3A 80 06 78C0 38 E9 30 4C D1 78 C9 41 78C8 90 25 C9 47 B0 21 38 E9 78D0 37 85 75 A4 74 B1 70 0A 78D8 0A 0A 0A 05 75 91 70 81 78E0 70 20 C2 79 A9 08 20 E3 78E8 FF 20 E3 FF 4C 61 78 C9 78F0 9F F0 19 C9 9C D0 63 20 78F8 23 7A C6 74 A5 74 C9 FF 7900 74 4C 0F 79 20 23 7A A9 7910 1F 20 E3 FF A9 00 20 E3 7918 FF 20 E3 FF A9 08 20 E3 7920 FF A5 70 38 E9 08 85 70 7928 A5 71 E9 00 85 71 A5 70 7930 38 E9 60 85 72 A5 71 E9 7938 00 85 73 20 DE 79 A9 1F 7940 20 E3 FF A9 00 20 E3 FF 7948 A9 18 20 E3 FF A9 20 A2 7950 27 20 E3 FF CA D0 FA 4C 7958 61 78 C9 9E F0 1D C9 32
We can also make the program more pleasant to use by making the addresses (at the extreme left) yellow and the data (the contents of the memory) green. We can then highlight the byte we are currently working on by making it white.
We are going to use the cursor keys and the shifted cursor keys for control of the cursor, so the first thing we need to do is set up the cursor keys to do this.
We could produce ASCII codes from the cursor keys using *FX4,1 but this will not distinguish between normal and shifted cursor keys. The way round this is to set up the cursor keys as soft keys and set them to generate ASCII codes. We do this with two commands. First, *FX4,2 sets up the cursor keys as soft keys 12 to 15. The shifted cursor keys will now automatically produce ASCII codes (from &8C to &8F) but the normal cursor keys will not. So, second, we make the normal cursor keys generate ASCII codes by setting the ASCII base of the normal function keys to &90 with *FX225,144. This means that instead of producing strings the soft keys will generate ASCII codes of &90 plus the key number, so that the normal cursor keys will now generate codes &9C to &9F. So the start of our machine code routine looks like this:
.monitor LDA #4 LDX #2 LDY #0 JSR osbyte LDA #&E1 LDX #&90 JSR osbyte (80-140)
Notice that we have used OSBYTE instead of &FFF4. To do this we must define the variable OSBYTE at the beginning of the assembler program. We are also going to use the OSASCI and OSRDCH routines so we can define these at the same time. We also need a place to put the machine code monitor program. For our purposes let's put it at &7900 and move HIMEM down to leave room for it. This will cause problems if you are writing a graphics program but it is easy, in that event, to change the program to assemble the machine code elsewhere in the memory.
So the beginning of the assembler routine looks like this:
10 HIMEM=&7900 20 osasci=&FFE3 30 osbyte=&FFF4 40 osrdch=&FFE0 50 FORpass%=0TO2STEP2 60 P%=&7900 70 [OPTpass%
Now back to the machine code. Our next task is to go into Mode 7 and turn the cursor off.
LDA #22 JSR osasci LDA #7 JSR osasci LDA #23 JSR osasci LDA #1 JSR osasci LDA #0 LDX #8 .loop1 JSR osasci DEX BNE loop1 (150-270)
Notice that the simple BASIC command VDU23,1,0;0;0;0; becomes quite complicated in machine code. The eight zeros are easier to send with a loop unlike in BASIC.
Next we must decide what memory address we are interested in displaying. It is convenient to set this to &0000 for the moment as it is easy to step through the memory to the location we are interested in. Because of the way we are going to display the table, we are going to be treating the memory as an array eight bytes across by 8192 bytes down.
It will be easier if we keep the address of the FIRST byte on the line we are looking at separate from the number of the byte (0-7) within that line.
Let's say &70 and &71 contain the address of the first byte on the line where the cursor is at present positioned and &74 contains the number of the byte on that line which we are interested in (0-7). Initially the address of the first byte on the line will be zero, so we can add to our program:
LDA #0 STA &70 STA &71 STA &74 (280-310)
Next we must display a screenful of memory - 24 lines of eight bytes each. It would be sensible to set up a routine which just prints one line (eight bytes) of memory, and use this repeatedly. However, before we can even do this we need a routine that will display the value of one byte as two hex digits. For this routine let us specify that the byte to be printed must initially be found in the accumulator. We will have to work on one nibble (half a byte) at a time, so we have to save the complete byte while we work on the first nibble in the accumulator. We can save the accumulator in &75. Next we can mask out the least significant nibble, leaving the most significant nibble in the accumulator (this will be the left-hand digit of the hex byte). We will then have to shift it right four times so that we get a number from zero to fifteen in the low nibble of the accumulator.
.byte STA &75 \ Display byte AND #&F0 \ in hex. LSR A LSR A LSR A LSR A (1990-2040)
Next we need to display this digit on the screen. We will need to do this twice (left-hand nibble and right-hand nibble) for each byte so we need a separate routine called NIBBLE to do this.
Having called this routine we must reload the accumulator with the original byte and this time mask out the most significant nibble, leaving the right-hand nibble in the least significant nibble of the accumulator, and call the nibble routine again. However, note there is little point in calling NIBBLE again as, once it is called, the BYTE routine will have finished so the next command would be RTS. We may as well 'fall through' straight to NIBBLE and let the RTS at its end (supplied by the OS subroutine OSASCI) do the job. This means that we have to place NIBBLE directly in place of the second JSR NIBBLE command. This leaves us with:
JSR nibble LDA &75 AND #&F .nibble ... (2050-2080)
The nibble routine must add 48 (ASCII code for 0) to the number in the accumulator before printing it using OSASCI. However, if the number is 10 or more (decimal) then we need first to add a further seven to bring it to the corresponding ASCII codes for the characters A, B, C, D, E and F.
.nibble CLC ADC #48 CMP #58 BCC print ADC #7 .print JSR osasci RTS
Notice that because the last-but-one command of NIBBLE is a JSR we can instead just jump to OSASCI and the RTS command at its end will save us from needing an extra RTS at the end of NIBBLE. Thus the end of NIBBLE becomes:
.print JMP osasci (2080-2140)
We now have the byte display routine; so, next, we need to write the line display routine. For this we need the address of the first byte on the line. This may not necessarily be the line the cursor is on, so we can't use &70 and &71. Instead we can specify that the address of the first byte on the line must be stored at &72 and &73. The routine must first of all print a 'yellow' teletext code for the address. Then it must print the two-byte address stored in &72 and &73 (remember that &73 is the high byte).
.line LDA #&83 JSR osasci LDA &73 JSR byte LDA &72 JSR byte (2160-2210)
Next we need a space to separate the address from the data.
LDA #32 JSR osasci (2220-2230)
We will next use POST-INDEXED INDIRECT ADDRESSING to load the byte to be displayed into the accumulator; so we need to set Y to zero for the first byte. Then, for each byte, we can print a 'green' teletext code to separate the byte from the previous one; then load then byte into the accumulator and display it; then increment Y; and repeat the process until all eight bytes that make up the line have been displayed. After that we only need a carriage return to complete this routine. As before, we can save ourselves from putting an RTS at the end by jumping to the OSASCI routine.
LDY #0 .loop3 LDA #&82 JSR osasci LDA (&72),Y JSR byte INY CPY #8 BNE loop3 LDA #13 JMP osasci (2240-2330)
Having written a routine for displaying a line, we can now go back to the main routine and display a whole screenful of data. For this overall display, it would be best if the byte we are currently examining or altering always appears half-way down the screen as then we can see what we have done and what is coming. For this reason the line the cursor is on will always be the thirteenth line down. Thus to print the block of memory above the cursor we need to subtract 96 (12 times 8) from the contents of &70 and &71. This we can put into &72 and &73 ready to display a line. We also need to start at the top of the screen (later we will jump back to this point so the change of mode is not sufficient).
.display LDA #30 \ Display sect of JSR osasci \ memory as table 8 LDA &&0 \ bytes of 24 SEC \ lines. SBC #96 STA &72 LDA &71 SBC #0 STA &73 (320-400)
We are going to print 24 lines in one go, so we can use the X register to count down from 24 to 1. We also need to add 8 to the contents of &72 and &73 to move the address forward by eight bytes after each line.
LDX #24 .loop2 JSR line LDA &72 CLC ADC #8 STA &72 LDA &73 ADC #0 STA &73 DEX BNE loop2 (410-510)
We are now at the stage where we need a cursor to appear. We are going to highlight the byte we are interested in by making it white. To do this we need to put a 'white' teletext code before it and a 'green' teletext code after it. As we are going to want to remove this cursor again, it would be sensible to use a subroutine to position the text cursor where we are going to place the 'white' byte. We shall call this routine CURSOR1. We know that the cursor will always be on line 12 so we only have to calculate how far across it will be. As each byte uses up three screen characters for its display we need to multiply the byte number by three. To do this we need to load the accumulator with the contents of &74, shift the accumulator left one bit to multiply it by two, and then add the contents of &74 to the accumulator to make three times the original number. We then have to add six to the accumulator to shift the cursor right past the address at the beginning of the line. We can use VDU31,x,y to move the text cursor on the screen. So the routine looks like:
.cursor1 LDA #31 \ Move text cursor JSR osasci \ to position LDA &74 \ for editing ASL A \ cursor CLC ADC &74 CLC ADC #6 JSR osasci LDA #12 JMP osasci (2350-2450)
We can now go back to the main routine. Firstly we need to call CURSOR1 and then we need to print a 'white'. As we have used 'green' codes to separate the bytes we don't need to put another one in. The text cursor is then on the first nibble of the byte.
.start JSR cursor1 LDA #&87 JSR osasci
We now need to get a key from the keyboard using OSRDCH. If ESCAPE has been pressed we must acknowledge it with OSBYTE &7E and we then want to turn the cursor back on with VDU23,1,1,0;0;0; reset the cursor keys to their normal functions with *FX4,0 and move the cursor to the bottom of the screen using VDU31, all before returning to BASIC.
.key JSR osrdch BCC key1 LDA #&7E JSR osbyte LDA #23 JSR osasci LDA #1 JSR osasci JSR osasci LDA #0 LDX #7 .loop4 JSR osasci DEX BNE loop4 \ Note that X must now LDA #4 \ be zero, so we don't LDY #0 \ need to set it for JSR osbyte \ the OSBYTE call LDA #31 JSR osasci LDA #0 JSR osasci LDA #24 JMP osasci (550-770)
Having checked for the ESCAPE key we need to see if the byte under the cursor is being altered. If the key pressed is either 0 to 9 or A to F then we must alter the byte accordingly. Firstly we can check if the code is less than 48. If so, then we must check for other keys.
.key1 CMP #48 BCC key2 (780-790)
Next we can look to see if the code is less than 58. If so, then a number key has been pressed and we need to subtract 48 to get the value of the new nibble.
CMP #58 BCS letter SEC SBC #48 JMP hex (800-840)
If not, we then want to look for a letter. If the code is less than 65 we are not interested and must wait for another key. If it is larger than or equal to 71 then we must look to see if it is a cursor key. Otherwise we want to subtract 55 to get the value of the new nibble.
.letter CMP #65 BCC key CMP #71 BCS key2 SEC SBC #55 (850-900)
We now have to decide what to do with the nibble. Probably the best way to input the byte is for each new nibble to shift the old byte left one nibble. Thus the high nibble is lost, the low nibble becomes the high nibble and the nibble typed in replaces the low nibble. To do this we have to temporarily store the nibble we have typed in while we shift the memory byte left four bits. Then we can OR in the new nibble and store the result back in memory.
.hex STA &75 LDY &74 LDA (&70),Y ASL A ASL A ASL A ASL A ORA &75 STA (&70),Y LDA (&70),Y (910-990)
This program will allow us to look into the ROMs but if we try to store an alteration back into a ROM nothing will happen. To make sure that the user doesn't think something has happened it would be sensible to load the byte back again before storing it on the screen. This way, if the byte hasn't been altered then the displayed byte on the screen won't change. As we have left the text cursor at the first nibble on the screen we can just call the subroutine BYTE to display the byte, moving the text cursor back again and go back to waiting for the next key.
JSR byte LDA #8 JSR osasci JSR osasci JMP key (1000-1050)
If the key pressed is not a number or a letter we must check whether it is a cursor key and act accordingly. We shall check first of all a cursor-up. If this has been pressed we shall branch to the relevant routine. Otherwise we shall check for a cursor-left.
.key2 CMP #&9F BEQ up CMP #&9C BNE key3 (1060-1090)
Having established that the cursor-left key has been pressed we need to remove the highlight cursor. We will have to do this several times so we need a subroutine which we shall call CURSOR. This must first call CURSOR1 to position the text cursor and then rub over the highlight teletext code with a 'green' code.
.cursor JSR cursor1 LDA #&82 JMP osasci (2470-2490)
So our cursor-left routine can now remove the cursor. Next it must decrement &74 to move the address of the byte being looked at, back by one. If this is now 255 then we must set it to seven (the end of the line) and do a cursor up. Otherwise we can go back to the start of the main routine. Notice that as this last branch is more than 128 bytes we have to use the 'skip and jump' technique.
JSR cursor DEC &74 LDA &74 CMP #255 BEQ skip1 JMP start .skip1 LDA #7 STA &74 JMP up1 (1100-1180)
While we are at it, we can write the UP routine as well. This will be the same as UP1 but with a call to CURSOR in front of it.
.up JSR cursor .up1 ... (1190)
Next we have to scroll the screen down one line. We can do this by first moving the cursor to the top of the screen using VDU30 and doing a cursor-up.
.up1 LDA #30 JSR osasci LDA #11 JSR osasci (1200-1230)
Next we have to subtract eight from &70 and &71 to move the cursor line back by one.
LDA &70 SEC SBC #8 STA &70 LDA &71 SBC #0 STA &71 (1240-1300)
Next we must call LINE with the address of the top line in &72 and &73. This will be the contents of &70 and &71 minus 96.
LDA &70 SEC SBC #96 STA &72 LDA &71 SBC #0 STA &73 JSR line (1310-1380)
Lastly we need to clear the bottom line of the screen by moving to the bottom line and printing 31 spaces.
LDA #31 JSR osasci LDA #0 JSR osasci LDA #24 JSR osasci LDA #32 LDX #31 .loop% JSR osasci DEX BNE loop5 JMP start (1390-1500)
Next we must check for cursor-down. If this has been pressed then we must jump to the relevant routine.
.key3 CMP #&9E BEQ down (1510-1520)
Otherwise we must check for cursor-right. If you are typing a long program it will be annoying to have to find the cursor-right key between typing in each byte, so we shall allow both the cursor-right key and the space bar to do the same job.
CMP #&9D BEQ right CMP #32 BNE key4 (1510-1520)
The RIGHT routine must first remove the old cursor and then increment &74 to move the cursor right by one byte. If the contents of &74 now equal eight then we must set it back to zero and jump to the cursor-down routine. Otherwise, we must use the 'skip and jump' technique to branch back to START.
.right JSR cursor INC &74 LDA &74 CMP #8 BEQ skip2 JMP start .skip2 LDA #0 STA &74 JMP down1 (1570-1650)
As with the UP routine, we can insert the DOWN routine here.
.down JSR cursor .down1 ... (1660)
Next we have to scroll the screen up a line. We can do this by moving to the bottom of the screen and doing a cursor-down. However, at the same time we can print the new bottom line. This is because we are leaving a blank line at the bottom of the screen. By printing the new line in this blank space the carriage return at the end will scroll the screen for us. First we need to move to this blank line.
.down1 LDA #31 JSR osasci LDA #0 JSR osasci LDA #24 JSR osasci (1670-1720)
Now we add eight to the address of the cursor line.
LDA &70 CLC ADC #8 STA &70 LDA &71 ADC #0 STA &71 (1730-1790)
Next we must store the address of the new bottom line in &72 and &73 and call LINE. Then we can jump back to START.
LDA &70 CLC ADC #88 STA &72 LDA &71 ADC #0 STA &73 JSR line JMP start (1800-1880)
We now have all we need. However, if you want to look at the contents of address &7F00 you will have to scroll through &0000 to &7F00 one line at a time and this will be slightly tedious. To solve this problem we shall make shifted cursor-up and shifted cursor-down move a page at a time through the memory. This we can do by incremented or decremented the high byte of the address of the cursor (line &71) and jumping back to DISPLAY.
.key4 CMP #&8E BNE key5 INC &71 JMP display .key5 CMP #&8F BNE key6 DEC &71 JMP display (1890-1960)
Finally, if the key that has been pressed is not one we are interested in then we must go back and wait for another key to be pressed.
.key6 JMP key (1970)
This program is a very simple one. There are several ROMs available that have more sophisticated monitors in them. BBC MONITOR (ROM based) from BBC Publications (1985) is one such. Another package from the same publishers is TOOLBOX 2 by Ian Trackman (1985), which comprises a book and software tape. It has a particularly interesting implementation of a monitor among its many utilities, and complements this book.
Of course, you can improve our monitor program. However, it will provide a useful tool for those people who can't be bothered to write a better version or buy a ROM. It will also give you valuable experience in how assembly code programs work.
Here, then, is the complete listing of the monitor program. You might like to use the command *SAVE MONITOR 7900 +20B 7900 to save the machine code once it is assembled. Then the monitor can be used by typing *MONITOR. This will take up less room on a disc or tape and will be faster to load. However, you should keep a copy of the source assembly code program so that you can assemble the program into different places, if necessary, by changing P% at line 60.
You do not need to type in the comments on the right-hand side of the listing.
10 HIMEM=&7900 20 osasci=&FFE3 30 osbyte=&FFF4 40 osrdch=&FFE0 50 FORpass%=0TO2STEP2 60 P%=&7900 70 [OPTpass% 80 .monitor LDA #4 \ Main program 90 LDX #2 \ initialisation. 100 LDY #0 110 JSR osbyte 120 LDA #&E1 130 LDX #&90 140 JSR osbyte 150 LDA #22 160 JSR osasci 170 LDA #7 180 JSR osasci 190 LDA #23 200 JSR osasci 210 LDA #1 220 JSR osasci 230 LDA #0 240 LDX #8 250 .loop1 JSR osasci 260 DEX 270 BNE loop1 280 LDA #0 290 STA &70 300 STA &71 310 STA &74 320 .display LDA #30 \ Display sect of 330 JSR osasci \ memory as table 8 340 LDA &70 \ bytes of 24 350 SEC \ lines. 360 SBC #96 370 STA &72 380 LDA &71 390 SBC #0 400 STA &73 410 LDX #24 420 .loop2 JSR line 430 LDA &72 440 CLC 450 ADC #8 460 STA &72 470 LDA &73 480 ADC #0 490 STA &73 500 DEX 510 BNE loop2 520 .start JSR cursor1 \ Start checking 530 LDA #&87 \ keys 540 JSR osasci 550 .key JSR osrdch 560 BCC key1 \ Check for 570 LDA #&7E \ ESCAPE. 580 JSR osbyte 590 LDA #23 600 JSR osasci 610 LDA #1 620 JSR osasci 630 JSR osasci 640 LDA #0 650 LDX #7 660 .loop4 JSR osasci 670 DEX 680 BNE loop4 690 LDA #4 700 LDY #0 710 JSR osbyte 720 LDA #31 730 JSR osasci 740 LDA #0 750 JSR osasci 760 LDA #24 770 JMP osasci 780 .key1 CMP #48 \ Check for byte 790 BCC key2 \ being altered. 800 CMP #58 810 BCS letter 820 SEC 830 SBC #48 840 JMP hex 850 .letter CMP #65 860 BCC key 870 CMP #71 880 BCS key2 890 SEC 900 SBC #55 910 .hex STA &75 920 LDY &74 930 LDA (&70),Y 940 ASL A 950 ASL A 960 ASL A 970 ASL A 980 ORA &75 990 STA (&70),Y 1000 LDA (&70),Y 1010 JSR byte 1020 LDA #8 1030 JSR osasci 1040 JSR osasci 1050 JMP key 1060 .key2 CMP #&9F \ Check for 1070 BEQ up \ cursor-up. 1080 CMP #&9C \ Check for 1090 BNE key3 \ cursor-left. 1100 JSR cursor 1110 DEC &74 1120 LDA &74 1130 CMP #255 1140 BEQ skip1 1150 JMP start 1160 .skip1 LDA #7 1170 STA &74 1180 JMP up1 1190 .up JSR cursor 1200 .up1 LDA #30 1210 JSR osasci 1220 LDA #11 1230 JSR osasci 1240 LDA &70 1250 SEC 1260 SBC #8 1270 STA &70 1280 LDA &71 1290 SBC #0 1300 STA &71 1310 LDA &70 1320 SEC 1330 SBC #96 1340 STA &72 1350 LDA &71 1360 SBC #0 1370 STA &73 1380 JSR line 1390 LDA #31 1400 JSR osasci 1410 LDA #0 1420 JSR osasci 1430 LDA #24 1440 JSR osasci 1450 LDA #32 1460 LDX #31 1470 .loop5 JSR osasci 1480 DEX 1490 BNE loop5 1500 JMP start 1510 .key3 CMP #&9E \ Check for 1520 BEQ down \ cursor-down. 1530 CMP #&9D \ Check for 1540 BEQ right \ cursor-right 1550 CMP #32 1560 BNE key4 1570 .right JSR cursor 1580 INC &74 1590 LDA &74 1600 CMP #8 1610 BEQ skip2 1620 JMP start 1630 .skip2 LDA #0 1640 STA &74 1650 JMP down1 1660 .down JSR cursor 1670 .down1 LDA #31 1680 JSR osasci 1690 LDA #0 1700 JSR osasci 1710 LDA #24 1720 JSR osasci 1730 LDA &70 1740 CLC 1750 ADC #8 1760 STA &70 1770 LDA &71 1780 ADC #0 1790 STA &71 1800 LDA &70 1810 CLC 1820 ADC #88 1830 STA &72 1840 LDA &71 1850 ADC #0 1860 STA &73 1870 JSR line 1880 JMP start 1890 .key4 CMP #&8E \ Check for 1900 BNE key5 1910 INC &71 \ cursor-down. 1920 JMP display 1930 .key5 CMP #&8F \ Check for 1940 BNE key6 \ shifted 1950 DEC &71 \ cursor-up. 1960 JMP display 1970 .key6 JMP key 1980 1990 .byte STA &75 \ Display byte 2000 AND #&F0 \ in hex. 2010 LSR A 2020 LSR A 2030 LSR A 2040 LSR A 2050 JSR nibble 2060 LDA &75 2070 AND #&F 2080 .nibble CLC \ Display nibble 2090 ADC #48 \ in hex. 2100 CMP #58 2110 BCC print 2120 CLC 2130 ADC #7 2140 .print JMP osasci 2150 2160 .line LDA #&83 \ Display line 2170 JSR osasci \ of table. 2180 LDA &73 2190 JSR byte 2200 LDA &72 2210 JSR byte 2220 LDA #32 2230 JSR osasci 2240 LDY #0 2250 .loop3 LDA #&82 2260 JSR osasci 2270 LDA (&72),Y 2280 JSR byte 2290 INY 2300 CPY #8 2310 BNE loop3 2320 LDA #13 2330 JMP osasci 2340 2350 .cursor1 LDA #31 \ Move text cursor 2360 JSR osasci \ to position 2370 LDA &74 \ for editing 2380 ASL A \ cursor 2390 CLC 2400 ADC &74 2410 CLC 2420 ADC #6 2430 JSR osasci 2440 LDA #12 2450 JMP osasci 2460 2470 .cursor JSR cursor1 \ Remove editing 2480 LDA #&82 \ cursor. 2490 JMP osasci 2500 ] 2510 NEXT 2520 CALL monitor