Assembly vs BASIC

From Maze

(Difference between revisions)
Jump to: navigation, search
Line 16:Line 16:
<pre>
<pre>
−
*= $1000 ; starting memory location<br>
+
*= $1000 ; starting memory location
−
lda #$80 ; set this value in...<br>
+
lda #$80 ; set this value in...
−
sta $d40f ; ... the noise speed hi SID register<br>
+
sta $d40f ; ... the noise speed hi SID register
sta $d412 ; ... and the noise waveform SID register
sta $d412 ; ... and the noise waveform SID register
loop ; label for loop location
loop ; label for loop location
−
lda $d41b ; load a random value
+
lda $d41b ; load a random value
−
and #1 ; lose all but the low bit
+
and #1 ; lose all but the low bit
−
adc #$6d ; value of "\" PETSCII
+
adc #$6d ; value of "\" PETSCII
−
jsr $ffd2 ; output character via kernal routine
+
jsr $ffd2 ; output character via kernal routine
−
bne loop ; repeat
+
bne loop ; repeat
</pre>
</pre>
Line 36:Line 36:
BASIC makes both of these acts compact and accessible. Print a character, generate a random number. Normally, carrying out either of these in assembly is an arduous task. Here's an example of a commonly used routine for generating a random 8-bit number in 6502 assembly:
BASIC makes both of these acts compact and accessible. Print a character, generate a random number. Normally, carrying out either of these in assembly is an arduous task. Here's an example of a commonly used routine for generating a random 8-bit number in 6502 assembly:
 +
<pre
Rand8
Rand8
lda random ; get seed from memory (must be non-zero)
lda random ; get seed from memory (must be non-zero)
Line 43:Line 44:
Rand8.no_eor
Rand8.no_eor
sta random ; save number as next seed
sta random ; save number as next seed
 +
</pre>
This routine is nine bytes long, or 25% of the space needed for the entire 10 Print program in BASIC. That's not surprising; a high-level language is supposed to abstract more complex, lower-level routines into more easily usable functions. But such functions can also be built into the hardware itself, stored in ROM as executable instructions, or produced through a combination of seemingly unrelated affordances.
This routine is nine bytes long, or 25% of the space needed for the entire 10 Print program in BASIC. That's not surprising; a high-level language is supposed to abstract more complex, lower-level routines into more easily usable functions. But such functions can also be built into the hardware itself, stored in ROM as executable instructions, or produced through a combination of seemingly unrelated affordances.
Line 50:Line 52:
But an even stranger approach to random number generation on the machine involves the C64 sound chip, another MOS Technologies integrated circuit, part 6581, also known as the Sound Interface Device or SID. The SID is a programmable sound generator chip which was responsible for the C64's distinctive audio abilities. Apart from its sonic functions, the SID also has he ability to generate random values. To do so, the programmer must select the noise waveform on the SID's voice 3 oscillator and set that voice's frequency to a non-zero value. Setting a higher frequency value will cause the noise values to change more rapidly, yielding a greater variety of random numbers. The first three instructions of the assembly program above accomplish these settings:
But an even stranger approach to random number generation on the machine involves the C64 sound chip, another MOS Technologies integrated circuit, part 6581, also known as the Sound Interface Device or SID. The SID is a programmable sound generator chip which was responsible for the C64's distinctive audio abilities. Apart from its sonic functions, the SID also has he ability to generate random values. To do so, the programmer must select the noise waveform on the SID's voice 3 oscillator and set that voice's frequency to a non-zero value. Setting a higher frequency value will cause the noise values to change more rapidly, yielding a greater variety of random numbers. The first three instructions of the assembly program above accomplish these settings:
 +
<pre>
lda #$80 ; set this value in...
lda #$80 ; set this value in...
sta $d40f ; ... the noise speed hi SID register
sta $d40f ; ... the noise speed hi SID register
sta $d412 ; ... and the noise waveform SID register
sta $d412 ; ... and the noise waveform SID register
 +
</pre>
... and once done, the program can get a new 8-bit random number by reading from memory location $d41b. While it looks a little messier than just calling RND in BASIC, the result is equally abstracted from the programmer's perspective--it's just abstracted to a different place, namely the SID chip.
... and once done, the program can get a new 8-bit random number by reading from memory location $d41b. While it looks a little messier than just calling RND in BASIC, the result is equally abstracted from the programmer's perspective--it's just abstracted to a different place, namely the SID chip.
Line 62:Line 66:
But as with the SID random number solution, the C64's underlying hardware ROM provides a much simpler solution. The C64 has a low-level operating system core, most of which it inherited from the earlier Commodore PET. This core is referred to as the KERNAL, and it occupies the last 8KB of the machine's address space ($E000-$FFFF). The KERNAL handles keyboard input and screen output, among other functions, including a routine that will send the PETSCII character value currently in the 6502 processor's accumulator to the current output device (the screen by default). That routine lives at memory address $ffd2, and it can be executed by jumping to subroutine at that address. This is just what the 10 Print assembly rendition above does, after loading a random value and manipulating it to insure that it will be one of the two slash characters that comprise the maze:
But as with the SID random number solution, the C64's underlying hardware ROM provides a much simpler solution. The C64 has a low-level operating system core, most of which it inherited from the earlier Commodore PET. This core is referred to as the KERNAL, and it occupies the last 8KB of the machine's address space ($E000-$FFFF). The KERNAL handles keyboard input and screen output, among other functions, including a routine that will send the PETSCII character value currently in the 6502 processor's accumulator to the current output device (the screen by default). That routine lives at memory address $ffd2, and it can be executed by jumping to subroutine at that address. This is just what the 10 Print assembly rendition above does, after loading a random value and manipulating it to insure that it will be one of the two slash characters that comprise the maze:
−
<code>
+
<pre>
jsr $ffd2 ; output character via kernal routine
jsr $ffd2 ; output character via kernal routine
−
</code>
+
</pre>
The output of the assembly program is essentially identical to 10 Print (it runs a bit faster, because the microprocessor is running machine instructions directly, rather than interpreting them first as BASIC commands and functions. But the program that generates that output is really no more or less lengthy or complex than is the BASIC program. When measured in bytes, the assembly program is even shorter than its BASIC cousin (22 bytes for the assembly program, compared to 36 bytes, or characters, for the BASIC program). While the assembly program is clearly more esoteric and less human readable than the BASIC one, its implementation teaches us that the abstraction that makes the emergent elegance of 10 Print's output possible in such a small set of instructions is not a feature of the BASIC interpreter, but of the underlying hardware itself.
The output of the assembly program is essentially identical to 10 Print (it runs a bit faster, because the microprocessor is running machine instructions directly, rather than interpreting them first as BASIC commands and functions. But the program that generates that output is really no more or less lengthy or complex than is the BASIC program. When measured in bytes, the assembly program is even shorter than its BASIC cousin (22 bytes for the assembly program, compared to 36 bytes, or characters, for the BASIC program). While the assembly program is clearly more esoteric and less human readable than the BASIC one, its implementation teaches us that the abstraction that makes the emergent elegance of 10 Print's output possible in such a small set of instructions is not a feature of the BASIC interpreter, but of the underlying hardware itself.

Revision as of 00:52, 7 August 2010

View this revision of Assembly vs BASIC.

Personal tools