Apple Assembly Line Volume 2 -- Issue 9 June, 1982 In This Issue... ---------------- Implementing New Opcodes Using 'BRK' . . . . . . . . . . . 2 A New Hi-Res Function for Applesoft (HXPLOT) . . . . . . . 7 Bubble Sort Demonstration . . . . . . . . . . . . . . . . 11 DOS File Exchange: A Review . . . . . . . . . . . . . . . 12 Macro Hint . . . . . . . . . . . . . . . . . . . . . . . . 12 Yes/No Subroutine . . . . . . . . . . . . . . . . . . . . 13 My Own Little Bell . . . . . . . . . . . . . . . . . . . . 14 Using the Shift-Key Mod . . . . . . . . . . . . . . . . . 16 Search for Page-Zero References . . . . . . . . . . . . . 19 Automatic CATALOG for S-C Macro Assembler . . . . . . . . 23 Examiner . . . . . . . . . . . . . . . . . . . . . . . . . 25 Advertising in AAL ------------------ Due to the increased costs of printing more than 1600 copies per month, and with the desire to limit the percentage of advertising pages to less than 30% each month, I have decided to raise the page rate again. For the July 1982 issue the price will be $50 for a full page, $30 for a half page. So-called "classified" ads, of up to forty words, will be $5. Implementing New Opcodes Using 'BRK'.......Bob Sander-Cederlof -------------------------------------------------------------- If you have the Autostart ROM, you can control what happens when a BRK instruction is executed. If you do nothing, a BRK will cause entry into the Apple Monitor, and the register contents will be displayed. But (if you have the Autostart Monitor) by a small amount of programming you can make the BRK do marvelous things. Like simulate neat instructions from the 6809, which are not in the 6502, for example. I am thinking particularly of the LEAX instruction, which loads the effective address into a 16-bit register; of BSR, which enters a subroutine like JSR, but with a relative address; and of BRA, which is a relatively addressed JMP. With these three instructions you can write position-independent programs (programs that execute properly without any modification regardless of where they are loaded in memory). I am thinking of these because of an article by A. Sato in "Lab Letters" (a publication of ESD Laboratories in Tokyo, JAPAN) Volume 6 No. 1, pages 91-93. It is all written in Japanese (see example below), but I think I deciphered what he is saying. When a BRK instruction is executed, the program is interrupted as though a Non-Maskable Interrupt (NMI) occurred. The B bit in the status register is set, so the Apple can tell that the interrupt was caused by BRK rather than some external event. After making this determination, the Autostart Monitor performs a "JMP ($3F0)" instruction. This means that you can get control by placing the address of your own program into $3F0 and $3F1. The monitor initialization process puts the address $FA59 there. By the time the monitor branches to the BRK processor (its own or yours) all the registers have been saved. The address of the BRK instruction plus 2 (PC) has been saved at $3A and $3B; the registers A, X, Y, P (status), and S (stack pointer) have been saved in $45 through $49, respectively. BRK Interceptor/Interpreter In the program below, lines 1180-1230 will set up the BRK-vector at $3F0 and $3F1 to point to your own BRK processor. Lines 1250-1320 back up the PC value by one, to point at the byte immediately following the BRK instruction. At this point I can decide what to do about the BRK. Since I want to simulate the operation of LEAX, BSR, and BRA, I will use the BRK instruction to introduce a pseudo instruction of three bytes. I decided to copy A. Sato on this. LEAX is a BRK instruction followed by LDX from an absolute address. This is $AE in hexadecimal, followed by a 16-bit value representing a relative address. BSR is BRK followed by a JSR instruction ($20) and a relative address; BRA is BRK followed by a JMP instruction ($4C) and a relative address. Looking back at the program, lines 1310 and 1320 store the address of the secondary opcode byte into PNTR and PNTR+1. These two bytes are inside an instruction at line 1760. I didn't want to use any page-zero space, so I had to resort to this kind of self-modifying code. While we are here, lines 1750-1780 pick up the byte whose address is in PNTR. Lines 1710-1740 increment PNTR. If we call GET.THIS.BYTE, it just picks up the byte currently pointed at. If we call GET.NEXT.BYTE, it increments the pointer and gets the next byte. Lines 1330-1370 pick up the three bytes which follow the BRK. The opcode byte is saved in the Y-register. Lines 1380-1450 compute the effective address, by adding the actual address of the instruction to the relative address inside the instruction. Lines 1470-1540 classify the opcode; if it is one of the three we have implemented, it branches to the appropriate code. If not, it jumps back into the monitor and processes the BRK in the normal monitor way. Opcode Implementation Lines 1560-1780 implement the three opcodes BSR, BRA, and LEAX. BRA (Branch Always) is the easiest one. We have already computed the effective address and stored it in the address field of the JMP instruction at line 1620. All BRA does is restore the registers (line 1610), and JMP to the effective address. BSR (Branch to Subroutine) is only slightly harder. We first have to push the return address on the stack, and then do a BRA. Lines 1560-1590 do the pushing. LEA (Load Effective Address) is the hardest. Lines 1650-1690 do the work. First GET.NEXT.BYTE moves the address in PNTR,PNTR+1 to point at the first byte of the next instruction. That is so we can continue exectution. Then MON.RESTORE gets back the original contents of all the registers. THEN LDY and LDX pick up the effective address in the Y- and X-registers. The high byte of the effective address is in the X-register, and the Z- and N-bits in the status register reflect the value of this byte. If you wish, you could modify this to not change the status by inserting a PHP opcode after line 1660, and PLP after line 1680; then the status register would remain unchanged by the entire LEA process. Or you could reverse lines 1670 and 1680, so that the status reflected the low-order byte of the effective address. Demonstration Using the New Opcodes Lines 1800 and beyond are a demonstration of the use of the new opcodes. First I defined some macros for the new opcodes. I didn't have to do this, but it is convenient if you have a macro assembler. If you don't, you can use the BRK instruction on one line, followed by a LDX, JSR, or JMP instruction with a relative address on the next line. My macros are defined in a nested fashion. The BRK macro generates two lines: BRK on the first line, and a second line consisting of the specified opcode and operand. The LEA, BSR, and BRA macros call BRK to generate LDX, JSR, and JMP instructions after the BRK. The operand field is a relative address, computed within the BRK macro. The demonstration program will run anywhere in memory, as long as the BRK interpreter has been loaded and initialized. You can test this by moving $871-89F to other places and running it. What it does is print out the message in line 2090. 1010 *-------------------------------- 1020 * IMPLEMENTING BSR, BRA, AND LEA OPCODES 1030 * USING THE 'BRK' VECTOR WITH THE 1040 * AUTOSTART ROM 1050 * 1060 * ADAPTED FROM AN ARTICLE IN "LAB LETTERS" 1070 * BY A. SATO 1080 *-------------------------------- 1090 MON.PC .EQ $3A,3B 1100 MON.XREG .EQ $46 1110 MON.YREG .EQ $47 1120 *-------------------------------- 1130 BRK.VECTOR .EQ $3F0,3F1 1140 *-------------------------------- 1150 MON.BRK .EQ $FA59 1160 MON.RESTORE .EQ $FF3F 1170 *-------------------------------- 1180 SETUP 1190 LDA #BREAK.INTERPRETER 1200 STA BRK.VECTOR 1210 LDA /BREAK.INTERPRETER 1220 STA BRK.VECTOR+1 1230 RTS 1240 *-------------------------------- 1250 BREAK.INTERPRETER 1260 LDY MON.PC+1 PICK UP ADDRESS OF THIRD BYTE 1270 LDX MON.PC 1280 BNE .1 BACK UP TO SECOND BYTE 1290 DEY 1300 .1 DEX 1310 STX PNTR MODIFY ADDRESS IN GET.THIS.BYTE SUBROUTINE 1320 STY PNTR+1 1330 JSR GET.THIS.BYTE 1340 TAY OPCODE BYTE 1350 JSR GET.NEXT.BYTE 1360 PHA ADDR-LOW BYTE 1370 JSR GET.NEXT.BYTE 1380 TAX 1390 PLA 1400 SEC ADDR-HIGH BYTE 1410 ADC PNTR COMPUTE EFFECTIVE ADDRESS 1420 STA EFF.ADDR 1430 TXA 1440 ADC PNTR+1 1450 STA EFF.ADDR+1 1460 *-------------------------------- 1470 CPY #$20 CLASSIFY OPCODE 1480 BEQ BSR 1490 CPY #$4C 1500 BEQ BRA 1510 CPY #$AE 1520 BEQ LEA 1530 STY MON.YREG 1540 JMP MON.BRK 1550 *-------------------------------- 1560 BSR LDA PNTR+1 PUSH RETURN ADDRESS ON STACK 1570 PHA 1580 LDA PNTR 1590 PHA AND DO BRA 1600 *-------------------------------- 1610 BRA JSR MON.RESTORE 1620 JMP *-* 1630 EFF.ADDR .EQ *-2 1640 *-------------------------------- 1650 LEA JSR GET.NEXT.BYTE POINT AT NEXT INSTRUCTION 1660 JSR MON.RESTORE RESTORE A-REG AND STATUS 1670 LDY EFF.ADDR ADDR-LO IN Y 1680 LDX EFF.ADDR+1 ADDR-HI IN X 1690 JMP (PNTR) 1700 *-------------------------------- 1710 GET.NEXT.BYTE 1720 INC PNTR 1730 BNE GET.THIS.BYTE 1740 INC PNTR+1 1750 GET.THIS.BYTE 1760 LDA $FFFF (FILLED IN) 1770 PNTR .EQ *-2 1780 RTS 1790 *-------------------------------- 1800 MSG .EQ 0,1 1810 JMP.COUT JMP $FDED 1820 .MA LEA 1830 >BRK LDX,]1 1840 .EM 1850 .MA BSR 1860 >BRK JSR,]1 1870 .EM 1880 .MA BRA 1890 >BRK JMP,]1 1900 .EM 1910 .MA BRK 1920 BRK 1930 ]1 ]2-:1 1940 :1 1950 .EM 1960 TEST >LEA MESSAGE 1970 STX MSG+1 1980 STY MSG 1990 LDY #0 2000 .1 LDA (MSG),Y 2010 PHA 2020 ORA #$80 2030 >BSR JMP.COUT 2040 INY 2050 PLA 2060 BPL .1 2070 LDA #$8D CARRIAGE RETURN 2080 >BRA JMP.COUT 2090 MESSAGE .AT /THIS IS MY MESSAGE/ A New Hi-Res Function for Applesoft............. Mike Laumer ------------------------------------------------------------ Most people use the language card as nothing more than a ROM simulator for the other version of BASIC that is not on the motherboard. But it can do much more since the memory is actually RAM. Indeed Bob S-C's Macro Assembler has a version which runs in a Language Card. The FLASH! Integer BASIC compiler which I wrote uses the language card in place of a disk file providing higher speed compilations for those people who have a language card. One nice aspect of having the language card is the ability to move Apple software from ROM to RAM in the card and make changes to add a new capability. Some people have done this already with the Apple monitor to add an extra feature or two at the expense of another (who needs the tape I/O routines). The program assciated with this article will allow you to patch a RAM card version of Applesoft to modify the 'HPLOT' command to function as an 'HXPLOT' command. What is 'HXPLOT' you say. Remember the DRAW and XDRAW commands in Applesoft. The 'DRAW' command will place a shape on the screen; 'XDRAW' does the same thing, but 'XDRAW' has the unique ability to redraw the shape and erase it from the screen leaving whatever was on the screen initially still intact. The 'HXPLOT' function in the listing functions the same way for the 'HPLOT' command as 'XDRAW' does for the 'DRAW' command. I have been developing a Hi-Res graphics editor as my next product. During the development cycle I was working with a line draw game paddle routine. You move a cursor to a position and anchor one end of the line to a point. Then you can move to another position and while you move a line stretches out from the point like a rubber band to the current cursor position. This gives you a preview of what the line looks like before you plot the line. The 'HXPLOT' function does have one sleight problem: it plots independent of the current color. What the function actually does as it draws a line is to invert each dot of the line path instead of plotting a color. When the same line is drawn with the same coordinates the bits on the line path are inverted again back to their original value, restoring the screen to what it was before you started HXPLOTting. You may be wondering why not just use the 'HPLOT' as it is to do this. You could just draw the line once with a color of 3 then change the color to 0 and erase the line with another 'HPLOT'. This only works if you have a black screen with no other images on it. If their are other images on the screen then when you erase the line you will draw a black line through those other images causing them to change. Only a function like 'XDRAW' or the 'HXPLOT' will be non-destructive of the background data on the screen. How It Works The 'HPLOT' command in Applesoft is actually two commands in one. HPLOT x, y plots 1 point HPLOT x1,y1 TO x2,y2 plots a line Each of the routines have one common place where they plot a bit onto the hi-res screen. The point plotting routine is at $F457 in the ROM and the line routine is at $F53A in the ROM. By putting Applesoft into the RAM card we can patch into these routines and modify their operation. The two areas that are patched are at $F457 and $F58D. After you run the patch program you should see the Applesoft prompt character and there will be no program in memory. So type in the small demo program listed here and run it. 10 HGR2: POKE 769,1 15 POKE 28,127: CALL 62454 20 FOR I=0 TO 279 STEP 10: FOR J=0 TO 192 STEP 10 25 HPLOT 140,96 TO I,J 30 FOR Z=1 TO 1: NEXT Z 40 HPLOT 140,96 TO I,J 50 NEXT J: NEXT I 100 GOTO 10 If you have an Integer BASIC motherboard you should boot up your system master disk and have Applesoft loaded into your RAM card before using the routine. 1000 *-------------------------------- 1010 * THIS ROUTINE ADDS AN XPLOT CAPABILITY 1020 * TO APPLESOFT. THE FLAG AT $301 (769) 1030 * CONTROLS WHETHER HPLOT OR XPLOT IS 1040 * FUNCTIONING. 1050 * 1060 * POKE 769,0 ENABLES HPLOT 1070 * POKE 769,1 ENABLES XPLOT 1080 *-------------------------------- 1090 .OR $300 1100 .TF B.HXPLOT 1110 NEW.HLIN LDA #0 TEST 'XPLOT' FLAG 1120 BNE .2 YES 'XPLOT' MODE 1130 LDA ($26),Y PLOT NORMAL LINE 1140 EOR $1C 1150 AND $30 1160 .1 JMP $F593 BACK INTO APPLESOFT LINE ROUTINE 1170 .2 LDA #$7F MASK COLOR SHIFT BIT 1180 AND $30 OFF OF BIT MASK 1190 AND ($26),Y TEST SCREEN BIT 1200 BNE .1 BIT IS SET!... SO CLEAR IT 1210 LDA #$7F BIT IS CLEAR!...SO SET IT 1220 AND $30 BIT MASK WITHOUT COLOR SHIFT BIT 1230 BPL .1 BRANCH ALWAYS 1240 *-------------------------------- 1250 NEW.PLOT JSR $F411 CALL HPOSN ROUTINE 1260 LDA $301 TEST 'XPLOT' FLAG 1270 BNE .1 YES 'XPLOT' MODE 1280 JMP $F45A PLOT NORMAL 1290 .1 LDA #$7F XPLOT 1300 AND $30 MASK COLOR SHIFT BIT OFF 1310 AND ($26),Y TEST SCREEN BIT 1320 BNE .2 SCREEN BIT IS SET 1330 LDA #$7F ...CLEAR SO PREPARE TO 1340 AND $30 SET SCREEN BIT 1350 .2 JMP $F460 BACK INTO APPLESOFT XPLOT ROUTINE 1360 *-------------------------------- 1370 * 1380 * TO USE THE ABOVE FUNCTION YOU MUST HAVE A RAM CARD. 1390 * APPLESOFT MUST BE IN THE RAM CARD. 1400 * THEN YOU MUST DO THE FOLLOWING: 1410 * 1420 * 0. BLOAD B.XPLOT.FOR.FP LOAD THE XPLOT ROUTINE 1430 * 1. CALL-151 TO ENTER THE MONITOR 1440 * 2. C081 C081 TO WRITE ENABLE THE CARD 1450 * 3. GO TO STEP 5 IF YOU HAVE AN INTEGER BASIC MOTHER BOARD 1460 * 4. D000