Appendix C Simple Assembler Notes On Assembling This program is written in BASIC because there is no reason not to. Since the program runs quickly enough and there is some complicated arithmetic involved, BASIC is the language of choice. There are assemblers in ML which make two "passes" through the source code and do need the extra speed. But this is a simple, "one-pass" assembler. The virtue of simplicity is that you can easily and quickly make small ML routines, test them, and debug them. An added bonus is that modifying the Simple Assembler is easy in BASIC. We'll see how you can customize it in a minute. The assembler accepts your opcodes and their arguments, translates them into the correct numeric values, and POKES them into RAM memory. You have a choice between using hex or decimal during your ML programming on the Simple Assembler (SA). If you remove line 10, the SA will accept only decimal numbers as arguments, will print all addresses in decimal, and will display the object code (the numbers it is POKEing) in decimal. Leaving line 10 in the program will result in the SA accepting, addressing, and displaying only hexadecimal numbers. The circumflex in lines 4010 and 5030 - the character following the number 16 - means "to the power of" and generally appears on computer keyboards as an arrow pointing up. Since this is not a complicated assembler, a decision had to be made concerning whether or not to include two of the conventions which have been traditional in ML programming. They were left out because it saves programming time to avoid them and they are unnecessary. The first one is the dollar sign ($). When an assembler can accept either hex or decimal simultaneously it must have a way to tell, if you type in "10", whether you mean decimal 10 or hex 10 (decimal 16). The convention requires that you write decimal ten as "10" and hex as "$10. "However, this can quickly become a burden. In the SA, you let it know which kinds of numbers you are using by setting H in line ten. After that, just type in the numbers. No $ is used. The second convention that is not included in the SA is the use of the comma. Again, there is no particular reason to use commas, but it has been the tradition to include them for certain addressing modes. They, too, can become burdensome when you are programming. Also, each line of your ML program is brought into the computer via the INPUT statement in line 240. Microsoft BASIC's INPUT statement dislikes seeing commas. So, it is expedient in several ways to drop the comma convention. There is just no reason to use them. One additional note. The SA does not accept the indirect jump: JMP ($OFFF). You could add it if you wish, but because of a bug in the 6502, it is far safer to avoid it. Here is a list of the traditional conventions used in most assemblers compared to the simplified conventions of the SA. Notice that each addressing mode has its own appearance, its own punctuation. This is how an assembler knows which addressing mode you mean to use. Spaces are important.
Addressing Mode Conventions | Simple Assembler | Traditional
Immediate | LDA #15 | LDA #$15
Absolute | LDA 1500 | LDA $1500
Zero Page | LDA 15 | LDA $15 (sometimes LDA *$15)
Accumulator | ASL | ASL A
Zero Page, X | LDA 15X | LDA $15,X
Zero Page, Y | LDX 15Y | LDX $15,Y
Absolute, X | LDA 1500X | LDA $1500,X
Absolute, Y | LDA 1500Y | LDA $1500,Y
Indexed Indirect | LDA (15X) | LDA ($15,X)
Indirect Indexed | LDA (15)Y | LDA ($15),Y
Customizing The Simple Assembler An assembler is only supposed to get your typed opcodes and their arguments, translate them into the right numbers, and put them in memory for you. Nevertheless, the assembler is there for your benefit and it is a computer program. It can be taught to do whatever else would assist you in your ML programming. This is where "pseudoops" come in. They are not part of the 6502 ML instruction set. They are false opcodes. When you enter one of these, the assembler doesn't put it into 6502 and POKE it. It can't. It does something for you like figure out the hex equivalent of a decimal number or whatever. The SA has four built-in pseudo-ops and you can add others. Following the input of the opcode (line 240) there is a short quiz. The first question the computer asks itself is: "did they type the word 'FORWARD'?" If so, it means that you are planning to branch forward, but you don't yet know how far. It will make a mental note of this and later, when you type in another pseudo-op, "RESOLVE," it will go back and put in the correct address for the branch. Also, you can hand-POKE in any number in any address by typing the pseudoop "POKE". And, when you are finished with a program, type "END" and the assembler will quit, reporting the starting and ending addresses of your program in decimal. A full-featured assembler can include dozens of pseudo-ops. Let's briefly examine several popular ones to see if there are some that you might want to add to the SA. Then we'll add a hex/decimal pseudo-op to the SA to show how it's done. BA - Begin Assembly. The SA asks you directly for the starting address (variable SA$). BA signifies the location in RAM memory where you want the object code to start. Example: BA $0400 BY - Bytes. This is for the creation of data tables. The BY is followed by numbers or text characters which are POKEd into memory at the current address. You put these Bytes at the start or end of a program (it could result in havoc if it were in the middle of a program; they would likely be meaningless as instructions). Example: BY 46 46 48 42 12 11 or BY "THIS IS A MESSAGE" DE - Define a label. Labels require a two-pass assembler that goes through the source code first to create a table of labels which would look something like this: `START 1500 LETTER.A 65 PRINTROUTINE 64422` Then, the second time through your source code, the assembler would replace all the labels with their correct values. This is called "resolving" the labels. DE is usually part of the initialization process. A number of the example programs in this book start off with a series of DE pseudo-ops, telling the assembler the meaning of various important labels that will be used later in the source code instead of literal numbers. Example: START DE 1500 or LETTER. A DE 65. EN - The end of the source program. Stop assembling at this point. The SA uses END. MC - Move code. This interesting pseudo-op takes care of a problem that sometimes comes up when you want your object code to be ultimately used in an address that is now being used by the assembler itself or cannot be directly POKEd at this time with the object code. For instance, if your computer's RAM memory starts at address 2048 like the Commodore 64, and you want to put your final ML object code there, what do you do? If the SA was told to start assembly there, it would begin to nibble away at itself. It's in RAM starting at 2048. To allow you to store object code elsewhere, but have it assembled appropriately for final use in 2048, you could instruct the assembler: MC 25000 (temporarily store it here) BA 2048 (but make internal JMPs, JSRs, and table references correct for this starting address) You can add your own pseudo-ops to the SA following line 240. Many times when you are working along in hex you will want to know the decimal equivalent of a number and vice versa. It's nice to be able to just ask for the translation right during assembling. The answer is printed on the screen and you continue on with your programming. The assembler will do nothing to the ML during all this; it's just giving you an answer. If you are working in the hex mode and want a decimal number, just type DECIMAL and the computer will accept a hex number from you and give back its decimal equivalent. Conversely, type HEX and give a decimal number for that translation. To include this pseudo-op in the SA, add the following lines: Program C-1 . Adding The Conversion Pseudo-op. `245 IFMN$="HEX"THENGOT07000 246 IFMN$="DECIMAL"THENGOTO7200 7000 PRINT"ENTER DECIMAL NUMBER";:INPUTDE:IFD E>255THENSZ=3:GOTO7020 7010 SZ=1 7020 GOSUB4000:PRINT" = $ "H$:GOTO230 7200 PRINT"ENTER HEX NUMBER";:INPUTH$ 7210 SX=LEN(H$):BK$="000":H$=LEFT$(BK$,4-SX)+ H$ 7220 GOSUB5000:PRINT" = " DE:GOTO230` The Simple Assembler has a few error messages that it will print when it can't make sense out of something. The primary responsibility for finding errors, however, is yours. You can create and save ML routines and then look at them with the Disassembler to see if they look like they should. SA takes up about 4.5K so it will not run on an unexpanded VIC. A 3K RAM expansion will provide 2000 bytes for storage of your ML routines. Program C-2. Simple Assembler (VIC, PET, Apple, 64 Version). `10 H=1:REM IF H = 0 THEN ASSEMBLY IS IN DEC IMAL 50 HE$="0123456789ABCDEF":SZ=1:ZO$="000" 100 PRINT" SIMPLE ASSEMBLER CONVENTIONS :" 110 DIMM$(56),TY(56),OP(56) 120 FORI=1TO56:READM$(I) 122 ROP$=MID$(M$(I),4,1):TY(I)=VAL(ROP$) 124 OP$=RIGHT$(M$(I),3):OP(I)=VAL(OP$) 126 M$(I)=LEFT$(M$(I),3) 140 NEXTI: PRINT 150 PRINT" IMMEDIATE LDA #15 155 PRINT"ABSOLUTE LDA 1500 160 PRINT"ZERO PAGE LDA 15 165 PRINT"ACCUMULATOR ASL 170 PRINT"INDIRECT X LDA (15X) 175 PRINT"INDIRECT Y LDA (15)Y 177 PRINT"ZERO PAGE X LDA 15X 179 PRINT"ZERO PAGE Y LDX 15Y 180 PRINT"ABSOLUTE X LDA 1500X 185 PRINT"ABSOLUTE Y LDA 1500Y 189 PRINT:PRINT" ENTER ALL NUMBERS IN "; 190 IFH=1 THENPRINT"HEX":GOTO200 195 PRINT"DECIMAL" 200 PRINT:PRINT"PLEASE INPUT STARTING ADDRES S FOR ML PROGRAM":INPUT SA$ 210 IFH=1THENH$=SA$:GOSUB5000:SA--DE:GOTO220 215 SA--VAL(SA$) 220 TA=SA:PRINT"fCLEAR)":REM CLEAR THE SCREE N 230 IFH=ITHENDE=SA:SZ=3:GOSUB4000:PRINTH$;:G OT0240 235 PRINTSA" "; 240 INPUTMN$:PRINT"(UP)"SPC(20);:REM GO UP O NE TINE AND OVER 20 SPACES 241 REM ADD NEW PSEUDO-OPS HERE 242 IFRIGHT$(MN$,7)="FORWARD"THENFB=SA 243 IFRIGHT$(MN$,7)="RESOLVE"THENFR=SA-FB:PO KEFB+1,FR-2:PRINT" OK":GOTO230 244 IFRIGHT$(MN$,4)="POKE"THENPRINT"ADDR,NUM BER(DEC)";:INPUTADR,NUM:POKEADR,NUM :GOTO230 250 IFMN$="END"THENPRINT:PRINT" PROGRAM IS FROM"TA"TO"SA:END 260 L=LEN(MN$):L$=LEFT$(MN$,3) 270 FORI=1TO56:IFL$=M$(I)THEN300 280 NEXTI 290 GOTO850 300 REM PRIMARY OPCODE CATEGORIES 301 TY=TY(I):OP=OP(I) 305 IFFB=SATHENTN=0:GOTO2010 310 IFTY=0THENGOTO1000 320 IFTY=3THENTY=1:IFL=3THENOP=OP+8:GOTO1000 330 R$=RIGHT$(MN$,L-4):IFH=1THENGOSUB6000 340 LR$=LEFT$(R$,1):LL=LEN(R$):IFLR$="#"THEN 480 350 IFLR$="("THEN520 360 IFTY=8THEN600 370 IFTY=3THENOP=OP+8:GOTO1000 380 IFRIGHT$(R$,1)="X"ORRIGHT$(R$,1)="Y"THEN 630 390 IFLEFT$(L$,1)="J"THEN820 400 TN=VAL(R$):IFTN>255THEN430 410 IFTY=1ORTY=3ORTY=4ORTY=5THENOP=0P+4 420 GOTO2000 430 H%=TN/256:L%=TN-256*H%:IFTY=2ORTY=7THENO P=OP+8:GOTO470 440 IFTY=1ORTY=3ORTY=4ORTY=5THENOP=OP+12:GOT O470 450 IFTY=6ORTY=9THEN470 460 GOTO850 470 GOTO3000 480 TN=VAL(RIGHT$(R$,LL-1)) 490 IFTY=1THENOP=OP+B:GOTO2000 500 IFTY=40RTY=5THENGOTO2000 510 GOTO850 520 IFRIGHT$(R$,2)=")Y"THEN540 530 IFRIGHT$(R$,2)="X)"THEN570 540 TN=VAL(MID$(R$,2,LL-3)) 550 IFTY=1THENOP=OP+16:GOTO2000 560 GOTO850 570 TN=VAL(MID$(R$,2,LL-3)) 580 IFTY=1THENGOTO2000 590 GOTO850 600 TN=VAL(R$):TN=TN-SA-2:IFTN<-128ORTN>127T HENPRINT"TOO FAR ";:GOTO850 610 IFTN<0THENTN=TN+256 620 GOTO2000 630 IFRIGHT$(R$,2)=")Y"THEN540 640 IFRIGHT$(R$,1)="X"THEN720 650 REM *ZERO Y 660 TN=VAL(LEFT$(R$,LL-l)):IFTN>255THEN680 670 IFTY=2ORTY=5THEN730 675 IFTY=1THEN760 680 GOSUB770:IFTY=1THENOP=OP+24:GOTO710 690 IFTY=5THENOP=OP+28:GOTO710 700 GOTO850 710 GOTO3000 720 TN=VAL(LEFT$(R$,LL-1)):IFTN>255THENGOSUB 770:GOTO780 730 IFTY=2THENOP=OP+16:GOTO760 740 IFTY=1ORTY=3ORTY=5THENOP=OP+20:GOTO760 750 GOTO850 760 GOTO2000 770 H%=TN/256:L%=TN-256*H%:RETURN 780 IFTY=2THENOP=OP+24:GOTO810 790 IFTY=10RTY=30RTY=5THENOP=OP+28:GOTO810 800 GOTO850 810 GOTO3000 820 TN=VAL(R$) 830 GOSUB770 840 GOTO710 850 PRINT"{REV} ERROR ":GOTO230 1000 REM 1 BYTE INSTRUCTIONS 1010 POKESA,OP:SA=SA+1:IFH=ITHEN 1030 1020 PRINTOP:GOTO230 1030 DE = OP:GOSUB4000:PRINTH$:GOTO230 2000 REM 2 BYTE INSTRUCTIONS 2005 IFTN>256THENPRINT" INCORRECT ARGUMENT. ( #5 IN HEX IS #05)":GOTO230 2010 POKESA,OP:POKESA+1,TN:SA=SA+2:IFH=1THEN2 030 2020 PRINTOP;TN:GOTO230 2030 DE = OP:GOSUB4000:PRINTH$" "; 2040 DE = TN:GOSUB4000:PRINTH$:GOTO230 3000 REM 3 BYTE INSTRUCTIONS 3010 POKESA,OP:POKESA+1,L%:POKESA+2,H%:SA=SA+ 3:IFH=1THEN3030 3020 PRINTOP;L%;H%:GOTO230 3030 DE = OP:GOSUB4000:PRINTH$" "; 3040 DE = L%:GOSUB4000:PRINTH$" "; 3050 DE = H%:GOSUB4000:PRINTH$:GOTO230 4000 REM DECIMAL TO HEX (DE TO H$) 4010 H$="":FORM=SZTO0STEP-1:N%=DE/(16^M):DE=D E-N%*16^M:H$=H$+MID$(HE$,N%+1,1) 4020 NEXT:SZ=1:RETURN 5000 REM HEX TO DECIMAL (H$ TO DE) 5010 D=0:Q=3:FORM=1TO4:FORW=0T015:IFMID$(H$,M ,1)=MID$(HE$,W+1,1)THEN5030 5020 NEXTW 5030 Dl=W*(16^(Q)):D=D+D1:Q=Q-1:NEXTM:DE=INT( D):RETURN 6000 REM ACCEPT HEX OPCODE INPUT AND TRANSLAT E IT TO DECIMAL 6010 IFLEFT$(R$,1)="#"THENH$="00"+RIGHT$(R$,2 ):GOSUB5000:R$="#"+STR$(DE):RETURN 6020 LS=LEN(R$):AZ$=LEFT$(R$,1):ZA$=MID$(R$,L S,1):IFAZ$<>"("THEN6050 6030 IFZA$="Y"THENH$="00"+MID$(R$,2,2):GOSUB5 000:R$="("+STR$(DE)+")Y":RETURN 6040 IFZA$=")"THENH$="00"+MID$(R$,2,2):GOSUB5 000:R$="("+STR$(DE)+"X)":RETURN 6050 IFZA$="X"ORZA$="Y"THEN6070 6060 H$=LEFT$(ZO$,4-LS)+R$:GOSUB5000:R$=STR$( DE):RETURN 6070 IFLS=5THENH$=LEFT$(R$,4):GOTO6090 6080 H$="00"+LEFT$(R$,2) 6090 GOSUB5000:R$=STR$(DE)+ZA$:RETURN 20000 DATAADC1097,AND1033,ASL3002,BCC8144, BCS8176,BEQ8240,BIT7036,BMI8048 20010 DATABNE8208,BPL8016,BRK0000,BVC8080,BVS8 112,CLC0024,CLD0216,CLI0088 20020 DATACLV0184,CMP1193,CPX4224,CPY4192,DEC2 198,DEX0202,DEY0136,EOR1065 20030 DATAINC2230,INX0232,INY0200,JMP6076,JSR9 032,LDA1161,LDX5162,LDY5160 20040 DATALSR3066,NOP0234,ORA1001,PHA0072,PHP0 008,PLA0104,PLP0040,ROL3034 20050 DATAROR3098,RTI0064,RTS0096,SBC1225,SEC0 056,SED0248,SEI0120,STA1129 20060 DATASTX2134,STY2132,TAX0170,TAY0168,TSX0 186,TXA0138,TXS0154,TYA0152` Program C-3. Simple Assembler: Atari Version. `10 HX=1:REM IF HX= 0 THEN ASSEMBLY I S IN DECIMAL 20 DIM HE$(16),ZO$(3),R$(10),MN$(12> ,ZA$(1),AZ$(1),L$(3),SA$(4),H$(4) ,LR$(1) 30 OPEN #1,12,0,"E:" 50 HE$="01234567B9ABCDEF":SZ=1:ZO$=" 000" 100 PRINT "{3 {3 "; 110 DIM M$(56*3),TY(56),OP(56) 120 FOR I=1 TO 56:READ MN$:M$(I*3-2, I*3)=MN$(1,3) 122 TY(I)=VAL(MN$(4,4)):OP(I)=VAL(MN $(5)) 130 NEXT I 140 PRINT :? 150 PRINT "Immediate{5 SPACES}LDA #1 5" 155 PRINT "Absolute{6 SPACES}LDA 150 0" 160 PRINT "Zero oage{5 SPACES}LDA 15 " 165 PRINT "Accum"lator{3 SPACES}ASL" 170 PRINT "Indirect X{4 SPACES}LDA ( 15X)" 175 PRINT "Indirect Y{4 SPACES}LDA ( 15)Y" 177 PRINT "Zero page X{3 SPACES}LDA 15X" 179 PRINT "Zero page Y{3 SPACES}LDX 15Y" 180 PRINT "Absolute X{4 SPACES}LDA 1 500X" 185 PRINT "Absolute Y{4 SPACES}LDA 1 500Y" 189 PRINT :PRINT :{4 SPACES}Enter al l numbers in ": 190 IF HX=1 THEN PRINT ""; 195 PRINT "" 197 ? :? "Addresses:Use 1536-1791 ($ 0600-$06FF)":? :? 200 PRINT "{2 DEL LINE}Please enter starting":? "address for ML prog ram";:INPUT SA$:IF SA$="" THEN ? "{2 UP}";:GOTO 200 210 IF HX=1 THEN H$=SA$:GOSUB 5000:S A=DE:GOTO 217 215 SA=VAL(SA$) 217 IF SA<256 OR SA>=40960 THEN ? " {4 UP}Not ZPAGE or ROM!":? :GOTO 200 220 TA=SA:PRINT "{CLEAR}":GOTO 230 225 ? :? "{BELL}":? :IF HX=1 THEN ? "(e.g. #5 should be #05)":? 230 IF HX=1 THEN DE=SA:SZ=3:GOSUB 40 00:PRINT H$;": ";:GOTO 240 235 PRINT SA;": "; 240 TRAP 225:INPUT # 1;MN$:? "{UP}";: POKE 85,20:IF MN$="" THEN ? " {DEL LINE}";:GOTO 230 241 REM ADD NEW PSEUDO-OPS HERE 242 IF LEN(MN$)>6 THEN IF MN$(LEN(MN $)-6)="FORWARD" THEN FB=SA 243 IF MN$="RESOLVE" THEN FR=SA-FB:P OKE FB+l. FR-2: PRINT " OK":GOTO 230 244 IF MN$="POKE" THEN PRINT "ADDR, N UMBER (DEC)";:INPUT ADDR,NUM:POKE ADDR,NUM: GOTO 230 250 IF MN$="END" THEN 8000 260 L=LEN(MN$):L$=MN$(1,3) 270 FOR I=l TO 56:IF L$=M$(I*3-2,I*3 ) THEN 300 280 NEXT I 290 GOTO 850 300 REM PRIMARY OPCODE CATEGORIES 301 TY=TY(I):OP=OP(I) 305 IF FB=SA THEN TN=0:GOTO 2010 310 IF TY=0 THEN GOTO 1000 320 IF TY=3 THEN TY=1:lF L=3 THEN OP =OP+8:GOTO 1000 330 R$=MN$(5):IF HX=1 THEN GOSUB 600 0 340 LR$=R$(1,1):LL=LEN(R$):IF LR$="# " THEN 480 350 IF LR$="(" THEN 520 360 IF TY=8 THEN 600 370 IF TY=3 THEN OP=OP+8:GOTO 1000 380 IF R$(LL)="X" OR R$(LL)="Y" THEN 630 390 IF L$(1,1)="J" THEN 820 400 TN=VAL(R$):IF TN>255 THEN 430 410 IF TY=1 OR TY=3 OR TY=4 OR TY=5 THEN OP=OP+4 420 GOTO 2000 430 H=INT(TN/256):L=(TN-256*H):IF TY =2 OR TY=7 THEN OP=OP+8:GOTO 470 440 IF TY=1 OR TY=3 OR TY=4 OR TY=5 THEN OP=OP+12:GOTO 470 450 IF TY=6 OR TY=9 THEN 470 460 GOTO 850 470 G0TO 3000 480 TN=VAL(R$(2)) 490 IF TY=1 THEN OP=OP+8:GOTO 2000 500 lF TY=4 OR TY=5 THEN GOTO 2000 510 GOTO 850 520 IF R$(LL-1)=")Y" THEN 540 530 IF R$(LL-1)="X)" THEN 570 540 TN=VAL(R$(2,LL-1)) 550 IF TY=1 THEN OP=OP+16:GOTO 2000 560 GOTO 850 570 TN=VAL(R$(2,LL-1)) 580 IF TY=1 THEN GOTO 2000 590 GOTO 850 600 TN=VAL(R$):TN=TN-SA-2:IF TN<-128 OR TN>127 THEN PRINT ""; :GOTO 850 610 IF TN<0 THEN TN=TN+256 620 GOTO 2000 630 IF R$(LL-1>=")Y" THEN 540 640 IF R$(LL-1)="X" THEN 720 650 REM *ZERO Y 660 TN=VAL(R$(1,LL-1)):IF TN>255 THE N 680 670 IF TY=2 OR TY=5 THEN 730 675 IF TY=1 THEN 760 680 GOSUB 770: IF TY=1 THEN OP=OP+24: GOTO 710 690 IF TY=5 THEN OP=OP+28:GOTO 710 700 GOTO 850 710 GOTO 3000 720 TN=VAL(F$(1,LL-1)):IF T>255 THE N GOSUB 770:GOTO 780 730 IF TY=2 THEN OP=OP+16:GOTO 760 740 IF TY=1 OR TY=3 OR TY=5 THEN OP= OP+20:GOTO 760 750 GOTO 850 760 GOTO 2000 770 H=INT(TN/256):L=TN-256*H:RETURIN 780 IF TY=2 THEN OP=OP+24:GOTO 810 790 IF TY=1 OR TY==3 OR TY=5 THEN OP= OP+28:GOTO 810 800 GOTO 850 810 GOTO 3000 820 TN=VAL(R$) 830 GOSUB 770 840 GOTO 710 850 PRINT "{BELL}":GOTO 230 1000 REM 1 BYTE INSTRUCTIONS 1010 POKE SA,OP:SA=SA+1:IF HX=1 THEN 1030 1020 PRINT OP:GOTO 230 1030 DE=OP:GOSUB 4000:PRINT H$:GOTO 230 2000 REM 2 BYTE INSTRUCTIONS 2005 IF TN>256 THEN ? :? "Error--";T N;">256 ($100)":GOTO 230 2010 POKE SA,OP:POKE SA+1,TN:SA=SA+2 :IF HX=1 THEN 2030 2020 PRINT OP;" ";TN:GOTO 230 2030 DE=OP:GOSUB 4000:PRINT H$;" "; 2040 DE=TN:GOSUB 4000:PRINT H$:GOTO 230 3000 REM 3 BYTE INSTRUCTIONS 3010 POKE SA,OP:POKE SA+1,L:POKE SA+ 2,H:SA=SA+3:IF HX=1 THEN 3030 3020 PRINT OP;" ";L:" ";H:GOTO 230 3030 DE=OP:GOSUB 4000:PRINT H$;" "; 3040 DE=L:GOSUB 4000:PRINT H$;" "; 3050 DE=H:GOSUB 4000:PRINT H$:GOTO 2 30 4000 REM DECIMAL TO HEX (DE TO H$) 4010 H$="":A=INT(DE/256):IF A>0 THEN AH=INT(A/16):AL=A-AH*16:H$=HE$ (AH+1,AH+1):H$(2)=HE$(AL+1,AL+1 ) 4020 A=DE-A*256:AH=INT(A/16):AL=A-AH *16:H$(LEN(H$)+1)=HE$(AH+1,AH+1 ):H$(LEN(H$)+1)=HE$(AL+1,AL+1): SZ=1:RETURN 5000 REM HEX TO DECIMAL (H$ TO DE) 5010 D=0:Q=3:FOR M=1 TO 4:W=ASC(H$(M ))-48:IF W>9 THEN W=W-7 5030 D=D*16+W:NEXT M:DE=INT(D):RETUR N 6000 REM ACCEPT HEX OPCODE INPUT AND TRANSLATE IT TO DECIMAL 6010 IF R$(1,1)="#" THEN H$="00":H$( 3)=R$(2):GOSUB 5000:R$="#":R$(2 )=STR$(DE):RETURN 6020 LS=LEN(R$):AZ$=R$(1,1):ZA$=R$(L S):IF AZ$<>"(" THEN 6050 6030 IF ZA$="Y" THEN H$="00":H$(3)=R $(2,4):GOSUB 5000:R$="(":R$(2)= STR$(DE):R$(LEN(R$)+1)=")Y":RET URN 6040 IF ZA$=")" THEN H$="00":H$(3)=R $(2,4):GOSUB 5000:R$="(":R$(2)= STR$(DE):R$(LEN(R$)+1)="X)":RET URN 6050 IF ZA$="X" OR ZA$="Y" THEN 6070 6060 H$="":IF LS<4 THEN H$=ZO$(1,4-L S) 6065 H$(LEN(H$)+1)=R$:GOSUB 5000:R$= STR$(DE):RETURN 6070 IF LS=5 THEN H$=R$(1,4):GOTO 60 90 6080 H$="00": H$(3)=R$(1,2) 6090 GOSUB 5000:R$=STR$(DE):R$(LEN(R $)+1)=ZA$:RETURN 8000 PRINT :PRINT "*STARTS ";TA;:SZ= 3:DE=TA:GOSUB 4000:PRINT " ($"; H$;")" 8010 PRINT " ENDS{3 SPACES}";SA;:DE= SA:SZ=3:GOSUB 4000:PRINT " ($"; H$;")":END 20000 DATA ADC1097,AND1033,ASL3002,B CC8144,BCS8176,BEQ8240,BIT7036 ,BMI8048 20010 DATA BNE8208,BPL8016,BRK0000,B VC8080,BVS8112,CLC0024,CLD0216 ,CLI0088 20020 DATA CLV0184,CMP1193,CPX4224,C PY4192,DEC2198,DEX0202,DEY0136 ,EOR1065 20030 DATA INC2230,INX0232,INY0200,J MP6076,JSR9032,LDA1161,LDX5162 ,LDY5160 20040 DATA LSR3066,NOP0234,ORA1001,P HA0072,PHP0008,PLA0104,PLP0040 ,ROL3034 20050 DATA ROR3098,RTI0064,RTS0096,S BC1225,SEC0056,SED0248,SEI0120 ,STA1129 20060 DATA STX2134,STY2132,TAX0170,T AY0168,TSX0186,TXA0138,TXS0154 ,TYA0152` Return to Table of Contents | Previous Chapter | Next Chapter |