Tải bản đầy đủ (.pdf) (137 trang)

Lesson 1: The Language of Microprocessors pps

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (400.17 KB, 137 trang )

Lesson 1: The Language of
Microprocessors
Most people think that computers are some kind of complicated device that is impossible
to learn and infinitely intelligent, able to think better than a person. The truth is much less
glamorous. A computer can only do what the programmer has told it to do, in the form of
a program. A program is just a sequence of very simple commands that lead the
computer to solve some problem. Once the program is written and debugged (you hardly
ever get it right the first time), the computer can execute the instructions very fast, and
always do it the same, every time, without a mistake.
And herein lies the power of a computer. Even though the program consists of very
simple instructions, the overall result can be very impressive, due mostly to the speed at
which the computer can process the instructions. Even though each step in the program is
very simple, the sequence of instructions, executing at millions of steps per second, can
appear to be very complicated, when taken as a whole. The trick is not to think of it as a
whole, but as a series of very simple steps, or commands.
Most microprocessors, or very small computers, (here after referred to simply as micro's)
have much the same commands or instructions that they can perform. They vary mostly
in the names used to describe each command. In a typical micro, there are commands to
move data around, do simple math (add, subtract, multiply, and divide), bring data into
the micro from the outside world, and send data out of the micro to the outside world.
Sounds too simple it is.
A typical micro has three basic parts inside. They are the Program Counter, Memory, and
Input / Output. The Program Counter keeps track of which command is to be executed.
The Memory contains the commands to be executed. The Input / Output handles the
transfer of data to and from the outside world (outside the micro's physical package). The
micro we'll be using is housed inside a 40 pin package, or chip. There are many other
actual parts inside our micro, but too much, too soon, would be too confusing right now.
We will, however, learn about each and every single one.
A Simple Program
As stated before, a program is a sequence or series of very simple commands or
instructions. A real world example program might be the problem of crossing a busy


street.
Step 1: Walk up to the corner of the street and stop.
Step 2: Look at the traffic light.
Step 3: Is the light green for your direction of travel?
Step 4: If the light is red, goto step 2. (otherwise continue to step 5)
Step 5: Look to the left.
Step 6: Are there cars still passing by?
Step 7: If yes, goto step 5. (otherwise continue to step 8).
Step 8: Look to the right.
Step 9: Are there cars still passing by? (there shouldn't be any by now, but, you never
know!)
Step 10: If yes, goto step 8. (otherwise continue to step 11)
Step 11: Proceed across the street, carefully!!
Now this may seem childish at first glance, but this is exactly what you do every time you
cross a busy street, that has a traffic light (at least, I hope you do). This is also exactly
how you would tell a micro to cross the street, if one could. This is what I mean by a
sequence or series of very simple steps. Taken as a whole, the steps lead you across a
busy intersection, which, if a computer did it, would seem very intelligent. It is
intelligence, people are intelligent. A programmer that programmed these steps into a
micro, would impart that intelligence to the micro.
The micro would not, however, in this case, know what to do when it got to the other
side, since we didn't tell it. A person, on the other hand, could decide what to do next, at a
moments notice, without any apparent programming. In the case of a person, though,
there has been some programming, it's called past experiences.
Another program might be to fill a glass with water from a faucet.
Step 1: Turn on the water.
Step 2: Put the glass under the faucet.
Step 3: Look at the glass.
Step 4: Is it full?
Step 5: If no, goto step 3.(otherwise, continue to step 6)

Step 6: Remove the glass from under the faucet.
Step 7: Turn off the water.
This is a simpler program, with fewer steps, but it solves a problem, to fill a glass with
water. In a micro, the problems are different (they could be the same if you've made some
kind of servant robot), but the logical steps to solve the problem are similar, that is, a
series of very simple steps, leading to the solution of a larger problem.
Also notice that since the steps are numbered, 1 through 7, that is the order in which
they're executed. The Program Counter, in this case, is you, reading each line, starting
with 1 and ending with 7, doing what each one says. In a micro, the Program Counter
automatically advances to the next step, after doing what the current step says, unless a
branch, or jump, is encountered. A branch is an instruction that directs the Program
Counter to go to a specific step, other than the next in the sequence. The branch in this
example is step 5. Not only is this a branch, but it is a conditional branch. In other words,
based on whether the glass is full or not, the branch is taken, or not. A micro has both
branch and conditional branch instructions. Without this ability to reuse instructions, in a
sort of looping action, a solution would take many more steps, if it would be possible at
all.
The point of this lesson is to show how a simple set of instructions can solve a bigger
problem. Taken as a whole, the solution could appear to be more complicated than any of
the separate steps it took to solve it. Well that wasn't so tough, was it?
The most difficult problem to be solved in programming a micro is to define the problem
you are trying to solve. Sounds like some kind of play on words, but I assure you, it's not.
This is the Logical Thought Process I mentioned earlier. The mark of a good programmer
is one who has this ability. It is, in my humble opinion, a developed skill, coupled with
some talent, and a good understanding of the problem you're trying to solve. In most
cases, God has endowed you with the talent and the ability to reason, all you need do is
develop the skill of Problem Solving.
My email address is here and I would welcome your questions or comments as you
proceed through this course. Depending on the volume of mail I get, it may take a couple
of days or so for me to get back to you, but be assured, I will get back to you. I really do

want you to understand the information I'm presenting, and not being a professional
teacher, I might not always explain things to the satisfaction of everyone, but with your
patience, I'll do my best. My home page is />

Decimal Vs. Binary (and Hex)
Most people have learned to use the Decimal numbering system for counting and
calculations. But micros use a different system. It's called Binary. All numbering systems
follow the same rules. Decimal is Base 10 and Binary is Base 2. The base of a system
refers to how many possible numbers can be in each digit position. In decimal, a single
digit number is 0 through 9. In binary a single digit number is 0 or 1. In decimal, as you
count up from 0, when you reach 9 and add 1 more, you have to add another digit
position to the left and carry a 1 into it to get 10 (ten). Ten is a two digit decimal number.
In binary, as you count up from 0, when you reach 1 and add 1 more, you have to add
another digit position to the left and carry a 1 into it to get 10 (two decimal). While this is
exactly what you do in decimal, the result looks like ten. What you have to do is get past
seeing all numbers as decimal. While decimal 10 (ten) looks like binary 10 (two decimal)
they represent different decimal values. It is still useful to think in decimal, since that's
what we're used to, but we have to get used to seeing numbers represented in binary.
Another small difference between decimal terminology and binary is that in binary a digit
is called a bit. It gets even more confusing by the fact that 4 bits make a nibble. Two
nibbles make a byte. Two bytes make a word. Most numbers used in a micro don't go
beyond this, although there are others. Using what I've just said, if two nibbles make a
byte, you could also say that a byte is eight bits.
To represent a binary number larger than 4 bits, or a nibble, a different numbering system
is normally used. It is called hexadecimal, or Base 16. A shorter name for hexadecimal is
simply hex, and that's what we'll use here after. In this system there are 16 possible
numbers for each digit. For the first 10, 0 through 9, it looks like decimal. Unlike
decimal, when you add 1 more to 9, you get A. I know that having a letter to represent a
number is really confusing, but they had to call it something, and A is what they chose.
So a hex A is a decimal 10 (ten). The numbers count up from A through F. Just to clarify

this here is the sequence of counting in hex from 0 to where you have to add another digit
position to the left 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F (no G). This represents a
decimal count of 0 through 15. At a count of F (15 decimal), if you add 1 more you get
10 (oh no! not another 10 that means something else!!). Sad but true.
Let's regroup here. A binary 10 (one zero) is decimal 2, a decimal 10 is ten, and a hex 10
is decimal 16. If you can get this concept, you will have conquered the most difficult part
of learning micros.
I need to get past one more obstacle, the idea of significance. In a decimal number like
123, 3 is the least significant digit position (the right most digit) and 1 is the most
significant digit position (the left most digit). Significance means the relative value of one
digit to the next. In the number 123 (one hundred twenty three) , each number in the right
hand most digit position (3) is worth 1. The value of each number in the next most
significant digit position (2) is worth ten and in the most significant digit position (1)
each is worth a hundred. I'm not trying to insult your intelligence here, but rather to point
out the rule behind this. The rule is that no matter what base you're working in, as you
start adding digits to the left, each one is worth the base times (multiplied) the digit to the
right. In the decimal number 123 (base 10), the 2 digit position is worth 10 times the 3
digit position and the 1 digit position is worth 10 times the 2 digit position. Hence the
familiar units, tens, hundreds, and so on. For some reason, for most people, this makes
sense for decimal (base 10) but not for any other base numbering system.
The very same is true for binary. The only difference is the base. Binary is base 2. So in
binary the least significant bit (remember bits?) is worth 1 ( this happens to be the same
for all bases). The next most significant bit is worth 2, the next worth 4, the next worth 8,
and so on. Each is 2 times (base 2) the previous one. So in an 8 bit binary number (or
byte, remember bytes?), starting from the right and moving left, the values for each of the
8 bit positions are 1, 2, 4, 8, 16, 32, 64 , and 128. If you've got this, you have passed a
major milestone, you should go celebrate your passage. If you haven't, I would re-read
the above until you do, and then go celebrate!! ( By the way, if you didn't get this the first
time through, join the crowd. I didn't either!!)
In hex (base 16) the same rule applies. In a 4 digit hex number, starting at the right and

working left, the first digit is worth 1 ( hey that's just like decimal and binary!!), the next
is worth 16 (base times the previous digit), the next is worth 256 (16 X 16), and the most
significant is worth 4096 (256 X 16). One last note, hex is just binary described another
way. A hex digit is a binary nibble ( remember nibbles?). Both are 4 bit binary values.
Trying to wrap all this confusion up in review, 4 bits is a nibble or a hex digit. Two hex
digits is a byte or 8 bit binary. A 4 digit hex number is a word, or 16 bit binary or 4
nibbles, or 2 bytes. You may have to review the previous paragraphs a few times (I did!!)
to get all the relationships down pat, but it is crucial that you are comfortable with all I've
said, so that what follows will make more sense.
Let's take a few example numbers and find the decimal equivalent of each. Let's start
with the binary number 1011, a nibble. Starting at the right and moving left, the first digit
is worth one, because there is a 1 there. The next is worth two, because there is a 1 in it.
The next would be worth 4, but since there is a 0, it's worth zero. The last or most
significant is worth eight, since there is a 1 in it. Add all these up and you get eleven. So
a binary 1011 is decimal 11. Also, since this could be a hex digit, the hex value would be
B.
Let's take a longer binary number 10100101. Starting at the right moving left, the first is
worth 1, the next is worth 0, the next is worth 4, the next is 0, the next is 0, the next is
worth 32, the next is 0, and the last is 128. Adding all these up you get decimal 165.
Dividing this number up into two hex digits, you get A5. So binary 10100101, decimal
165, and hex A5 are all the same value. Using hex, the rightmost digit is worth 5, and the
most significant digit is worth 160 (10 X 16), resulting in decimal 165. If you understand
this, your ready to move on, leaving the different systems behind. If you don't, keep
reviewing and studying until you do. If you don't understand and still continue, you will
be confused by what follows. I promise that once you get this, the rest is easier.
This ends the second lesson. I hope this wasn't too daunting or difficult, but there was a
lot to get through. The rest of the course should be a little easier. Learning a new
numbering system is like learning a new language. It's a little cumbersome at first, but it
gets easier.
My email address is here and I would welcome your questions or comments as you

proceed through this course. Depending on the volume of mail I get, it may take a couple
of days or so for me to get back to you, but be assured, I will get back to you. I really do
want you to understand the information I'm presenting, and not being a professional
teacher, I might not always explain things to the satisfaction of everyone, but with your
patience, I'll do my best. My home page is
A Micro's Commands (or Instructions).
I would like to take a moment and address a few things that will make it easier for me to
describe things to you later. In a micro we refer to a binary number like 1111 as 1111b, a
decimal number like 123 as 123, and a hex number like A5 as A5h. So don't be confused
by the letters following numbers, it is easier than having to say the whole words binary,
decimal, or hexadecimal, but still indicate it. By doing this, there is no doubt what base a
multidigit, or multibit, number is in.
Also there is another kind of memory, called flags. Flags are single bit numbers used to
indicate different conditions. They are called flags because they flag the program of
events or conditions. If a flag is raised, or has a 1 in it, it is said to be SET. If it is a 0, it is
said to be CLEARED.
One other thing, in an 8 bit byte the 8 bits are referred to as bits 0 through 7, with bit 0
being the right most, or least significant, and bit 7 as the left most or most significant. In
micros, a 0 is just as real a number as 1 or 8, and it should not be thought of as "nothing".
Lastly, there are various Registers inside a micro. These vary from micro to micro, but all
contain a register called the Accumulator. It is also referred to in some as the a register. I
will be using the accumulator in the following discussion. It is a type of memory for
storing temporary results and is 8 bits wide, or a byte, as are most places that data can be
put inside the micro.
In the micro we will be using, there are 5 different types of instructions and several
variations of each, resulting in 110 different instructions. These 5 types are
ARITHMETIC, LOGICAL, BOOLEAN, BRANCHING, and DATA TRANSFER.
ARITHMETIC
The arithmetic instructions include addition, subtraction, division, multiplication,
incrementing, and decrementing. There are two flags used with arithmetic that tell the

program what the outcome of the instruction was. One is the Carry (C) flag. The other is
the Zero (Z) flag. The C flag will be explained in the following example of addition. The
Z flag, if set, says that the result of the instruction left a value of 0 in the accumulator. We
will see the Z flag used in a later lesson.
Addition
This is straight forward and is simply to add two numbers together and get the result.
However there is one more thing. If, in the addition, the result was too big to fit into the
accumulator, part of it might be lost. There is a safeguard against this. Take the case of
11111111b (255) and 11111111b (255). These are the largest numbers that can fit into an
8 bit register or memory location.You can add these as decimal numbers, since I gave
you their values in decimal also, and you would get 510. The binary value for 510 is
111111110b (9 bits). The accumulator is only 8 bits wide, it is a byte. How do you fit a 9
bit number into 8 bits of space? The answer is, you can't, and its called an OVERFLOW
condition. So how do we get around this dilemma? We do it with the CARRY (C) flag. If
the result of the addition is greater than 8 bits, the CARRY (C) flag will hold the 9 th bit.
In this case the accumulator would have a 11111110b (254) and the C flag would be a 1,
or set. This 1 has the value of 256 because this is the 9th bit. We haven't covered a 9 bit
number, but they come up all the time as overflows in addition. Since we are using base
2, and we found out in lesson 2 that the 8th bit (bit 7) in a byte is worth 128, then the 9th
bit is worth 2 times that, or 256. Adding 254 and 256, we get 510, the answer, and we
didn't loose anything, because of the C flag. Had the result of the addition not caused an
overflow, the C flag would be 0, or cleared.
Subtraction
In the case of subtraction, the process is more difficult to explain, and as such, I'm not
going to cover it here. It involves 1's compliment and 2's compliment representation. But
I will tell you this, you can subtract two numbers and if there is an under flow, the C flag
will be a 1, otherwise it will be a 0. An under flow is where you subtract a larger number
from a smaller number.
Multiplication and Division
In the micro we will be using, are multiply and divide instructions, but I will wait till later

to talk about them. They do, however, just what the names suggest.
Two other instructions are included in the arithmetic group. They are increment and
decrement. These instructions are used to count events or loops in a program. Each time
an increment is executed, the value is incremented by 1. A decrement, decrements the
value by 1. These can be used with conditional jumps to loop a section of program, a
certain number of times. We will see these used later.
LOGICAL
In micros there are other mathematical instructions called logical instructions. These are
OR , AND, XOR, ROTATE, COMPLEMENT and CLEAR. These commands are
usually not concerned with the value of the data they work with, but, instead, the value,
or state, of each bit in the data.
OR
The OR function can be demonstrate by taking two binary numbers, 1010b and 0110b.
When OR'ing two numbers, it doesn't matter at which end you start, right or left. Let's
start from the left. In the first bit position there is a 1 in the first number and a 0 in the
second number. This would result in a 1. The next bit has a 0 in the first number and a 1
in the second number. The result would be 1. The next bit has a 1 in the first number and
a 1 in the second number. The result would be a 1. The last bit has a 0 in the first number
and a 0 in the second number, resulting in a 0. So the answer would be 1110b. The rule
that gives this answer says that with an OR, a 1 in either number results in a 1, or said
another way, any 1 in, gives a 1 out.
AND
AND'ing uses a different rule. The rule here is a 0 in either number will result in a 0 , for
each corresponding bit position. Using the same two numbers 1010b and 0110b the result
would be 0010b. You can see that every bit position except the third has a zero in one or
the other number. Another way of defining an AND is to say that a 1 AND a 1 results in a
1.
XOR (eXclusive OR)
XOR'ing is similar to OR'ing with one exception. An OR can also be called an inclusive
OR. This means that a 1 in either number or both will result in a 1. An eXclusive OR says

that if either number has a 1 in it, but not both, a 1 will result. A seemingly small
difference, but crucial. Using the same two numbers, the result would be 1100b. The first
two bits have a 1 in either the first or the second number but not both. The third bit has a
1 in both numbers which results in a 0. The fourth has no 1's at all, so the result is 0. The
difference may seem small, even though the OR and XOR result in different answers.
The main use of an XOR is to test two numbers against each other. If they are the same,
the result will be all 0's, otherwise the answer will have 1's where there are differences.
Compliment
Complimenting a number results in the opposite state of all the 1's and 0's. Take the
number 1111b. Complimenting results in 0000b. This is the simplest operator of all and
the easiest to understand. It's uses are varied, but necessary, as you'll see later.
Rotate
These instructions rotate bits in a byte. The rotation can be left or right, and is done one
bit each instruction. An example might be where the accumulator has a 11000011b in it.
If we rotate left, the result will be 10000111b. You can see that bit 7 has now been moved
into bit 0 and all the other bits have move 1 bit position in, the left direction.
Clear
This instruction clears, or zero's out the accumulator. This is the same as moving a 0 into
the accumulator. This also clears the C flag and sets the Z flag.
BOOLEAN
There are other commands that deal with single bit values. In a program, an 8 bit byte
location may be used as 8 separate flags or indicators, defined by the programmer, and
used to signal events or conditions between separate parts of a program. This might be a
bit that indicates whether a door is open or closed, or whether a key has been pressed or a
switch is closed or open. These bits or flags are usually the mechanism that keeps law
and order in the program, and insures that the program does not get "lost" or misdirected.
We'll see how this works later.
There are instructions to do the same things with bits that are done with bytes by other
instructions. You can AND, OR, SET, CLEAR, or MOVE bits. You will see in a later
lesson how these are used.

BRANCHING
There are also program flow commands. These are branches or jumps. They have several
different names reflecting the way they do the jump or on what condition causes the
jump, like an overflow or under flow, or the results being zero or not zero. But all stop
the normal sequential execution of the program, and jump to another location, other than
the next instruction in sequence.
Jump on Bit
These instructions let you make a jump based on whether a certain bit is set (a 1) or
cleared (a 0). This bit can be the CY (carry) flag, the Z (zero) flag, or any other bit.
Compare and jump
These instructions compare two values and jump based on the result. In lesson 1 we
looked at a glass filling with water and compared it to a full one in our mind, and if it
wasn't full we looked at it some more. This caused that program to loop, or wait, until the
glass was full before continuing on.
Call
There is also a variation on a jump that is referred to as a CALL. A CALL does a jump,
but then eventually comes back to the place where the CALL instruction was executed
and continues with the next instruction after the CALL. This allows the programmer to
create little sub-programs, or subroutines, that do repetitive tasks needed by the main
program. This saves programming time because once the subroutine is written, it can be
used by the main program when ever it needs it, a kind of way to create your own
instructions.
DATA TRANSFER
Moving
These instructions do exactly what you would think. They move data around between the
various registers and memory.
Exchanging
Exchanging is a variation on the move instruction. Here data is exchanged between two
places.
Exchange Digit

This is a variation on the exchange instruction. Here the lower nibble, or digit, is
exchanged with the lower nibble of the other location. The upper nibble is the left 4 bits
(bits 4 through 7) and the lower nibble is the right 4 bits (bits 0 through 3).
Swapping
This is another variation on the exchange instruction, but here the data exchange occurs
between the upper nibble and the lower nibble in the accumulator.
This is the end of lesson 3. I've tried to show all the possible instructions without actually
showing each. I will, in a later lesson, go into each of the 110 different instructions and
explain each one. In the next lesson we will learn more about memory and all the
possible ways to get to a memory location.
My email address is here and I would welcome your questions or comments as you
proceed through this course. Depending on the volume of mail I get, it may take a couple
of days or so for me to get back to you, but be assured, I will get back to you. I really do
want you to understand the information I'm presenting, and not being a professional
teacher, I might not always explain things to the satisfaction of everyone, but with your
patience, I'll do my best. My home page is />

The DS5000 Micro controller.
Well, finally, this is what all the previous lessons have been getting you ready for. To
start looking at the micro we will be using in this course. All the previous lessons have
been laying the ground work and basic concepts common to most micros. The one we
will be using is the Dallas Semiconductor DS5000 micro controller. This chip, in my
mind, is one of the neatest ones ever made. Dallas Semiconductor knew what to put in a
chip. There are a few external parts needed along with the DS5000, but they are few, and
cheap to buy. I will give you a schematic and a parts list, along with the places to get all
the parts later.
I would recommend that you get the Secure Micro controller Data Book
(in PDF format)
from Dallas Semiconductor, as soon as you can. The paperback version is out of print
now. The telephone number is 972 - 371 - 4448. They are located in Dallas Texas at 4401

South Beltwood Parkway, zip 752444-3292. It's loaded with information and is
absolutely crucial for a good understanding of the DS5000. The book actually covers
several versions of the 5000 series of microcontroller chips.
My hope is that you will buy one of the DS5000 parts and really start building things
with it. I think it costs about $75. Cheap, considering what you can do with it. But don't
buy it yet, I'll tell you when. There is still lots to learn before you will be able to start
building something with it.
The DS5000 is a microcontroller based on the Intel 8051 microprocessor. It looks like an
8051 as far as programming and the general pinout of the package. The pinout refers to
the physical package and what each pin on the package is used for. But the DS5000 is
much more. There are 40 pins on the package. Of these pins, 32 are connections to the
outside world that information can be brought into or out of the DS5000. There are a few
other pins, but more on them later.
These 32 pins show up inside the package as 4 ports. Each port is 8 bits wide and have
the names p0, p1, p2, and p3. Each port can be inputs or outputs to or from the outside.
Besides being inputs and outputs, p0, p2, and p3 have special functions assigned to them.
P0 and p2 are used for external memory interface, which we will not use since there is
plenty of memory inside the DS5000. These 16 pins will be used for input / output. But if
we were talking about an 8051, this is where memory would connect. Half of the pins of
port 3 will be used for their special functionality. The other four pins of p3 will be used
as regular inputs and outputs, not using their special functions. These functions will be
discussed later, however.
Two pins of p3 are for serial communications with the DS5000. Through these pins,
serial data can be sent or received with another computer. This is how we will load a
program into the DS5000 from a PC.
Two more pins are for a different kind of input called interrupts. In our example in lesson
1 of the program where we are standing at the street corner, watching the light and the
traffic, if a person walked up and tapped us on the shoulder and asked what time it is, this
would be an example of an interrupt. It doesn't alter the program we are doing, it just
temporarily stops us while we tell the time to the person. As soon as we tell the time, we

go back to watching the lights and traffic as before. This describes the action of an
interrupt.
The interrupt has a program associated with it to guide the micro through a problem. In
the case of the above example, this program would be to look at our watch, read the time,
and then tell it to the person. This is called an interrupt service routine. Each time an
interrupt occurs, the current program is temporarily stopped and the service routine is
executed and when complete, returns to the current program. We will spend a lot more
time later describing interrupts and how we'll use them.
Inside the DS5000 is a 128 byte memory area called internal ram (random access
memory). The first 32 bytes are used for 4 banks of registers. They are called bank 0,
bank 1, bank 2, and bank 3. When the micro is first powered up, bank 0 is the selected
bank. Afterwards there is a command which allows switching to another bank, but we
won't do that right now. Inside each bank there are 8 seperate registers. They are called
r0, r1, r2, r3, r4, r5, r6, and r7. These registers are used for temporary storage of whatever
is needed by the program. There is also a register that is the accumulator called a. This
register is different from the other 8 registers. It is used to accumulate the results of
various instructions like add or sub (subtract).
The next 16 bytes of internal ram are for bit storage and retrieval. This allows for 128
different bits that can be used by the program. Most early micros didn't have this very
useful feature.
The last 80 bytes of internal ram are for general storage and is used for many different
things.
There is another 128 byte area of memory called the special function registers. This is
where p0, p1, p2, and p3 are located. The accumulator and program counter are also in
this area along with other registers that control various aspects of the operation of the
DS5000. More on these as they come up later.
Lastly there is one more area of memory that is divided into two parts. The program
memory and the data memory. This is in reality a block of 32K (32768) bytes of ram that,
through the programming of one of the special function registers, can be divided into the
two sections. In most of our work we will divide this up into 16K (16384) bytes of

program and 16K (16384) bytes of data. The program memory is write protected so that
an errant program can't change itself accidently and really make a mess out of things. The
data memory can be written to or read from as needed by the program.
There is a lithium battery inside the DS5000 that keeps all the memory alive when power
is turned off. This is one of the neatest features of the DS5000, and I don't know of
another micro that has this. In most micros there is PROM ( programmable read only
memory) or EPROM (erasable programmable read only memory), as the program
memory. PROM can be programmed once and that's it. EPROM can be programmed and
then erased with ultra violet light through a glass window in the micro's package. But this
requires a special programmer and an ultra violet light source for erasure (over $125
worth of stuff!!).
But in the DS5000, 2 of the pins can be placed in a special state, and the program
downloaded to the chip through the serial port from a PC. There is a special program
inside the DS5000 that allows all this to happen, that goes away when these 2 pins are
returned to their normal state. This special program can be accessed anytime to change
the user program by, in our case, flipping a switch, downloading the program, and then
returning the switch to its normal position. Neat, huh? It takes just a few seconds to do
this, where it used to take a half hour to go through the erase / program cycle of an
EPROM based micro. And no special hardware is needed, other than the serial port.
This speeds up program development and allows a change to be made to the program,
downloaded to the micro, and executed, in under a minute. Slick!!! It will still take plenty
of time to develope and debug a program, but very little time or effort to get the program
into the DS5000, ready to run.
I have also located a free 8051 simulator for your use that will allow you to test small
programs out on your PC without downloading them to the DS5000. You can see all the
registers change as the program is stepped through each instruction. This greatly speeds
up the debugging process, and is an educational tool that shows how each instruction
affects the various parts of the DS5000. We will use this in later lessons to illustrate the
different instructions and programs that we will write.
There are other features to be covered later, as they come up. In the next lesson we will

start looking at assembly language, the method we will use to write a program.
My email address is here and I would welcome your questions or comments as you
proceed through this course. Depending on the volume of mail I get, it may take a couple
of days or so for me to get back to you, but be assured, I will get back to you. I really do
want you to understand the information I'm presenting, and not being a professional
teacher, I might not always explain things to the satisfaction of everyone, but with your
patience, I'll do my best. My home page is .
What is Assembly Language?
Inside the DS5000, instructions are really stored as hex numbers, not a very good way to
look at them and extremely difficult to decipher. An assembler is a program that allows
you to write instructions in, more or less, english form, much more easily read and
understood, and then converted or assembled into hex numbers.
The program is written with a text editor ( I'll furnish you with one), saved, and then
assembled by the assembler (I'll furnish you with one). The result is the file you
download to the DS5000. Here is an example of the problem of adding 2 plus 2: [This file
will be called prob01.asm]
mov r0,#2
mov a,#2
add a,r0
The first line moves a 2 into register r0. The second moves a 2 into the accumulator. This
is all the data we need for the program. The third line adds the accumulator with r0 and
stores the result back into the accumulator, destroying the 2 that was originally in it. The
accumulator has a 4 in it now and r0 still has a 2 in it.
Assembly language follows some rules that I will describe as they come up. With most
instructions, especially those involving data transfer, the instruction is first, followed by
at least 1 space, then the destination followed by a comma, and then the source. The
destination is where the result of the instruction will end up and the source is where the
data is coming from.
Next we will read a switch, and light an led if the switch is pressed. Bit 0 of p1 will be
the switch. When the switch is closed or pressed, bit 0 will be a 1, and if the switch is

open or not pressed, bit 0 will be a 0.
Bit 0 of p0 will be the led. If bit 0 is a 0 the led is off and if bit 0 is a 1, the led will be on.
All the other bits of both p0 and p1 will be ignored and assumed to be all 0's, for the sake
of discussion. [This is prob02.asm]
start: mov a,p1 ;read the switch
mov p0,a ;write to the led
sjmp,start ;go to start
The first line has something new. It's called a label. In this case it is start:. A label is a
way of telling the assembler that this line has a name that can be referred to later to get
back to it. All labels are followed by the symbol : , which tells the assembler that this is a
label. Also a comment can be added to the line to remind you of what that line does. A
comment is always started with a ; which tells the assembler to ignore all that follows on
that line because it is a comment.
In the first line we also read the switch by reading p1 (the source) and putting it into the
accumulator (the destination).
The next line writes the accumulator, which has the switch in it (the source) to p0, which
has the led attached (the destination).
The last line jumps back to start. This completes the loop of reading the switch and
writing to the led.
I hope you see that if the switch is closed, the first line will result in a 1 in the
accumulator. In the second line, writing a 1 to p0 will light the led. If the switch is open
in line 1, there will be a 0 in the accumulator which, when written to p0, will turn off the
led. This loop would continue, endlessly, reading the switch and writing the led, until the
micro is turned off, or a new program loaded. If the switch is pressed, the led will be lit,
otherwise it won't
This particular problem could have been solved with just a switch connected to an led,
like a light is connected to a wall switch in your house. But with a micro in the loop,
much more could be done. We could have a clock that also turns on and off the led based
on time. Or we could monitor the temperature and turn the led on and off based on what
temperature it is. Or we could monitor several switches and turn the led on and off based

on a combination of switches.
In the above example we assumed that the other bits of p0 and p1 were all zeros. But in
reality, each of these bits could have a function assigned to them. Then we would need to
look only at bit 0 in p0 and bit 0 in p1. This further complicates the problem.
In assembly we can assign a name to a bit and refer to it by that name, instead of a bit in a
port. This is done with an equate directive. Directives are assembler commands that don't
result in program but instead direct the assembler to some action. All directives start with
a period.
In the DS5000 there are many bit locations. 128 of them were discussed in the previous
lesson. There are others like all the bits in the accumulator, all the bits in the p0, p1, p2,
and p3 ports. Each one is assigned an address by the DS5000 and can't be changed. The
first 128 are the 16 bytes of internal ram following the first 32 bytes. Bit 0 of p0 is
address 128 (80h) and bit 0 of p1 is address 144 (90h). Now let's look at what this looks
like in assembly. [This is prob03.asm]
.equ switch,144 ;p1 bit 0 is now called switch
.equ led,128 ;p0 bit 0 is now called led
start: mov c,switch ;get the state of the switch and put in
carry

mov led,c ;mov the carry flag to the led
sjmp start ;jump to start
This has the same result as the previous program, but doesn't assume anything about the
other bits in p0 and p1. Also the equate only has to be made once at the start of the
program, and thereafter the name or label is used instead of the bit number. This makes
things much simpler for the programmer. Also the carry flag is used with bit instructions
like the accumulator is used for byte instructions. All bit moves must be through the carry
flag. All equates must be defined before they are used in a program. This holds true for
labels also. Another advantage of naming bits with an equate is that if, later in the design
process, you decide to use a different bit for the led or the switch, only the equate has to
be changed, not the program itself.

Another way to do the 2 plus 2 problem is to use a similiar technique. This directive is
the reserve storage directive. Here is how this would look in assembly: [This is
prob04.asm]
first: .rs 1 ;reserve a byte called first
secnd: .rs 1 ;reserve a byte called secnd
mov first,#2 ;put a 2 into first
mov secnd,#2 ;put a 2 into secnd
mov a,first ;mov first into accumulator
add a,secnd ;add secnd to accumulator
In the first line we see the .rs directive. The first part is the name or label, the second is
the directive, and the third is the amount of storage to be assigned to the name. In this
case we only needed 1 byte for each variable so only 1 was reserved for each. Also you
will notice that everything lines up vertically. This is only for readability for the
programmers sake of clarity. The rule that the assembler uses is that at least 1 space must
be between each part of the line. Also the names can be much longer, but I prefer short
names so I don't have to type so much. Plus by using short names, more space is left for
the comment field. Comments are very important. When you initially write a program,
the tendancy is not to write much in the comment field because you're in a hurry. But if
you have to come back to it a few weeks later, it's much easier to understand what you've
written if you've taken the time to write good comments. Also good comments help in
debugging.
In this example, we reserved two bytes and stored a 2 in each one. Then we got the first
one (first) and put it into the accumulator. Then we added the second (secnd) to the
accumulator. Now the accumulator has a 4 in it, and first and secnd still have a 2 in them.
This method also has the advantage of being able to not worry which byte is first and
which byte is secnd, because the assembler takes care of it for you. The difference
between a .rs and a .equ is that with the .equ you tell the assembler exactly which bit you
want to name, where with the .rs, the order of the reserve storage determins which byte is
which. It really doesn't matter which is which, because you refer to them as names
instead of actual locations.

In the DS5000, there are several ways of addressing variables. One is the register
addresses, r0, r1, r2, and so on. Another is by direct addressing. This uses the actual
address in internal ram where the variable is. Using a name with the .rs directive is a form
of direct addressing. Here the assembler assigns the actual address of the named variable
by which order the .rs's are in. If the variable first was actual location 0 then the variable
secnd would be actual location 1. Location and address mean the same thing. When the
assembler assembles the program, the names are dropped (to protect the innocent) and the
actual addresses are used.
Another form of addressing is called immediate addressing. This is the form used in the
original 2 plus 2 problem. It is indicated by the # symbol in front of the number. This tells
the assembler that the number is in the instruction, not somewhere else. Also this method
was used in the above example where the variables first and secnd were loaded with a 2.
The 2 was in the instruction not somewhere else. But when we started getting the
numbers to add we used direct addressing, using the names. Here the 2's were in locations
and not in the instruction. Here are those instructions and what type of addressing was
used in each:
first: .rs 1 ;this is a directive not an instruction
secnd: .rs 1 ;so is this one
mov first,#2 ;direct,immediate
mov secnd,#2 ;direct,immediate
mov a,first ;implied,direct
add a,secnd ;implied,direct
Here's the original 2 plus 2 problem and the addressing modes of each instruction:
mov r0,#2 ;register,immediate
mov a,#2 ;implied,immediate
add a,r0 ;implied,register
Notice that each instruction can have two different addressing modes, one for the
destination and one for the source. Also notice that the a is an implied address. Register
refers stictly to the registers r0, r1, r2, and so on, even though I've referred previously to
the accumulator as a register. This comes partly from my experience with the Zilog Z-80

microprocessor, where the accumulator is a register. In the DS5000 the accumulator is in
the special function registers but the instruction implies that the accumulator will be used
as either the source or the destination, depending on the instruction. Implied is a method
of addressing that shortens the number of bytes any particular instruction assembles into.
To digress just a little here, an instruction like add a,r0 is a one byte instruction. In
other words this instruction would end up inside the DS5000 as one byte. Part of the byte
is the opcode and the other part is which register is affected or used. The reason for this is
that a prime concern in programming a micro is how may bytes the program will actually
take up inside the micro, after it's been assembled. The idea is to cram as much as
possible into as few bytes as possible. This is why implied addressing is used. It limits
choices in the use of the instruction, you always have to use the accumulator as either the
source or the destination, but it shrinks the size of the instruction, so that more
instructions can fit inside the micro. This is a choice made by the maker of the micro, and
is not up for discussion. It's a trade off of flexibility vs. size. That's why you'll see lots of
instructions that use the accumulator. This is the best way to describe implied addressing.
In the case of an instruction like add a,secnd ,two bytes are assembled. The first byte
says that this is an add instruction and that the accumulator is implied as the destination.
The second byte is the direct address of the source variable, secnd. This is transparent to
the programmer because we are using an assembler, but the underlying results are
noteworthy when trying to cram the most into the DS5000. Well enough of that. We will
probably get into this again, later.
Another form of addressing variables is called register indirect or just plain indirect
addressing. This is a little more complicated. Here the address is held in a register, either
r0 or r1. The following is another example of the 2 plus 2 problem using register indirect
addressing. [This is prob05.asm]
buffer: .rs 2 ;reserve two locations for the data
mov r0,#buffer ;set r0 to the start of the buffer
mov @r0,#2 ;put a 2 into the first location of the
buffer


inc r0 ;increment r0 to point to the second byte
mov @r0,#2 ;put a 2 into the second location of the
buffer

mov r0,#buffer ;set r0 to the start of the buffer
mov a,@r0 ;get the first 2
inc r0 ;step to the second 2
add a,@r0 ;add the second 2 to the first 2
Line 1 is again a reserve storage directive, but this time we are reserving two locations,
one for each 2 in the problem. Line 2 sets r0 to point to the first location of the buffer
we've created with the .rs directive. As stated before, the # means immediate, but in this
case the assembler sees that the first character after the # is not a number, and, instead
finds the label buffer and gets the direct address of where it is in the internal ram and
puts that address in r0, immediately. That's a mouthfull but that's what happens on that
one line!
Line 3 stores a 2 in the first location of buffer. The @ symbol tells the assembler that
the following register holds the address (indirect) of where to put the 2 into. So after this
instruction, the first byte of buffer has a 2 in it. Line 4 increments or steps r0 to the
second location in buffer. If r0 had the address of the first byte, then incrementing it by
1 now results in the address of the second byte being in r0.
Line 5 does the same thing that line 3 did, except that the 2 is stored in the second byte of
buffer. Line 6 does the same thing that line 2 did, getting r0 to point to the first location
in buffer. Line 7 moves the first byte of buffer (the first 2)into the accumulator. Line
8 steps r0 to the address of the second 2 in buffer. Line 9 adds the second 2 to the first 2
and stores the result in the accumulator.
Repeating what we did for the other example programs, here are the addressing modes of
each line:
buffer: .rs 2 ;this is a directive, not an instruction
mov r0,#buffer ;register,immediate
mov @r0,#2 ;indirect,immediate

inc r0 ;this is arithmetic, adding 1 to r0
mov @r0,#2 ;indirect,immediate
mov r0,#buffer ;register,immediate
mov a,@r0 ;implied,indirect
inc r0 ;arithmetic, adding 1 to r0
add a,@r0 ;implied,indirect
Here is another example of the 2 plus 2 problem done still a different way: [prob06.asm]
buffer: .rs 2 ;reserve 2 bytes for the data
mov #buffer,#2 ;put a 2 in the first location in buffer
mov #buffer+1,#2 ;put a 2 in the second location in buffer
mov a,buffer ;move the first 2 into the accumulator
add a,buffer+1 ;add the first 2 to the second 2
Line 1 reserves 2 bytes and names it buffer. Line 2 puts a 2 into the first location of
buffer. Line 3 puts a 2 in the second location of buffer. Line 4 moves the first 2 into
the accumulator. Line 5 adds the first 2 to the second 2 and stores the result into the
accumulator. There are still other ways to solve this problem. In fact, if a problem was
given to 100 programmers, there would probably be 100 different programs, all with the
same results.
Lastly, I want to explain something else about the assembler. Since there are two distinct
memory areas in the DS5000, there must be a way to describe to the assembler which one
is being referred to at any particular place in the source file. The source file is what the
above program, or any program that has been written, is referred to. It is the source for
the assembler, or the file that is going to be read by the assembler to generate the object
file (the object of the assembler) from. The object file is the file that will be download to
the DS5000. They are two different files. One you've written with a text editor (the
source file) and the other is created by the assembler (the object file) when you assemble
the source file. You use an assembler with the object in mind of generating a file to
download to the micro, hence the name, object file.
I've left out some directives from the previous programs, for simplicities sake, that I need
to mention now. One is the .org directive. It is the originate or origin directive. This tells

the assembler at what address the first byte of assembled code is to be placed inside the
DS5000. It is the origin of the program or the beginning. Here's how this would look for
our last example program:
.org h'0000
mov r0,#buffer ;set r0 to the start of the buffer
mov @r0,#2 ;put a 2 into the first location of the
buffer

inc r0 ;increment r0 to point to the second byte
mov @r0,#2 ;put a 2 into the second location of the
buffer

mov r0,#buffer ;set r0 to the start of the buffer
mov a,@r0 ;get the first 2
inc r0 ;step to the second 2
add a,@r0 ;add the second 2 to the first 2
.segment .memory
.memory
.org h'00
buffer: .rs 2
The first part is the same with the exception of the .org. This tells the assembler that the
first byte of code will be assembled at address 0000h, in this case. Later in the program is
another directive called
.segment. This tells the assembler that a different area of
memory named .memory will be used now. This represents the internal ram. The next line
has a
.memory directive. This switches to the internal ram memory. The .org following
this is telling the assmbler that the first .rs is located at address 00h. So the address of
buffer is 00h or just 0. This is the value or address that is loaded into r0 when the mov
r0,#buffer

is executed.
Well we've covered quite a lot in this lesson, and I hope you've gotten most of it. If not, I
would suggest re-reading it until you do. I would also suggest that you print out all of
these lessons so you can refer to them later. In the next lesson we will actually be
assembling these programs and running them in the simulator for a closer look at what
happens inside the DS5000. This is where it really gets good.
My email address is here and I would welcome your questions or comments as you
proceed through this course. Depending on the volume of mail I get, it may take a couple
of days or so for me to get back to you, but be assured, I will get back to you. I really do
want you to understand the information I'm presenting, and not being a professional
teacher, I might not always explain things to the satisfaction of everyone, but with your
patience, I'll do my best. My home page is
Using an Assembler and Simulator
I would suggest that you create a directory somewhere on your hard drive called
COURSE and put the following files in this directory. They are all zipped and you will
need PKUNZIP from PKWARE or a similar unzipper to extract the files. All these
programs are DOS based and should be ran under DOS. If you are using WIN3.1 or
WIN95 you'll need to get to DOS. If you're a power user you could setup icons to run
these programs, but my explanations and examples will assume that you are at the DOS
command line C:\COURSE prompt.
I've spent several hours searching the net to find all these files. All are either shareware or
freeware and there should be no ethical problems using them for this course. You should,
however, purchase all of them in the event you continue using them after the course. I
can't give you license to use them, but for educational purposes, I don't think that there
will be any problems. Most of these programs have manuals that explain how they work.
Print these out for future reference. I've lost the docs for QEDIT and BR but if you've
ever used a text editor or browser, you shouldn't have any problem using them.
The assembler we are going to use is made by Pseudo Corp and can be downloaded here.
The simulator is made by HiTech Corp and is here. The examples from lesson 6 are here.
The text editor QEDIT , by SemWare, can be downloaded here. A text browser can be

downloaded here. Any text editor can be used to create the assembler source files. You
could even use notepad in Windows. I am giving you the ones in lesson 6 already typed
up. Also, a handy 8051 reference can be downloaded here
. It is a TSR that can be loaded
once before starting the assembler or simulator, and then invoked by pressing a couple of
keys together. It has some good info and might be useful in the process.
For those of you who just can't wait, here
is a rough draft of the system we will use later
on in this course for training purposes. It's isn't finished (all the parts are not marked) but
all the pin numbers and the general connections are complete, and could be built, but
don't. I'll give you the real thing later on. There is a text file describing how to print it out,
read it before trying to print it!
The first step in writing a program is to define the problem as completely as possible.
You will always think of things as you go along that you left out. After thinking out the
problem, you start by typing up a source file. I have already typed up all the sample files
in lesson 6 and assembled them. The source files all end with the .asm extension. The
extensions created by the assembler are
.obj which is the object file and .lst which is
the listing file. The listing file shows all the addresses resolved by the assembler, all the
code generated and all the comments. This file is very important in using the simulator.
In the simulator, there are no labels shown because the simulator really dis-assembles the
object file as it is loaded into the simulator. No names are listed in the simulator so the
listing file is used to keep up with where the simulator really is. You'll see all this as we
go along. The listing file also shows any errors in the assembly process so that you can
correct them. It is crucial that you look at the listing file to be sure that there are no errors
listed.
One note, the assembler creates object files with the extension .obj but the simulator
looks for object files with the extension .hex. So you have to rename them after
assembly before loading them into the simulator. Sorry about that, but that's the way it
works. I have already renamed the problem object files for you, but any you create will

have to be renamed each time you assemble a file before loading them into the simulator.
The simulator is a way to test your programs without downloading them to the DS5000.
This means, for our purposes, you don't have to have a DS5000 to learn to use a DS5000.
The way you would use it in real life is to write each program, assemble it, and then load
it into the simulator. After all the different pieces of the whole program have been tested,
you would combine them into one file, possibly test it again, and then download it to the
DS5000. This particular simulator isn't fancy, and there are better ones, especially the one
from Pseudo Corp, the one I use when I'm making something ($199). But this one is free
and will do for our purposes. The only thing that it can't do is simulate an interrupt, but
this can be worked around and I'll show you how later.
We are going to look at some of the examples from the last lesson and watch them in
action in the simulator. We're not going to look at all of them, but you can look at the
others on your own. The first we will look at is PROB01.ASM. I am assuming that you
followed my directions and created a directory to hold all the files listed on this page.
These should include the assembler program, the editor program, the simulator program,
and all the example files from lesson 6. Also you are in that directory at the DOS prompt.
The first thing to do is start the simulator. Do this by typing
SIM51EM and press ENTER.
You are now looking at the simulator screen with all the various sections of the 8051.
The screen is divided into six sections. Each section is separated by dashed lines. The top
section is the Registers section.On the left side starting on the 8th line are the names
Addr, Opcode and Instructions. This is the Code section. On the Right starting on line 4
is the Internal RAM section. Below that is the External RAM section. Below that is the
Program memory section. Below that is the Function Key assignments and what each
does. To the left of that is two boxes, one that says File and the other says Select. Below
that is the command line with the flashing cursor.
Of these sections, we will be concerned with the Register, Code, and Internal RAM
sections, the function keys, and the command line. I will describe each as this discourse
continues. Notice that in the function key section, the F7 File IO is highlighted. Also on
the far left of that, a box that says FILE is shown. Inside that box are Name file, Read

file, and Write file. These are the commands that can be entered on the command line.
Only the capital letter of each is used. So to name a file you press N, to read a file you
press R and to write a file you press W.
First we must name the file we want to load into the simulator. Press N and enter
PROB01.HEX and press enter. Now PROB01.HEX should appear on the line. Press enter
to accept it. Now press R(READ) and Y to accept PROB01.HEX. PROB01.HEX is now
loaded into the simulator.
Looking at the Code section we see under Addr a column of 4 digit numbers. On the first
line we see a 0000 followed by 7802, MOV R0,#02. The 0000 says that this is location
0000 in Program memory ( the first location). The 7802 is the actual two byte Opcode
that is assembled from the MOV R0,#02 instruction. The 78 says that this is a MOV
immediate into R0 and the 02 is the value moved into R0. Also notice that this line is
highlighted. This is the instruction that will be executed next. Notice above the Code
section is R0 and the value below it is 00. This is what is currently in R0. Also notice that
at the top of the screen in the Register section is ACC and below that a 00. This is what is
currently in the accumulator. And lastly notice the PC and the 0000 below it. This is the
current value in the Program Counter.
The next thing we must do is to start executing the program. To do this first press F5.
Notice the left two boxes have now changed to Breakpoint and Misc. These are the
commands that can now be entered on the command line. Notice the Single step in the
right box. To single step the program one instruction, press S. Do that now, but only
once. Notice that now in the Code window the highlight is on the next line. Also notice
that R0 now has a 2 in it. We have just executed our first instruction, to put a 2 in R0.
Notice that the ACC is still 0. Also notice that the PC is now 0002. Remember that the
PC always points to the instruction that will be executed next. Now press S again. Now
the ACC has a 2 in it as does R0. Also the PC is now 0004. We have just executed the
second instruction, to move a 2 into the accumulator. We are now ready to add 2 plus
2.Now press S again. Now the accumulator has a 4 in it. This is the result of adding 2
plus 2. This also finishes this program.
Notice that in the Code window below the three instructions that were in this program

that the rest of the lines have NOP in them for the Instruction. Also notice that the
Opcode is 00. A NOP is an instruction that does nothing and happens to have an Opcode
value of 00. These are here because all the rest of Program memory has 0's in them,
which we didn't load with anything, but are interpreted as NOP's. This is normally what
you will see following the last instruction in a program.
In review, the Opcode is the actual value that the assembler assembles for an instruction
and is what the micro understands and can execute. The Instruction is the english form of
the Opcode and is for the benefit of the programmer.
To exit the simulator, first press F1 and then E and Y. This completes the first session
with the simulator. You can simulate this program again by repeating the previous steps.
Next we will simulate PROB04.ASM. Start the simulator, name PROB04.HEX, and read
it. Also you will need the list file for this program (PROB04.LST) printed out for
reference. You need to set your printer for condensed because the lines are longer than 80
characters.
About the listing file PROB04.LST, you'll notice that this resembles the source file
PROB04.ASM but with three extra columns of numbers to the left. The left most column
is line numbers and is just for reference. The next column is addresses or memory
locations. They mean different things depending on what part of the listing your looking
at. Notice that on line 3 there is an org 8. This is telling the assembler to start reserving
internal ram locations with location 8. The next line has an 8 in the second column. This
is the location reserved for the variable first. Line 5 has a 9 in this column. Location 9
is reserved for the variable second. I mention these because in the simulator there are no
labels shown but instead you'll see the numbers 8 and 9 used. This is some of what the
assembler takes care of for you. You get to reference the variables by name in the source
file, while the micro uses numbers to reference them. Now look at line 7. Here is an org
0. This tells the assembler to start assembling code at location 0000h. Notice that on line
8 there is a third column of numbers. This is the actual opcode generated by the
assembler for a given instruction. You will see these numbers in the simulator in the code
window along with the numbers in the second column.
I tell you this to show you the relationship between the listing file and the code window

in the simulator. Since there are no labels in the simulator, the listing file can be used to
interpret the code window in the simulator and keep up with where you are in the
simulator.
With the simulator started and PROB04.HEX loaded, notice that all the registers have a 0
in them to start with. Also notice the first 4 lines in the code window. These are the 4
instructions in the listing file. See the simularity between the 2nd and 3rd colums in the
listing file and the code window. Also notice that none of the lines in the listing file
above the instructions are listed in the code window. All these lines are for the assembler
only and don't generate any code.
Now single step once. Notice that in the Int Ram window, on the second line there is an
0008 and beside that an 02. This is the 02 that was loaded into
first which had location
8 reserved for it by the assembler. So the result of MOV first,#2 was to put a 2 in
location 8 of the internal ram. The layout of the Int Ram window is the location followed
by 8 bytes of data. The 8th byte on that line is location 07h. The next line starts with
location 08h and goes through location 0fh. The next line starts with location 10h and
ends with location 17h, and so on.
Now single step once. Notice that location 09 in the internal ram now has a 2 in it. Single
step again and notice that there is now a 02 in the accumulator. We have just moved the 2
from location 8(first) and put it in the accumulator. Single step again and notice that the
accumulator has a 04 in it. We have just added location 9(secnd) to the accumulator with
the result in the accumulator. We are now done with the program, and the second session
of using the simulator. Exit the simulator to get ready for the next and last example.
Now start the simulator and load the PROB03.HEX file. In this example we will modify
port lines to simulate a switch being closed. Remembering back to PROB03.ASM, p1 bit
0 was where we connected the switch and p0 bit 0 is the line connected to the LED. If the
switch is closed we will have a 1 on p1 bit 0. If we have a 1 on p0 bit 0, the LED will be
lit.
Notice that in the Register window in the simulator, on the left side line 3 is P0 followed
by FF and 11111111. The FF is the hex representation of 11111111b. The 1's are the

individual bits or lines of p0, with the left most being bit 7 and the right most bit 0. The
same holds true for p1. So currently there is all 1's on p0 and all 1's on p1. So the switch
is closed and the LED is lit. Also notice that across the top of the register window is the
CY or carry flag and it is currently a 0. Also the first line in the code window has the
instruction
MOV C,P1.0. This says to move port 1 bit 0 into the carry flag. Single step
once. Now see that the CY has a 1 in it. We have just moved the 1 on bit 0 p1 into the
carry flag. Single step again. This moved the 1 in the carry flag to p0 bit 0. But since we
already had a 1 on that bit, no difference was noticed. Notice that the highlighted line in
the code window is a SJMP 0000. Notice that in the listing file PROB03.LST there is a
label on line 8 called
start. Also notice in the address column is a 0000h. So the label
start is at location 0000h. On line 10 of the listing file is a sjmp start. This says to
jump to the label start. Since start is at 0000h, that is the address shown in the code
window. This says to jump to location 0000h. This again illustrates the relationship of the
listing file to the code window Single step once more. Now we are back to the first
instruction.
Now we are going to set bit 0 of p1 to a 0. Do this by first pressing F6. Now press I for
internal ram. Now F for fill. Now enter 90 for the start, 90 for the end, and 00 for the
byte. Answer Y to the following prompt. Now see that p1 has a 00h or 00000000b in it.
We have not only put a 0 in bit 0 but a 0 in all the bits. We put a 90h for the start and stop
address for the fill because p1 is at address 90h in the 8051 and can't be changed. If you
notice in the listing file all the names and numbers that follow the program listing. These
are all the reserved names in the assembler and the corresponding addresses of each
inside the 8051. Find P1 and you will see the address 0090 to the right of it. This is the
address of p1 in the 8051. So we entered a start for the fill of 90 and a 90 for the end of
the fill. This selected the one location for the fill. You can specify a range of addresses
and fill all of them at once. That is why it asks for a start and an ending adress for the fill.
But since we only wanted to alter p1, we entered the same address for the start and end.
Now the switch would be open. Press F5 to switch back to Execute. Now single step

once. Notice that the carry flag now has a 0 in it. We have just moved the 0 in p1 bit 0
into the carry flag. Single step once. Notice that bit 0 of port 0 now has a 0 in it and the
rest of the bits are still 1's. The LED would now be off. Single step once. Now we're back
to the first instruction.
We can now put all 1's back into p1 to simulate the switch being closed again. Do this by
repeating the above steps only when it asks for the byte of data, enter FF (make sure
CAPS is set on your keyboard or it won't accept the entry) instead of 00. Now single step
through the instructions again and you will see a 1 in p0 bit 0. This would again lite the
LED. You can now exit the simulator. We have finished this program example.
Well this has been somewhat sticky, having to look at the listing file and the code
window, navigating the simulator, loading programs and altering register contents. But I
hope this has given you some insight into the simulator, the relationship of the listing file
to the code window, and some differences between the assembly source file and the hex
object file that is generated by the assembler. The fact that labels are dropped in the
assembly process and replaced by absolute addresses for the micro to use. How the
assembler lets you write a program using english names and labels in a form much easier
for the programmer to keep up with. Without an assembler, the task of writing a program
would be extremely difficult, since what ends up inside the micro is just numbers.
In my early days of micro building I hand assembled each instruction into the hex
opcodes and programmed an EPROM with them. The time consummed this way was
enormous. It was an exercise in converting assembly language into opcodes that, in and
of itself, was a total waste of time. I had to keep an intense concentration level while
doing this, and one mistake would cause the program not to work. I would then have to
go through my hand written program and not only check the logic of my instructions, but
whether I had properly assembled them into opcodes. I never want to do that again. The
tools I have furnished you with, I would have given practically anything to have had back
then. There were such tools but they cost several thousand dollars, way beyond my price
range. I considered my time to be cheap and went the route I did for that reason. But time
isn't cheap in reality, and anything you can use to better utilize it is a must. I probably
should have came up with the money to buy these tools back then but I didn't. One

project I worked on for Levi Strauss, took me 18 months to finish. With these tools I
could have done it in a few weeks, I'm sure. Well enough of that.
In the next lesson we will look at the second phase of writing a complete system. The
first phase is to define the system and what you want to accomplish with it. The next is to
write all the subroutines and functions that will be repeated throughout the system. These
are called the BIOS (Basic Input/Output System) routines and OS (Operating System)
routines.
My email address is here and I would welcome your questions or comments as you
proceed through this course. Depending on the volume of mail I get, it may take a couple
of days or so for me to get back to you, but be assured, I will get back to you. I really do
want you to understand the information I'm presenting, and not being a professional
teacher, I might not always explain things to the satisfaction of everyone, but with your
patience, I'll do my best. My home page is
.

×