I'm in the process of building a basic
computer using a version of the 6502
microprocessor and so far I've just
programmed it to blink some LEDs like
this and the program I wrote that's
doing this is stored on this ROM chip oh
really it's a programmable ROM chip so
we can actually change the program but
if we pull the chip out we can put it in
a programmer and take a look at what's
on it so this is an 80 28 C 256 chip so
we just go to read here and read the
device here's the program that was
running it's just a bunch of hexadecimal
numbers but of course they have meaning
so a nine means to load the next byte
into the a register so this is going to
load FF into the a register eight D
means to store the contents of the a
register into the address in the next
two bytes here and so on until we get to
this four C zero five eight zero which
obviously means to loop back and keep
repeating this well if that doesn't seem
so obvious to you then you're not gonna
be surprised to hear that no one
actually writes software this way even
for your really low level stuff like
this now my last video I actually did
write this program by writing out the
machine code here by hand you know with
a little bit of Python code down here to
sort of massage it into a binary file of
the of the appropriate size but of
course you know it just isn't practical
to write machine code by hand like this
for you know anything more complex
instead the way to do this is to write
our program using assembly language so
we can actually just say load a FF and
store a six zero zero two or you know
whatever else we want and then we can
use an assembler which is just a program
that will convert this to machine code
without us having to worry about what
all the different up codes are so of
course we're gonna need an assembler and
there are a number of different
assemblers out there for the 6502 so I'm
gonna use this thing called vasan it's
you know looks like it's actively
maintained it's written by Volcker bar
Thurmond and a lot of work on the 6502
stuff was done by Frank Willow but you
can see you know it supports the 6502
family it supports a number of different
syntax flavors I'm going to be using the
hold 8-bit style syntax and it'll give
us this raw binary output which is what
we need in order to write to our problem
but in any event you can download the
source code from the website here and
compile it yourself I've got it
downloaded here we just do make actually
we have to do PU equals 6502 and syntax
is old-style
and we get a few warnings but that
should generate this file here which is
the actual assembler and so if we run
that you can see okay wants an input
file and so you can either compile this
yourself or if you go back to the
website go to Volkers page here he's got
binaries here for Mac Windows and Linux
for the 6502 so you can just download
that and that ought to be what you need
so once we have the assembler now let's
run it to translate this assembly
language program just this this two line
thing I've written here into a raw
binary file that we can put on the ROM
so they save this so now if we run the
assembler with that file there it goes
and so what did it do well by default it
puts its output into a file called a dot
out so we take a look at that we can see
it's actually a text file that has a
bunch of stuff in it and it does have
the opcodes here spelled out in in
hexadecimal but this is just a text file
yeah we can't put this on the EEPROM
directly like this you know we need a we
need a binary file but if we go take a
look at the documentation for the
assembler you can see there's a bunch of
options and one of those options is - F
format to use a particular output format
and it says C the chapter on output
drivers for more details but if we take
a look at the let's see there's an
output module here for simple binary
let's take a look at that and here it
says the simple binary output module can
be selected with the - f bin option so
let's do that so I'll run the assembler
again with the - f bin and a file name
and now if we look at a dot out well now
it just looks like a couple unknown
characters I guess this is this is the
contents of the file which is sort of
what we expect right it's just a binary
file with a couple instructions in it so
let's do a hex dump to see exactly
what's in there and here we go we've got
our program - a nine is the opcode for
load a FF and then eight D is the opcode
for store a and then it's got the six
zero zero two here and so that matches
the program that we wrote now a couple
things I'll point out here in the
program before I get too far is you see
there's a hash symbol here and then the
dollar signs and these have meaning to
the assembler so the dollar sign here
for example means that the number is
hexadecimal so if I left off this dollar
sign and this would be address six
thousand two decimal not address six
zero zero two hexadecimal which is what
want and in that the hash sign up here
means that this load a is a load
immediate meaning it's loading the value
FF into the a register and if I left off
this hash symbol then this would
actually mean to load whatever data is
at address FF or or really address a 0 0
FF load load whatever is at that memory
address into a register sorry I actually
let me leave the the hash symbol off and
save this and show you what that does so
I go back and and just rerun the
assembler and take a look at the hex
dump you can see instead of having you
know this instruction being a 9 FF it's
now instruction a 5 FF so it's actually
a different opcode even though the only
thing we changed was was just leading
leaving off this hash symbol that was
here you know so getting rid of that
hash symbol actually changes the opcode
so we look at the data sheet for the
microprocessor we can see a 5 is still
an opcode for the load a instruction
just like a 9 but where a 9 is is sort
of under this you know go figure it's a
hash column here that means an immediate
data a 5 is ZP which is 0 page which you
know means it's loading from an address
that starts with 0 0 in this case would
be 0 0 FF which is very different from
what we want so it turns out that hash
symbol is pretty important here but
anyway now if we want to recreate the
rest of that blink program that we
started with we can just continue to do
that in assembly language here so I
could put out five five hex into the a
register which is just the alternating
ones and zeros and then store that out
to address 6 0 0 0 which will put it on
the LEDs and then load a a which is the
other alternating bits and then store
that to put that on the LEDs and at the
bottom I had a jump instruction here to
create a loop so that's pretty much what
we had before but instead of us having
to look up and type in the actual hex op
codes we're using these mnemonics so
it's you know much easier to read and
write now one thing I'll point out that
that maybe isn't that obvious is that
each line here has some spaces at the
beginning it turns out to be really
important that each instruction has some
spaces or a tab or something in front of
it like this otherwise the assembler
will give you all sorts of errors and
I'll get into why that is in a minute
but you definitely wanna make sure
you've got some blank space the
beginning of each line so let's save
this and go ahead and assemble it and
now if we hex dump the output here's
what we get and it's more or less
identical to what we have in the run
in fact if we take a look at that you
can see these first 18 bytes here the
firt you know the the actual program
itself is identical to what was in the
ROM but of course the ROM image is more
than 18 bytes in fact it's 32,768 bytes
and it has to be exactly that size
because that's how big the the EEPROM
that we're using is also at the end here
at fffc well well it's 7f FC + f7 FF d
in the ROM which is going to appear at
address F of FC and F of FD in memory
this is the the reset vector and this
you know this 0 0 8 0 is what tells the
processor where to start executing code
you know at address eight zero zero zero
so our assembler is giving us this but
we you know we need all this padding
here to get the file to be exactly 32 K
long and we need this zero zero eight
zero here so how can we do that well
this is something the assembler actually
makes really easy for us if we go back
to our code we can use the origin
direction which is org and this origin
directive tells the assembler where the
the following code goes in memory so at
the very top here I can say you know org
eight zero zero zero and and this says
the next statement you know this load a
here is going to be a tad rs.8000 and
the reason we want to say that the first
instruction is at address eight zero
zero zero is because even though it's
the first instruction in the in the
first byte of the ROM here
remember the ROM is only enabled when
the processor sets the top address line
a 15 when it sets that high and so if a
15 is a 1 but all the rest of these
address lines are all zeros all these
address lines here are all zeros then
that's what's going to give us the first
bite out of the ROM right the rom is
enabled and we're and we're getting the
first bite out of it but from the
processors perspective it's not reading
address 0 it's reading address 8 0 0 0
so this org directive at the top just
tells the assembler a you know the
processor is gonna think that the code
in this file starts at address eight
zero zero which is fine but now we can
do another org directive down here at
the bottom for address fffc
which says that the next thing after
this goes at address fffc
so right here after that org direct if
we want to just tell the assembler just
put the address eight zero zero zero
because that's the start address we want
to have at this you know FFF C position
and we can do that with the dot word
directive which just puts a word which
is just a 16-bit value into the output
so we could say word eight zero
zero now if we save this and assemble
this whoops assemble it you get some
errors here so unknown mnemonics a.org
word it doesn't understand and that's
because we actually need to tell the
assembler we want to use these
directives with dots in front of them so
what we want to do is use the dash dot
der option here and okay there we go so
now let's take a look at the output so
if we do a hex dump of a dot out and
there we go we've got the first the
first 18 bytes are the same that's our
program and then we have a whole bunch
of zeros all the way up to ffff C and F
of F D which is now their zero zero
eight zero so this is almost exactly
what we want it's actually two bytes
short because we need two more bytes
here to get the file to be exactly 32768
bytes long but you know that's easy
enough we can just add another word to
the end here it could be whatever and
now let's assemble this and do a hex
dump and there we go so it's the right
length right so 7f f f is the last byte
here it's got the zero zero eight zero
in the right place for the reset vector
and it's got our program here at the
beginning so of course now we could just
write this file to the EEPROM like like
we have in them in previous videos and
run the program but there's still a few
more things we can do to make things
even easier for us if we go back to our
code one thing that's really tricky
about this is we have this jump eight
zero zero five here and the goal of that
is to create a loop out of this block
here and so the eight zero zero five is
supposed to be the address where this
load a is but you know I only know that
because I know well we're starting at
eight eight zero zero zero and the load
a is one byte and this this FF is one
byte and the store a this is three bytes
and so then this must be a zero zero
five but you know that that's a just a
bug waiting to happen you know as soon
as anything changes this the address of
this instruction could change so instead
we can actually have the assembler keep
track of all that so I could put a label
here call it loop and then instead of
jumping to address eight zero zero five
I can just jump to that label loop and
now that's way better so it's much
easier to tell what's going on here so
we have you know a loop here and because
we're not hard coding that address if
this code moves around in the future
then nothing's going to break and now
you may have noticed that unlike every
other line in this
while this label here is not indented
and that's very much intentional because
that's how the assembler knows that it's
a label now if we want we can add
another label at the top here for the
initialization code and then down here
at the bottom for our reset vector
instead of hard-coding that we can just
use that reset label so let's save this
and assemble it again
and we take a look at the output you can
see it's the same as before so that
jumped that for C zero five eight zero
is the same it's still using address
eight zero zero five but now you know we
didn't have to keep track of that and
figure that out on our own and of course
the reset vector here is still zero zero
eight zero so that so that's the same as
well so hopefully you'll find this code
here to be much more legible and
maintainable than just a raw listing of
hex codes that we started with so for
example we can actually change this
program pretty pretty easily now so
let's let's make some changes here after
we initialize the interface adapter here
let's let's output something right away
so I'll do five zero hex and output that
and then in the loop what I'll do is a
rotate write instruction and then this
instruction just by itself will shift
all of the bits in the a register to the
right you're rotating the rightmost bit
back around to the left and then once we
do that what I can do is we'll just
store the modified a register back to
address six zero zero zero two to put it
out on the LEDs and I'll get rid of the
rest of this and that'll actually just
be our loop there so this whole program
is you know we're initializing the
interface adapter here where we're
outputting the five zero hex pattern to
the LEDs and then in our loop we're just
you know essentially just shifting that
pattern to the right and rotating it
around so we should see something kind
of interesting on the LEDs with that
let's save this and I'll run the
assembler again and then do a hex dump
of the output there and if we look what
we've got here I've got a nine which is
load a FF and then we have our eight D
which is store a zero two six zero which
is actually I know another nice thing
about the assembler is you know it's
figuring out how to put this in the
little endian format this sort of
backwards format because this is address
six zero zero two and of course in our
code you know we just type six zero zero
two we don't have to think about the
fact that it has to be stored in this
sort of backwards format in the
hex file anyway then we've got load a-50
store a6000 then this 6a opcode that's
got to be the opcode for rotate right
and then another store a6000 and then
our jump so for CEA's jump but this time
we're jumping to well this is going to
be eight zero zero a but of course we
didn't have to worry about figuring that
out the assembler just knew you know
that's the right place to jump to get
back to the loop label which which I
guess would be sort of here-ish so let's
see what this program does let's write
it to the EEPROM there we go now I'll
put the EEPROM back in our circuit here
and power it up I'll reset ok there's
five and you know there it goes so it's
got those two bits from the the five
zero and it's rotating them right which
it looks like it's going left because
I've got the the bit sort of swapped
around here on you know physically but
it's rotating it right and you'll see
this bit now goes into the carry bit and
then the carry bit comes back so there's
actually sort of a hidden ninth bit in
this rotation which is the carry bit but
otherwise that's what our programs
supposed to do and of course now being
able to write programs in assembly
language for this little computer we're
building means that we'll be able to do
something more complex than just
blinking some LEDs early still be easier
for us to write programs that are a
little bit more complex not to say that
blinking LEDs can't be fun but in the
next video I'm gonna hook these control
signals up to this LCD display and we'll
be able to write a program a little bit
more easily to control it and actually
display some some more interesting text
and remember if you want to follow along
with these videos and build and program
your own little computer I've gathered
all the parts together that you'll need
them and you can buy them on my website
as a kit it comes with everything you'll
need to build the basic computer and
I've also got a kit for the the clock
that I'm using here as well so you can
check out Eater net slash 6502 for more
information on all of that and as always
thanks to all my patrons since your
support is also critical in making these
videos possible
you