Classic Computer Magazine Archive COMPUTE! ISSUE 25 / JUNE 1982 / PAGE 133

Machine Language: First Steps, Part II

Jim Butterfield

In the last episode, our hero, F. R. Vescent has started to convert the following bar graph program from BASIC to machine language:

200 DATA 15, 10, 30, 35, 28, 28, 15, 0
210 READ V : IF V = 0 GOTO 300
220 J = 48 : FOR K = 1 TO J
230 J = J + 1 : IF J = 58 THEN J = 48
240 PRINT CHR$(J);
250 NEXT K
270 GOTO 210
300 END

He has coded lines 220 to 260 inclusive to read:

      LDX #$30
      LDY #$01
      CPX #$3A
      BNE SKIP
      LDX #$30
      JSR $FFD2
      CPY $0300
      LDA #$0D
      JSR $FFD2

He puzzles for a moment over the BCC YLOOP; he knows that this is equivalent to Branch-Less-Than; and this will cause the loop to be executed one time too few. After a few moments thought, he changes the LDY #$01 to LDY #$00; that should do the job. Now he's ready to translate the above Assembler code into machine code, which is what the computer really needs.

The coding will be placed in the PET's first cassette buffer, which starts at hexadecimal address 027A; this is noted at the left of the first line. Now, F. R. looks up LDX in his table of Op Codes, and finds that there are about five different ways the instruction can work. The one he wants is Immediate Mode – flagged by the "#" sign in the operand. That translates to hex A2, so he adds to the first line to make:

027A A2 30 LDX #$30

Counting off the address bytes, he decides that the next address must start at hex 027C. He writes this value at the left of the second line. Continuing the translation, he gets:

027A   A2    30           LDX  #$30
027C   A0    00           LDY  #$00
027E   E88          YLOOP INX
027F   E0    3A           CPX  #$3A
0281   D0    02           BNE  SKIP
0283   A2    30           LDX  #$30
0285   8A           SKIP  TXA
0286   20    D2  FF       JSR  $FFD2
0289   C8                 INY
028A   CC    00  03       CPY  $0300
028D   90    EF           BCC  YLOOP
028F   A9    0D           LDA  #$0D
0291   20    D2  FF       JSR  $FFD2
0294   60                 RTS

There are a few coding tricks that F. R. has to keep in mind to do this translation. First, two-byte addresses are coded "backwards" – that is, hex 0300 is coded as 00 03 and hex FFD2 is coded as D2 FF. Secondly, Branches are coded as a relative offset, so that D0 02 may be read as "if not equal, hop over the next two bytes." A relative branch value of hex EF (see BCC YLOOP) causes the program to branch back 17 locations from the start of the following instruction, if the branch condition is satisfied.

The above "hand assembly" can be greatly helped by the use of assemblers or "tiny assemblers" which work out the Op Code values and calculate the branch values.

Now F. R. is ready to put the machine language program into memory. He calls the machine language Monitor with SYS4, and then asks for a memory display from 027a to 0294 with:

.M 027A 0294

He might get anything. He will go back and type over the memory contents to enter his program. The changed memory map will look like this:

.:  027A A2 30 A0 00 E8 E0 3A D0
.:  0282 02 A2 30 8A 20 D2 FF C8
.:  028A CC 00 03 90 EF A9 0D 20
.:  0292 D2 FF 60 .. .. .. .. ..

Now that the machine language program is in place, the BASIC program can be written to hook in with it. F. R. returns to BASIC (with .X) and writes:

200 DATA 15, 10, 30, 35, 28, 28, 15, 0
210 READ V : IF V = 0 GOTO 300
220 POKE 768, V
230 SYS 634
270 GOTO 210
300 END

Line 220 POKEs the desired value into memory where the machine language program will pick it up. Line 230 calls the machine language program. After the ML program is executed, the BASIC program will resume at line 270.

Try entering the program – both machine language and BASIC – and run it. You'll see the extra speed that machine language gives you.

The program is complete. But it isn't in a form that's very suitable for saving, especially if we want to save to tape. We'll conclude the fearless exploits of F. R. Vescent in the next episode.