Classic Computer Magazine Archive COMPUTE! ISSUE 32 / JANUARY 1983 / PAGE 160

Apple Machine Language Memory Aid

K. Lourash, Decatur, IL

"ML Helper" is a utility developed to assist fledgling Apple machine language programmers in studying 6502 object code when the original source code is not available, and also in adapting that code to their particular needs and systems. This program also works as is on OS1 and can easily be modified for any Microsoft BASIC.

Options are offered in this program to list and modify zero page usage, to list and modify absolute addressing references, and to relocate the code under examination. Although written in Microsoft floating-point BASIC, this utility is readily converted to the other popular dialects. In fact, while my system is OSI, the listing is for Apple simply to involve a wider audience.

You may save ML Helper without REMarks. If you do, notice that line 31 may be incorporated into line 29, and line 35 into line 33, for increased program optimization. However, do not tamper with the "NEXT A" statement of line 51, since ML Helper will exit a loop without completing it; a simple "NEXT" there is insufficient.

In the interest of brevity, I chose to do no error checking of input from the keyboard. Thus it's easy to become careless and obtain seemingly inexplicable program performance. Also, when using hexadecimal notation, I assumed you won't prefix an address with the "$" symbol. Furthermore, leading zeros are harmless, but quite unnecessary. No relocate is foolproof. Hence, ML Helper does not resolve the indirect JMP or the technique of jumping with an RTS once the stack has been prepared. In other words, jump tables and data blocks are moved unchanged.

Disassemble And Relocate

When up and running, ML Helper emulates a disassembler, examining the address range you've specified for valid 6502 operation codes. When they are found, the program logic proceeds to list or modify the zero page references, to list external absolute references, to modify absolute references, or to move code and modify addresses for a successful relocate, whichever option is operative.

Bytes determined to be invalid instruction code sequences are assumed to form data tables. A data table finder, as such, is always active and can actually become an unspecified sixth option to locate unknown data table areas.

At this point I set an arbitrary criterion — namely, that wherever there occurs a block of six or fewer consecutive bytes of executable code, the data table finder should, nonetheless, report that block of code as part of a data table area. If this standard proves unsuitable for your requirements, then change the "A-7" expression in line 350. The absence of data tables is reported as an address range of 0-0 ($0000-0000 hexadecimal).

Menu item 4 may not be immediately clear. The "EXTERNAL" references that ML Helper will list are those absolute addresses referencing memory outside the body of the program module being examined. Displaying all absolute addressing usage produces a counterproductive volume of screen clutter which I thought best to avoid.

Menu item 5, by which you elect to change absolute references, is not similarly restricted. If during a run it appears that interesting data might scroll away, then Apple users are reminded to invoke the CTRL S Stop-List feature of their system; others may have to rely on CTRL C or divert all output to hard copy. Have fun exploring uncharted machine language programs with ML Helper pointing the way.

0 DATA 232, 200, 202, 136, 72, 104, 24, 56, 96, 170, 168, 138, 152, 234, 10, 74, 42, 106, 186
1  DATA 154, 64, 120, 88, 184, 248, 216, 8, 40, 0, 208, 240, 144, 176, 48, 16, 80, 112, 169, 162
2  DATA 160, 201, 224, 192, 105, 233, 41, 9, 73, 165, 166, 164, 133, 134, 132, 230, 198, 197, 228
3  DATA 196, 101, 229, 36, 37, 5
10 DATA 69, 38, 102, 6, 70, 181, 182, 180, 149, 150, 148, 246, 214, 213, 117
11 DATA 245, 53, 21, 85, 54, 118, 22, 86, 177, 145, 209, 113, 241, 49, 17, 81, 161, 129, 193, 97
12 DATA 225, 33, 1, 65, 32, 76, 108, 44, 173, 174, 172, 141, 142, 140, 238, 206, 205, 236, 204
13 DATA 109, 237, 45, 13, 77, 46, 110, 14, 78, 189, 190
20 DATA 188, 157, 254, 222, 221, 125, 253, 61, 29, 93, 62, 126, 30, 94, 185, 153, 217, 121, 249
21 DATA 57, 25, 89 : GOTO 530
30 REM *** LIST ADDRESSES ***
40 IF A(Z) >  = S THEN  IF A(Z) <  = E THEN ~ RETURN
50 IF Z = 0 GOTO 80
60 FOR X = 0 TO Z - 1 : IF A(X) = A(Z) THEN RETURN
68 S(T) = VAL (H$) : E(T) = VAL (E$)
70 NEXT
80 PRINT "ADDR REF'D : "; : IF H THEN D = A(Z) : GOSUB 220 : PRINT "$"H$ : GOTO 100
90 PRINT A(Z)100 Z = Z + 1 - (Z > 29) : RETURN
110 REM *** ZERO PAGE CHANGE ***
120 FOR I = 0 TO X : IF C(I) = A(Z) THEN POKE A + 1, D(I)
130 NEXT : RETURN
140 REM *** RELOCATE ***
150 IF A(Z) < TS OR A(Z) > TE THEN RETURN
160 I =  PEEK (A + 1) + T3 : IF I > 255 THEN I ~ = I - N : T4 = T4 + 1
170 POKE A + 1, I : POKE A + 2, PEEK (A + 2) + T4 : RETURN
180 REM *** CHANGE ABSOLUTE ADDR ***
190 FOR I = 0 TO X : IF C(I) = A(Z) THEN K = INT (D(I) / N)
195 POKE A + 1, D(I) - N * K : POKE A + 2, K
200 NEXT : RETURN
210 REM *** DEC - HEX ***
220 H$ = "" : F = 4096 : FOR J = H TO 4 : K = INT ~ (D / F) : D = D - K * F
225 H$ = H$ + MID$ (G$, K + H, H) : F = F / 16 : NEXT : RETURN
230 REM *** DEC - HEX ***
240 D = 0 : F = H : FOR J = LEN (H$) TO H STEP - ~ H : M = ASC ( MID$ (H$, J, H )) - 48
245 D = D + F * (M - 7 * (M > 9) ) : F = 16 * F : ~ NEXT : RETURN
250 REM *** PRINT DATA TABLES ***
260 PRINT "DATA TABLE :  " ; : IF H THEN D = T1 : ~ GOSUB 220 : PRINT "$" H$ "-" ; : D = T2
265 GOSUB 220 : PRINT H$ : RETURN
270 PRINT T1"-" T2 : RETURN
280 REM *** MAIN ROUTINE ***
290 FOR A = S TO E
300 REM *** SKIP DATA TABLES ***
310 FOR I = 0 TO T : IF S(I) THEN IF A > = S(I) THEN A = E(I) + 1 : S(I) = 0
320 NEXT : FOR I = 0 TO 150 : READ M : IF PEEK (A) = M GOTO 390
330 NEXT
340 REM *** PRINT DATA TABLES ***
350 IF A - 7 > T2 THEN IF T1 THEN GOSUB 260 : T1 = A
360 IF T1 = 0 THEN T1 = A
370 T2 = A : GOTO 510
380 REM *** 1 - BYTE IGNORE ***
390 IF I < 29 GOTO 510
400 REM *** 2-BYTE IGNORE ***
410 IF I < 48 GOTO 500
420 REM *** ZERO PAGE ***
430 IF I > 102 OR C > 2 GOTO 470
440 IF C < 3 THEN A(Z) = PEEK (A + 1) : ON C GOSUB 50, 120
450 GOTO 500
460 REM *** 3 - BYTE ***
470 IF I < 103 GOTO 500
480 IF C > 2 THEN A(Z) = PEEK (A + 1) + PEEK (A ~ + 2) * N : ON C - 2 GOSUB 150, 40, 190
490 A = A + 1
500 A = A + 1
510 RESTORE : NEXT A : GOSUB 260 : END
520 REM *** END OF MAIN ROUTINE ***
530 PRINT "1 = LIST ZERO PAGE REFERENCES" : PRINT "2 = CHANGE ZERO PAGE REFERENCES"
531 PRINT "3 = RELOCATE" : PRINT "4 = LIST EXTERNAL ABSOLUTE REFERENCES"
532 PRINT "5 = CHANGE ABSOLUTE REFERENCES" : PRINT : PRINT "CHOOSE ONE: " ; : GET H$
533 PRINT H$ : C = VAL (H$) : PRINT : PRINT "WANT HEX NUMBERS, Y/N? " ; : GET H$ : PRINT H$
540 PRINT : H = H$ = "Y" : N = 256 : G$ = "0123456789ABCDEF": DIM A(30)
541 INPUT "INPUT START, END ADDRESSES : " ; H$, E$ : PRINT
542 IF H THEN GOSUB 240 : S = D : H$ = E$ : GOSUB 240 : E = D : GOTO 560
550 S = VAL (H$) : E = VAL (E$)
560 IF C < > 3 GOTO 660
570 INPUT "INPUT TARGET ADDRESS : " ; H$ : PRINT : IF H THEN GOSUB 240 : TS = D : GOTO600
580 TS = VAL (H$)
590 REM *** CALCULATE OFFSET ***
600 TE = TS + E - S : I = ABS (TS - S) : T4 = INT ~ (I / N) : T3 = I - T4 * N
605 IF TS < S THEN T3 = - T3 : T4 = - T4
610 REM *** MOVE ROUTINE ***
620 IF T3 > 0 THEN K = TE : FOR I = E TO S STEP - 1 : POKE K, PEEK (I) : K = K - 1
625 NEXT : GOTO 650
630 K = TS : FOR I = S TO E : POKE K, PEEK (I) : ~ K = K + 1 : NEXT
640 REM *** SWAP TS & S, TE & E ***
650 K = TS : TS = S : S = K : K = TE : TE = E : E = K
660 PRINT "LIST UP TO 11 KNOWN DATA TABLES IN ~ THE  PROGRAM.  TYPE 0, 0 WHEN DONE." : PRINT
670 PRINT "DATA TABLE "T" START, END : " ; : INPUT "" ; H$, E$
675 IF H THEN GOSUB 240 : S(T) = D : H$ = E$ : GOSUB 240 : E(T) = D : GOTO 690
680 S(T) = VAL (H$) : E(T) = VAL (E$)
690 IF E(T) THEN I = T3 + T4 * N : S(T) = S(T) + I : E(T) = E(T) + I : T = T + 1
695 IF T < 11 GOTO 670
700 IF C < > 2 THEN IF C < > 5 THEN PRINT : GOTO 290
710 PRINT : PRINT "LIST UP TO 11 ADDRESSES TO BE CHANGED. TYPE 0, 0 WHEN DONE. " : PRINT
720 PRINT "#"X". OLD, NEW ADDRESSES : " ; : INPUT "" ; H$, E$
725 IF H THEN GOSUB 240 : C(X) = D : H$ = E$ : GOSUB 240 : D(X) = D : GOTO 740
730 C(X) = VAL (H$) : D(X) = VAL (E$)
740 IF C(X) = D(X) OR X = 10 THEN PRINT : GOTO 290
750 X = X + 1 : GOTO 720