************************************************************** * MACHINE LANGUAGE TUTORIAL * * * * * * BROUGHT TO YOU BY: * * * * THE SHOALIN TEMPLE OF THE DRAGON BBS * * ([408] 739-5370) * ************************************************************** MACHINE CODE BY TOM O'BRIEN [EDITOR'S NOTE: THIS TUTORIAL FROM TOM O'BRIEN OF THE GREEN APPLE USERS GROUP IN CEDAR FALLS IOWA IS DERIVED FROM A SERIES OF LESSONS ON MACHINE LANGUAGE PROGRAMMING WHICH WERE DISTRIBUTED ON A TUTORIAL DISK PRODUCED BY THAT CLUB. I HAVE TAKEN THE LIBERTY OF ALTERING HIS WORK TO SUIT THE FORMAT OF THIS DISK. ] INTRODUCTION IT IS DIFICULT TO TELL WHERE TO START WITH SOMETHING LIKE THIS COURSE. MAYBE "COURSE" ISN'T THE RIGHT WORD. WHAT I HOPE TO BE ABLE TO DO IS TO GIVE YOU A ROADMAP WHICH YOU CAN FOLLOW TO EXPLORE THE INSIDE WORKINGS OF YOUR COMPUTER. I'LL TRY TO START OUT WITH LOTS OF DETAILS SO YOU CAN TELL WHICH WAY TO GO. AS THINGS GO ON, THE DETAILS WILL GET LEFT BEHIND. THEY WILL BE THINGS FOR YOU TO FIGURE OUT ON YOUR OWN. I'M NOT GOING TO DO THE WORK FOR YOU. I'LL TRY TO ANSWER QUESTIONS YOU HAVE AND I'LL TRY TO HELP YOU....BUT, YOU WILL HAVE TO DO THE WORK YOURSELF. STARTING WITH THE MINI-ASSEMBLER WE WILL USE THE MINI-ASSEMBLER THAT IS AVAILABLE IN INTEGER BASIC. IF YOU HAVE AN INTEGER CARD OR A LANGUAGE CARD (16K RAM CARD) OR HAVE A 64K MACHINE (EG THE APPLE //E), THEN THE MINI- ASSEMBLER IS AVAILABLE TO YOU. IF YOU HAVE AN APPLE ][ PLUS WITHOUT A 16K RAM CARD, YOU WILL NEED TO ACCESS THE MINI-ASSEM BLER FROM THE FILE ON THIS COPY OF THE IAC MACHINE LANGUAGE UTILITIES DISK. I WON'T TRY TO TELL YOU WHAT A MINI-ASSEMBLER IS AT THIS TIME, OTHER THEN IT IS A TOOL WHICH WILL HELP YOU TO CREATE MACHINE LANGUAGE PROGRAMS. LET'S START WITH A SIMPLE PROGRAM. ENTER: ]CALL-151 TO JUMP INTO THE APPLE'S MONITOR. * IS THE PROMPT CHARACTER WHICH INDICATES THAT YOU ARE IN THE HEART OF THE MACHINE. TYPE IN THE FOLLOWING: 1000:A9 C8 8D 48 06 1000G YOU SHOULD SEE THE CHARCTER "H" ON THE THE RIGHT HAND SIDE IN THE MIDDLE OF THE SCREEN. TYPE IN THE FOLLOWING: 1000:A9 C5 8D 48 06 1000G YOU SHOULD NOW SEE THE CHARACTER "E" WHERE THE "H" WAS LOCATED. BY NOW YOU MAY BE WONDERING WHERE THIS IS LEADING TO. MACHINE CODE IS A LOT CLOSER TO THE ACTUAL HEART OF THE MACHINE THAN IS BASIC. THERE ARE SOME ADDRESSES THAT YOU MUST KEEP TRACK OF (EG $0648 IS AN ADDRESS IN THE LOW-RES SCREEN). THERE ARE NUMBERS WHICH YOU MUST KEEP TRACK OF (EG. $C8 IS "H" AND $C5 IS "E"). YOU MUST THINK IN TERMS OF HEXADECIMAL INSTEAD OF DECIMAL. $1000 IN HEX IS 4096 IN DECIMAL. 4096 256 16 1 1000 100 10 1 $100 IN HEX IS 256 DECIMAL $ 16 IN HEX IS 22 DECIMAL $ A IN HEX IS 10 DECIMAL IN BASIC WE COULD HAVE THE STATEMENT GET A$ IN ASSEMBLY LANGUAGE WE WOULD HAVE SOMETHING LIKE: 1000: LDA $C000 1003: BPL $1000 AS WE WILL SEE IN THE LESSON ON THE KEYBOARD, $C000 IS A PHYSICAL ADDRESS OR LOCATION WHICH REFERS TO THE APPLE'S KEYBOARD. WHEN A KEY HAS BEEN PRESSED THE ADDRESS $C000 WILL BE NEGATIVE. (ANOTHER WAY OF SAYING THE SAME THING IS THAT ITS HIGH BIT WILL BE SET OR EQUAL TO ONE WHEN A KEY IS PRESSED.) TO RESET THE KEYBOARD SO THAT WE CAN TELL WHEN ANOTHER KEY HAS BEEN PRESSED WE HAVE TO LOOK AT ADDRESS $C010. BY STORING SOMETHING OR GETTING SOMETHING AT THAT ADDRESS ($C010), THE COMPLEMENTARY LOCATION $C000 IS NOW READY TO CAPTURE AND HOLD THE CODE FOR THE NEXT KEY THAT IS PRESSED. (STORING OR WRITING TO $C010 CAUSES THE HIGH BIT AT $C000 WILL GO LOW [=0]). IT MIGHT BE PARENTHETICALLY ADDED THAT THE APPLE II REFERENCE MANUAL IS OF GREAT HELP IN UNDERSTANDING MACHINE CODE ON THE APPLE. THE MANUAL HAS CHARTS AND LISTS ON THE ACTUAL ADDRESSES THAT WE WILL NEED TO KNOW. JUST LIKE YOU MUST KNOW SOMEONE'S MAILING ADDRESS TO SEND THEM A LETTER, YOU MUST KNOW YOUR COMPUTER'S ADDRESSES TO DISPLAY SOMETHING ON THE SCREEN. (IT HAS MORE THAN ONE SCREEN). THE APPLE II REFERENCE MANUAL WILL THEREFORE BE USED TO FIND LOCATIONS INSIDE THE COMPUTER LIKE WE WOULD USE A PHONE BOOK TO LOOK UP A FRIENDS ADDRESS. LETS GO INTO THE MINI-ASSEMBLER: ]INT > CALL -151 * F666G NOW ENTER: !1000:LDA #$C1 STA $0468 LDA #$C2 STA $0469 AS YOU TYPE IN THE ABOVE, YOU WILL SEE: 1000- A9 C1 LDA #$C1 1002- 8D 68 04 STA $0468 1005- A9 C2 LDA #$C2 1007- 8D 69 04 STA $0469 A WORD OF EXPLANATION: 1000 IS THE ADDRESS OF A9 WHICH IS THE MACHINE CODE FOR LOAD THE ACCUMULATOR (LDA) IMMEDIATELY. 1001 IS THE ADDRESS OF C1 WHICH IS THE HEXADECIMAL NUMBER THAT WILL BE LOADED INTO THE ACCUMULATOR. LDA #$C1 IS A EASIER WAY FOR US TO DEAL WITH THE MACHINE. 1002 IS THE ADDDRESS OF 8D WHICH IS THE MACHINE CODE FOR STORE WHAT IS IN THE ACCUMULATOR (STA) AT THE ABSOLUTE ADDRESS IN THE NEXT TWO BYTES, IN THIS CASE 1003 AND 1004. IF THIS DOESN'T MAKE SENSE TO YOU, PLEASE KEEP AT IT. HOPEFULLY AS YOU SEE AND FOLLOW MORE EXAMPLES, THE FOG WILL LIFT A LITTLE. NOW LET'S RUN THE ROUTINE BY JUMPING TO MEMORY LOCATION $1000 WITH THE MINI-ASSEMBLER COMMAND ! $1000G (THIS TELLS THE APPLE TO GO TO LOCATION $1000 AND START EXECUTING WHAT'S THERE.) WHAT HAPPENED? DID ANY CHARACTERS APPEAR ON THE SCREEN? WERE THEY "A" AND "B"? WERE THEY NEXT TO EACH OTHER? IN STARTING TO LEARN MACHINE LANGUAGE PROGRAMMING, IT IS COMMON TO USE THE LOW-RESOLUTION SCREEN... GETTING TO KNOW HOW WE CAN CONTROL WHAT IS ON THE SCREEN. WE WILL INPUT DATA FROM THE KEYBOARD AND DISPLAY IT ON THE SCREEN. LETS' GO BACK TO THE MINI-ASSEMBLER AND ENTER: *F666G ! 1000: LDA $C000 BPL $1000 STA $0468 LDA $C010 JMP $1000 AS YOU TYPE IN THE ABOVE, YOU SHOULD SEE 1000- AD 00 C0 LDA $C000 1003- 10 FB BPL $1000 1005- AD 68 04 STA $0468 1008- AD 10 C0 LDA $C010 100B- 4C 00 10 JMP $1000 ! $1000G NOW PRESS DIFFERENT KEYS ON YOUR COMPUTER. TRY CONTROL CHARACTERS... WHAT DOES ESCAPE LOOK LIKE? WHAT DOES A RETURN LOOK LIKE? CAN YOU GET OUT OF THE PROGRAM? DOES CONTROL-C STOP IT? ONE THING YOU PROBABLY KNOW IS THAT IF YOU HAVE AN OLD APPLE ][ WITHOUT THE AUTOSTART ROM, HITTING THE RESET KEY WILL EXIT FROM THE MINI-ASSEMBER INTO THE MONITOR (* PROMPT). WITH THE NEWER AUTOSTART ROM MADE IN THE PAST COUPLE OF YEARS, EXITING THE MONITOR CAN BY DONE BY THE RESET WHICH DUMPS YOU TO APPLESOFT AND THEN RE-ENTER THE MONITOR BY >CALL -151 OR REQUIRES THE COMMAND: ! $FF69G WHICH TELLS THE COMPUTER TO GO TO THE MACHINE LANGUAGE LOCATION $FF69 AND DO WHATEVER IS THERE. LET'S LOOK AT THE LAST PROGRAM WE RAN. 1000- AD 00 C0 LDA $C000 THIS COMMAND MEANS LOAD THE ACCUMULATOR WITH THE VALUE OF THE BYTE THAT IS AT HEXIDECIMAL ADDRESS $C000. THIS IS THE ADDRESS OF THE KEYBOARD, AND SO THIS LINE OF CODE LOOKS AT THE KEYBOARD. THE NEXT LINE IS: 1003- 10 FB BPL $1000 WHICH IS BRANCH POSITIVE TO $1000 (OR BRANCH ON PLUS TO $1000). 10 IS THE OP CODE...BRANCH POSITIVE FB IS THE OFFSET....HOW FAR TO BRANCH TO DIGRESS TO THE PROGRAM COUNTER (PC) FOR A MOMENT, WHEN THE MICROPROCESSOR GETS CODE, THE PROGRAM COUNTER POINTS AT 1005, WHICH IS ONE BYTE PAST THE INSTRUCTION BEING EXECUTED. WE ADD $FB TO THE LOW BYTE OF THE PROGRAM COUNTER, $05 $FB+$05= $00 DISREGARD CARRY PUTTING THE PROGRAM COUNTER, PC, BACK TOGETHER, WE BRANCH TO MEMORY LOCATION $1000 IF THE ACCUMULATOR IS POSITIVE AFTER BEING LOADED WITH THE VALUE OF THE BYTE THAT IS IN $C000. THIS CAUSES THE PROGRAM TO STAY IN THE LOOP 1000- LDA $C000 1003- BPL $1000 UNTIL A KEY IS PRESSED. THE EQUIVALENT BASIC PROGRAM WOULD BE: 10 X = PEEK ( - 16384 ) 20 IF X >= 128 GOTO 10 30 REM CONTINUE... IF YOU ARE INTERESTED IN TECHNICAL DESCRIPTIONS, HERE IS WHAT HAPPENED. PRESSING A KEY SETS CLOCKS THE "D" VALUE OF A D- FLIP FLOP INTO THE "Q" OUTPUT. SINCE "D" IS TIED HIGH, THE "Q" OUTPUT GOES HIGH. THIS IS BIT 8 (THE HIGH BIT) OF WHAT IS AT $C000. FOR THOSE OF YOU WHO KNOW HARDWARE, THE FLIP-FLOP IS A 74LS74 AT LOCATION B-10 ON THE APPLE'S MOTHERBOARD. ONCE THE KEY IS PRESSED AND $C000 IS NEGATIVE (A NUMBER IS NEGATIVE IF ITS HIGH BIT IS SET), WE FALL THROUGH THE BRANCH INSTRUCTION 1005- STA $0468 THIS INSTRUCTS THE CPU (MICROPROCESSOR) TO STORE WHAT IS IN THE ACCUMULATOR AT LOCATION $0468. $0468 IS ONE LOCATION IN THE LOW- RES SCREEN, PAGE ONE. THE NEXT INSTRUCTION IS 1008- LDA $C010 OR LOAD THE ACCUMULATOR WITH WHAT IS AT $C010. THIS WILL CLEAR THE FLIP-FLOP THAT WAS SET WHEN A KEY WAS PRESSED. THE ADDRESS $C010 IS DECODED BY SEVERAL CHIPS AND SENT THROUGH A NOR GATE (74LS02 AT LOCATION A12) TO THE CLEAR INPUT OF THE FLIP-FLOP AT LOCATION B10. NOW WHEN WE LOOK AT LOCATION $C000 THE HIGH BIT WILL BE LOW AND THE NUMBER WE SEE WILL BE POSITIVE. (ONE NOTE:THE HIGH BIT OF THE FLIP-FLOP IS HELD LOW DURING POWER-UP OR A RESET) THE NEXT INSTRUCTION IS 100B- JMP $1000 OR JUMP TO LOCATION $1000 WHICH GETS THE NEXT KEYSTROKE AND STARTS THE PROCESS OVER AGAIN. LESSON THREE LET'S USE A SHORT MACHINE CODE PROGRAM WITH A BASIC PROGRAM. GO TO BASIC (USE INTEGER BASIC IF YOU HAVE IT, TO AVOID RELOADING THE MINI-ASSEMBLER AGAIN). 10 CALL 4096 20 END GO TO MONITOR CALL-151 * F666G (OR WHATEVER CALL GETS THE MINI-ASSEMBLER) ! 1000: LDA #$B1 1002: STA $0770 1005: RTS * $9DBFG RETURN TO BASIC THRU DOS RUN WHAT HAPPENED? DID YOU SEE "1" ON THE SCREEN IN THE LOWER RIGHT HAND SIDE? LINE 10....CALL 4096 IF WE CONVERT 4096 TO HEXIDECIMAL WE END WITH $1000. THIS IS THE ADDRESS ON THE SHORT MACHINE CODE PROGRAM WE WROTE. THE BASIC LINE INSTRUCTED TO COMPUTER TO JUMP TO THE MACHINE LANGUAGE SUBROUTINE AT MEMORY LOCATION 4096 AND EXECUTE THE INSTRUCTIONS THERE. OUR MACHINE CODE PROGRAM LOADS THE ACCUMULATOR WITH THE HEX NUMBER $B1 AND THEN STORES THE ACCUMULATOR IN THE LOW-RES SCREEN AT LOCATION $0770. WE THEN DID A "RTS" WHICH STANDS FOR RETURN FROM SUBROUTINE. THE PROGRAM RETURNS TO THE PROGRAM THAT CALLED IT, WHICH IN THIS CASE IS THE SHORT BASIC PROGRAM. LATER WE WILL LOOK AT WHAT IS CALLED THE STACK AND THE STACK POINTER AND SEE HOW TO USE IT. (THE STACK IS THE AREA OF MEMORY FROM $0100 TO $01FF. THE STACK POINTER IS A NUMBER BETWEEN $00 AND $FF.) MEANWHILE, LET'S DO ANOTHER SHORT PROGRAM. GO TO MONITOR. CALL-151 AND ENTER THE MINI-ASSEMBLER WITH *F666G (OR WHEREVER YOU HAVE LOCATED IT. IT MAY BE NECESSARY TO RELOAD THE MINI-ASSEMBLER IF YOU WERE IN APPLESOFT.) ! NOW WE ARE IN THE MINI-ASSEMBER ! 1000: LDA #$00 STA $0400 INC $1001 INC $1003 JMP $1000 THIS SHOULD LOOK LIKE: 1000- A9 00 LDA #$00 1002- 8D 00 04 STA $0400 1005- EE 01 10 INC $1001 1008- EE 03 10 INC $1003 100B- 4C 00 10 JMP $1000 THE FIRST LINE: LDA #$00 LOAD THE ACCUMULATOR IMMEDIATELY WITH THE HEX NUMBER $00. THE SECOND LINE: STA $0400 STORE THE VALUE IN THE ACCUMULATOR IN MEMORY LOCATION $0400. THE THIRD LINE: INC $1001 INCREMENT MEMORY LOCATION $1001 OR, SAID IN ANOTHER WAY, ADD ONE TO THE VALUE THAT IS IS IN MEMORY LOCATION $1001. THE FOURTH LINE: INC $1003 INCREMENT MEMORY LOCATION $1003 OR, SAID ANOTHER WAY, ADD ONE TO THE VALUE IN MEMORY LOCATION $1003. THE FIFTH LINE: JMP $1000 JUMP TO MEMORY LOCATION $1000 WHICH IS THE START OF OUR PROGRAM. BEFORE YOU RUN THIS PROGRAM, TRY TO STEP THROUGH THE PROGRAM. CAN YOU PREDICT WHAT IT IS GOING TO DO? NOW, GO TO BASIC (INTEGER IF POSSIBLE) > CALL-151 * F666G ! TYPE IN THE PROGRAM. WE ARE IN THE MINI-ASSEMBLER. WHEN YOU ARE FINISHED, ENTER THE MONITOR WITH ! $FF69G OR GO TO BASIC AND ENTER THE MONITOR WITH > CALL -151 * 1000G WILL START THE PROGRAM. DID IT DO WHAT YOU THOUGHT IT WOULD DO? DO A LIST OF THE PROGRAM: * 1000L DOES IT LOOK THE SAME AS WHEN YOU TYPED IT IN? WHAT IS DIFFERENT? MEMORY LOCATIONS $1001 AND $1003 HAVE BEEN CHANGED BY THE PROGRAM. THIS IS A PROGRAM THAT CHANGES ITSELF AS IT RUNS! WE WILL GET INTO OTHER EXAMPLES WHERE THIS IS HELPFUL AS THESE LESSIONS CONTINUE. LESSON 4...COMPUTER NUMBERS BINARY, HEXIDECIMAL AND DECIMAL ARE NUMBER SYSTEMS HAVING DIFFERENT BASES. ALL ARE USED IN DEALING WITH COMPUTERS. THE FIRST TWO, BINARY AND HEXADECIMAL, MAY BE NEW TO SOME PEOPLE. LET'S TALK ABOUT DECIMAL NUMBERS FIRST. 129 IS ONE HUNDRED TWENTY NINE 129 = 1*100 + 2*10 + 9*1 23 IS TWENTY THREE 23 = 2*10 + 3*1 WE KNOW THAT DECIMAL NUMBERS ARE POWERS OF TEN. 10000 1000 100 10 1 EACH ONE IS 10 TIMES THE ONE BEFORE IT. 1200 IS TWELVE HUNDRED 1200 = 1*1000 + 2*100 + 0*10 + 0*1 IN BINARY NUMBERS THE ONLY SYMBOLS WHICH ARE USED ARE 0 AND 1. COUNTING IN BINARY (AS SHOWN FROM RIGHT TO LEFT) IS: 2048 1024 512 256 128 64 32 16 8 4 2 1 WHERE WE CAN SEE THAT EACH NUMBER IS 2 TIMES THE ONE BEFORE (GOING RIGHT TO LEFT). 3 = 1*2 + 1*1 9 = 1*8 + 0*4 + 0*2 + 1*1 16 = 1*16 + 0*8 + 0*4 + 0*2 + 0*1 THE DECIMAL NUMBER 3 IS 11 IN BINARY. OR ANOTHER WAY, 3(BASE 10)= 11 (BASE 2) 9 (BASE 10) = 1001 (BASE 2). THE DECIMAL NUMBER 9 EQUALS THE BINARY NUMBER 1001. IF YOU HAVE BEEN FOLLOWING THIS, DO YOU KNOW THE ANSWER TO 101 (BASE 2) = ?????? (BASE 10) WHAT HAVE WE SEEN BEFORE? EACH ONE IS TWICE THE ONE BEFORE.... 16 8 4 2 1 SO THAT 101 STANDS FOR 1*4 + 0*2 + 1*1 IN DECIMAL OR 5. YOU MIGHT BE WONDER WHY YOU WOULD WANT TO KNOW THIS. YOU DO NOT NEED TO KNOW THIS, BUT IT CERTAINLY HELPS. THE 6502 PROCESSOR HAS WHAT IS CALLED A STATUS REGISTER, "P". MOST OF THE 6502 CPU INSTRUCTIONS AFFECT THE STATUS REGISTER P. FOR EXAMPLE, IF WE HAD JUST EXECUTED THE INSTRUCTION LDA #$00 (LOAD THE ACCUMULATOR IMMEDIATELY WITH THE HEXIDECIMAL NUMBER 00), THE P REGISTER WOULD CHANGE TO REFLECT THE ZERO. BIT 1 WOULD BE SET (EQUAL TO ONE). THE P REGISTER MIGHT BE 2 (BASE 10) OR 00000010 (BASE 2). WE WILL EXAMINE THIS MORE AS WE CONTINUE, SO IF YOU DO NOT FEEL COMFORTABLE AT THIS POINT, DON'T FEEL LEFT OUT. LESSON 5 : THE 6502 PROCESSOR LET'S NOW EXAMINE DIFFERENT PARTS OF THE ANATOMY OF THE 6502 MICROPROCESSOR. WE WILL TALK ABOUT THE ACCUMUATOR, INDEX REGISTER X, INDEX REGISTER Y, PROGRAM COUNTER, STACK POINTER, AND THE PROCESSOR STATUS REGISTER P. IF WE WERE TO TALK ABOUT THE APPLE II AS A LARGE POSTOFFICE, THEN THE ADDRESS OF A MEMORY LOCATION WOULD BE LIKE THE NUMBER OF A POSTOFFICE BOX. FOR EXAMPLE, WE SAY THAT $C000 IS THE ADDRESS OF THE MEMORY LOCATION THAT IS CHANGED BY THE KEYBOARD. ANOTHER EXAMPLE IS THAT $400 IS THE ADDRESS OF THE FIRST BYTE OF PAGE ONE OF THE LOW-RES SCREEN, AT THE TOP LEFT CORNER OF THE SCREEN. IN A POSTOFFICE THERE ARE SORTING BINS OR BOXES WHICH SERVE AS TEMPORARY PLACES TO KEEP THINGS. LIKEWISE IN THE APPLE, THE ACCUMULATOR, INDEX REGISTER X AND INDEX REGISTER Y CAN BE COMPARED TO THESE TEMPORARY PLACES TO KEEP LETTERS. WE CAN PUT NUMBERS IN THEM AND TAKE NUMBERS OUT OF THEM. ONE DIFFERENCE IS THAT WHEN WE TAKE WHAT IS IN THEM AND STORE THAT NUMBER ELSEWHERE, THAT ORIGINAL NUMBER IS STILL LEFT IN THE REGISTER. (FOR EXAMPLE, WE CAN TAKE THE NUMBER IN THE ACCUMULATOR AND STORE IT ELSEWHERE, AND IT IS STILL PRESENT IN THE ACCUMULATOR.) THE PROCESSOR STATUS REGISTER P IS RATHER LIKE A BLACKBOARD WHERE WE MIGHT MAKE A CHECK MARK IF THE LETTER WE PICKED UP WAS AN AIRMAIL LETTER, WHILE WE WOULD REMOVE THAT CHECK MARK IF THE NEXT LETTER WE PICK UP IS NOT AN AIRMAIL LETTER. SOME EXAMPLES OF HOW TO USE THE MOST IMPORTANT OF THE REGISTERS IN THE 6502, THE ACCUMULATOR, ARE AS FOLLOWS: STA $05 STORE WHAT IS IN THE ACCUMULATOR IN MEMORY LOCATION $05 STA $0400 STORE WHAT IS IN THE ACCUMULATOR IN MEMORY LOCATION $0400 LDA $0568 LOAD THE ACCUMULATOR WITH WHAT IS IN MEMORY LOCATION $0568 LESSON 6 : KEYBOARD ONE OF THE THINGS YOU NEED TO KNOW IF YOU ARE GOING TO PRINT MESSAGES ON THE SCREEN IS THE LIST OF ASCII CODES FOR THE DIFFERENT LETTERS. DID YOU KNOW THE ASCII CODE FOR "1" IS $B1 (HEXADECIMAL)? ($B1 = 11*16 + 1*1 = 177 ). THIS INFORMATION CAN BE FOUND ON PAGE SEVEN OF THE APPLE II REFERENCE MANUAL. LOCATED THERE IS TABLE 2, WHICH IS A LIST OF THE APPLE II KEYBOARD CHARACTERS AND THEIR ASSOCIATED ASCII CODES. LET'S WRITE A SHORT MACHINE CODE PROGRAM TO CHECK THE TABLE. TO DO THAT, WHAT THINGS DO WE NEED TO KNOW? 1) THE MEMORY LOCATION OF THE KEYBOARD 2) A WAY TO PRINT TO THE SCREEN $C000 IS THE MEMORY LOCATION INSIDE THE APPLE II WHICH HOLDS THE CODE OF THE LAST KEY PRESSED. $FDF0 IS A ROUTINE IN THE MONITOR ROM THAT WILL PRINT TO THE SCREEN. $FDDA IS A ROUTINE IN THE MONITOR ROM THAT WILL PRINT HEXADECIMAL NUMBERS TO THE SCREEN. NOW LETS'S WRITE A PROGRAM! CALL-151 (TO GO INTO MONITOR) *F666G (USE THE MINI-ASSEMBLER) !1000:LDA $C000 (LOAD THE ACCUMULATOR WITH WHAT IS IN THE KEYBOARD) JSR $FDF0 (JUMP TO THE SUBROUTINE AT $FDF0, USING THE MACHINE CODE PROGRAM THAT IS IN THE MONITOR ROM) JMP $1000 (JUMP TO THE START AND DO IT AGAIN) NOW RUN THE ABOVE PROGRAM BY EXITING THE MINI-ASSEMBLER AND THEN GOING TO LOCATION $1000: ! $1000G DID THE SCREEN FILL WITH CHARACTERS? DID IT CHANGE IF YOU PRESSED ANY KEY? LET'S MAKE THE PROGRAM A LITTLE BETTER. GET INTO THE MINI-ASSEMBLER *F666G !1000:LDA $C000 LOAD THE ACC WITH KEYBOARD DATA BPL $1000 GOTO $1000 IF THE KEYBOARD DATA IS POSITIVE. WHEN A KEY IS PRESSED THE HIGH-BIT IN $C000 WILL BE "1"...WHICH MAKES IT A NEGATIVE NUMBER TO THE 6502 MICROPROCESSOR CHIP INSIDE YOUR APPLE. JSR $FDF0 USE THE MONITOR ROUTINE TO PRINT TO THE SCREEN LDA $C010 CLEAR THE KEYBOARD STROBE. THIS MAKES THE HIGH-BIT IN $C000 ="0"..WHICH MAKES IT A POSITIVE NUMBER TO YOUR APPLE. JMP $1000 DO IT AGAIN ! $1000G WILL RUN THE PROGRAM NOW, IF THINGS ARE RIGHT, EVERYTIME YOU PRESS A KEY YOU SHOULD SEE IT ON THE SCREEN. LET'S MAKE OUR PROGRAM A LITTLE LONGER. *F666G GOTO THE MINI-ASSEMBER !1000: LDA $C000 BPL $1000 JSR $FDF0 LDA #$A0 THIS IS A BLANK " " JSR $FDF0 PRINT IT ON SCREEN LDA $C010 JMP $1000 RUN THAT BY GOING TO $1000. ! $1000G NOW, A PROGRAM THAT IS EVEN LONGER: *F666G !1000:LDA $C000 BPL $1000 JSR $FDF0 LDA #$A0 JSR $FDF0 LDA $C000 JSR $FDDA PRINT HEXIDECIMAL NUMBER LDA $C010 JMP $1000 NOW, WHEN YOU RUN THIS PROGRAM, YOU SHOULD SEE ALL THE VALUES IN THE TABLE ON PAGE 7 IN YOUR APPLE II REFERENCE MANUAL. MAYBE, A COUPLE WORDS OF EXPLANATION ARE NEEDED. JSR $FDF0 TELLS THE APPLE TO JUMP TO THE SUBROUTINE LOCATED AT $FDF0 AFTER SAVING THE RETURN ADDRESS, AND EXECUTE THE MACHINE CODE LOCATED THERE. THE PROGRAM JUMPS TO LOCATION $FDF0 AND DOES THE INSTRUCTION AT THAT LOCATION. THIS IS A PROGRAM ALREADY IN EXISTANCE WHICH WE WILL USE TO MAKE OUR PROGRAM SHORTER. LESSON 7 : INDEXED ADDRESSING LET'S FIND AN EXAMPLE OF SOMETHING WE KNOW ABOUT IN ORDER TO DESCRIBE THIS FORM OF ADDRESSING. ALL OF US IN GIVING DIRECTIONS TO SOMEONE HAS SAID SOMETHING LIKE "IT'S THE THIRD HOUSE ON THE LEFT AFTER YOU PASS THE STOPLIGHT". INDEXED ADDRESSING IS THE SAME TYPE THING. THE INDEX WOULD BE LIKE "IT'S THE THIRD HOUSE ON THE LEFT ". THE BASE ADDRESS IS LIKE "AFTER YOU PASSED THE STOPLIGHT". LDA $4000,X LOAD THE ACCUMULATOR REGISTER (LDA) WITH WHAT IS IN THE MEMORY LOCATION X ADDRESSES AFTER THE ADDRESS $4000. IF X=$05, THEN WE WOULD BE TALKING ABOUT ADDRESS $4000+$05 OR $4005. THE INDEX IS THE REGISTER X. THE BASE ADDRESS (IN THIS CASE ) IS $4000. WHY? WHY DO YOU WANT TO KNOW WHAT THIS DOES? EXAMPLE: SUPPOSE WE HAD 5 NUMBERS IN MEMORY LOCATIONS $3500, $3501, $3502, $3503 AND $3504... AND THAT WE WANT TO MOVE THEM TO $0408, $0409, $040A, $040B AND $040C. WE COULD DO IT LIKE THIS: LDA $3500 LOAD THE A-REG WITH WHAT IS IN $3500 STA $0408 STORE WHAT IS IN REG-A AT MEMORY LOCATION $0408 LDA $3501 LOAD THE ACCUMULATOR WITH WHAT IS IN $3501 STA $0409 STORE THE ACC IN MEMORY LOCATION $0409 LDA $3502 LOAD ACCUMULATOR STA $040A STORE ACC IN $040A LDA $3503 LOAD ACCUMULATOR STA $040B STORE ACC IN $040B LDA $3504 LOAD THE ACCUMULATOR WITH WHAT IS IN MEMORY LOCATION $3504 STA $040C STORE THE ACCUMULATOR IN MEMORY LOCATION $040C. AT THIS POINT YOU MAY WANT TO GO TO THE MINI-ASSEMBER AND ENTER THE ABOVE PROGRAM INTO MEMORY AT $1000 AND PUT SOME NUMBERS IN $3500...$3504 AND SEE IF THE NUMBERS ARE MOVED. DID THE SCREEN CHANGE WHEN YOU RAN THE PROGRAM? GOOD...IF IT DID. RUN IT AGAIN WITH $C8 IN $3500, $C5 IN $3501, $CC IN $3502, $3503, AND $CF IN $3504. DID "HELLO" SHOW UP ON THE SCREEN? LET'S DO THE SAME PROGRAM...MOVE $3500...$3504 TO $0408...$040C. USE THE INDEX ADDRESSING INSTRUCTION. LDX #$00 SET THE X-REGISTER EQUAL TO ZERO...OR ...LOAD X-REGISTER IMMEDIATELY WITH $00. LDA $3500,X LOAD ACC WITH WHAT IS X BYTES PAST ADDRESS $3500. LDA ( $3500+$00) LDA $3500 STA $0408,X STORE THE ACC AT X MEMORY LOCATIONS PAST $0408...STORE THE ACCUMULATOR AT $0408 INDEXED BY THE X-REGISTER. INX INCREMENT THE X REGISTER BY ONE. SINCE IT WAS ZERO, IT IS NOW $0+$1=$1. LDA $3500,X LOAD THE ACC WITH WHAT IS THE MEMORY LOCATION X BYTES AFTER $3500... OR SINCE X=$01... LOAD THE ACC WITH WHAT IS AT $3501 STA $0408,X STORE THE ACC AT $0408 INDEXED BY THE X-REGISTER... INX X = $01 +$01 = $02 LDA $3500,X STA $0408,X STA $0408+$02 STA $040A INX X=$02 + $01 = $03 LDA $3500,X $3500+$03=$3503 STA $0408,X $0408+$03=$040B INX LDA $3500,X STA $0408,X THIS PROGRAM WILL DO THE SAME AS THE PROGRAM WE LOOKED AT BEFORE. LETS LOOK AT IT ONCE AGAIN. LDX #$00 LDA $3500,X STA $0408,X INX LDA $3500,X STA $0408,X INX LDA $3500,X STA $0408,X INX LDA $3500,X STA $0408,X INX LDA $3500,X STA $0408,X NOTICE THAT WE USED "LDA $3500,X" AND "STA $0408,X" 5 TIMES ...ONCE EACH TIME WE WANTED TO MOVE A NUMBER. LETS WRITE ONE MORE PROGRAM TO DO THE SAME THING. (THIS ONE WILL REQUIRE AN ASSEMBLER.) LDX #$00 LINE2 LDA $3500,X STA $0408,X INX CPX #$05 BNE LINE2 NOW THE PROGRAM IS SHORTER. WE ADDED TWO NEW INSTRUCTIONS... CPX #$05 BNE LINE2 CPX #$05 COMPAGE THE X-REGISTER WITH THE NUMBER $05 BNE LINE2 IF THE X-REGISTER DOES NOT EQUAL $05, THEN GOTO LINE2. IF WE WANTED TO MOVE $53 NUMBERS, OUR LATEST PROGRAM IS EASIER TO WRITE... LDX #$00 LINE2 LDA $3500,X STA $0408,X CPX #$53 BNE LINE2 AND I LIKE TO DO THINGS THE EASY WAY. THIS WAS ONE EXAMPLE OF HOW TO USE INDEXED ADDRESSING, AND OBVIOUSLY THERE ARE MANY OTHER WAYS TO USE IT. LESSON 8: THE STACK THE "STACK" CAN BE COMPARED TO A NOTE PAD USED TO WRITE THINGS DOWN ON... NOTES THAT TELLS US THINGS TO DO. IF WE HAVE FOUR OR FIVE THINGS TO DO IN ONE DAY WE MIGHT WRITE THEM DOWN IN OUR NOTE PAD. IF THE APPLE ][ HAS ONE OR MORE SUBROUTINES TO DO, IT WRITES DOWN IN THE "STACK" WHAT TO DO. IT IS SORT OF LIKE WRITING A NOTE ON A PIECE OF PAPER AND THEN PLACING THE NOTE ON A SPINDLE. LATER, WHEN WE THING OF SOMETHING ELSE WE SHOULD DO WE PUT ANOTHER NOTE ON THE SPINDLE. THEN, WHEN WE GET TIME TO DO THINGS, WE TAKE THE TOP NOTE OFF THE SPINDLE AND DO IT... THEN THE NEXT NOTE OFF THE SPINDLE ... FIRST ON ------- LAST OFF SUPPOSE, FOR AN EXAMPLE, OUR STACK LOOKED LIKE : 01FF C1 01FE C8 01FD 23 <-- STACK POINTER NOTE: THE STACK POINTER POINTS TO THE NEXT AVAILABLE SPACE. IF OUR PROGRAM LOOKED LIKE: C11A: A9 8D LDA #$89 C11C: 20 58 FF JSR $FF58 C11F: BA TSX WHEN THE COMPUTER GOT TO THE JUMP TO SUBROUTINE (JSR) AT $FF58, IT WOULD PUT THE HIGH BYTE OF THE ADDRESS OF THE LAST PART OF THE JSR INSTRUCTION ON THE STACK FIRST 01FF C1 01FE C8 01FD 23 01FC C1 <-- STACK POINTER AND THEN THEN LOW BYTE 01FF C1 01FE C8 01FD 23 01FC C1 01FB 1E <-- STACK POINTER ON THE STACK. NOTICE THAT THE ADDRESS $C11E IS ON THE BOTTOM OF THE STACK... THIS IS THE ADDRESS OF THE LAST PART OF THE JSR $FF58 INSTRUCTION.... NOW THE COMPUTER WOULD GO TO THE SUBROUTINE AT $FF58, DO WHAT IT IS TOLD TO DO, AND WHEN IT COMES ACROSS A RETURN FROM SUBROUTINE (RTS) INSTRUCTION, IT WILL GET THE LOW BYTE $1E FROM THE BOTTOM OF THE STACK $01FB AND THEN IT WILL INCREMENT THE STACK POINTER AND GET THE HIGH BYTE $C1 OFF THE STACK $01FC. IT WILL THEN HAVE THE ADDRESS $C11E INTERNALLY TO THE CPU AND WILL PLACE THEM IN THE PROGRAM COUNTER, ADD ONE $C11E +$01 = $C11F AND THE GOTO THAT ADDRESS TO CONTINUE DOING INSTRUCTIONS.... PLEASE NOTICE THAT $C11F IS THE ADDRESS ON THE INSTRUCTION THAT WAS JUST AFTER THE JUMP TO SUBROUTINE INSTRUCTION (JSR $FF58).