Introduction To 8051 Programming
Introduction To 8051 Programming
In this section we discuss Assembly language format and define some widely used
terminology associated with Assembly language programming.
While the CPU can work only in binary, it can do so at a very high speed. For humans,
however, it is quite tedious and slow to deal with Os and Is in order to program the computer. A
program that consists of Os and Is is called machine language. In the early days of the computer,
programmers coded programs in machine language. Although the hexadecimal system was used
as a more efficient way to represent binary numbers, the process of working in machine code was
still cumbersome for humans. Eventually, Assembly languages were developed that provided
mnemonics for the machine code instructions, plus other features that made programming faster
and less prone to error. The term mnemonic is frequently used in computer science and
engineering literature to refer to codes and abbreviations that are relatively easy to remember.
Assembly language programs must be translated into machine code by a program called
an assembler. Assembly language is referred to as a low-level language because it deals directly
with the internal structure of the CPU.
Structure of Assembly language
An Assembly language program consists of, among other things, a series of lines of
Assembly language instructions. An Assembly language instruction consists of a mnemonic,
optionally followed by one or two operands. The operands are the data items being manipulated,
and the mnemonics are the commands to the CPU, telling it what to do with those items.
characters automatically. The DB directive is the only directive that can be used to define ASCII
strings larger than two characters; therefore, it should be used for all ASCII data definitions.
Following are some DB examples:
Either single or double quotes can be used around ASCII strings. This can be useful for
strings, which contain a single quote such as "O'Leary". DB is also used to allocate memory in
byte-sized chunks.
Assembler directives
The following are some more widely used directives of the 8051.
ORG (origin)
The ORG directive is used to indicate the beginning of the address. The number that
comes after ORG can be either in hex or in decimal. If the number is not followed by H, it is
decimal and the assembler will convert it to hex. Some assemblers use ". ORG" (notice the dot)
instead of "ORG" for the origin directive. Check your assembler.
EQU (equate)
This is used to define a constant without occupying a memory location. The EQU
directive does not set aside storage for a data item but associates a constant value with a data
label so that when the label appears in the program, itp constant value will be substituted for the
label. The following uses EQU for the counter constant and then the constant is used to load the
R3 register.
When executing the instruction "MOV R3, ttCOUNT", the register R3 will be loaded
with the value 25 (notice the # sign). What is the advantage of using EQU? Assume that there is
a constant (a fixed value) used in many different places in the program, and the programmer
wants to change its value throughout. By the use of EQU, the programmer can change it once
and the assembler will change* all of its occurrences, rather than search the entire program trying
to find every occurrence.
END directive
Another important pseudocode is the END directive. This indicates to the assembler the
end of the source (asm) file. The END directive is the last line of an 8051 program, meaning that
in the source code anything after the END directive is ignored by the assembler. Some
assemblers use ". END" (notice the dot) instead
of "END".
By choosing label names that are meaningful, a programmer can make a program much
easier to read and maintain. There are several rules that names must follow. First, each label
name must be unique. The names used for labels in Assembly language programming consist of
alphabetic letters in both uppercase and lowercase, the digits 0 through 9, and the special
characters question mark (?), period (.), at (@), underline (_), and dollar sign ($). The first
character of the label must be an alphabetic character. In other words it cannot be a number.
Every assembler has some reserved words that must not be used as labels in the program.
Foremost among the reserved words are the mnemonics for the instructions. For example,
"MOV" and "ADD" are reserved since they are instruction mnemonics.
Port 0
Port 0 occupies a total of 8 pins (pins 32 -39). It can be used for input or output. To use
the pins of port 0 as both input and output ports, each pin must be connected externally to a lOK-
ohm pull-up resistor. This is due to the fact that PO is an open drain, unlike PI, P2, and P3.Open
drain is a term used for MOS chips in the same way that open collector is used for TTL chips. In
any system using the 8051/52 chip, we normally connect PO to pull-up resistors.
Port 0 as input
With resistors connected to port 0, in order to make it an input, the port must be programmed by
writing 1 to all the bits. In the following code, port 0 is configured first as an input port by
writing Is to it, and then data is received from that port and sent to P1.
Port 1
Port 1 occupies a total of 8 pins (pins 1 through 8). It can be used as input or output. In contrast
to port 0, this port does not need any pull-up resistors since it already has pull-up resistors
internally. Upon reset, port 1 is configured as an input port. The following code will continuously
send out to port 1 the alternating values 55H and AAH.
Port 1 as input
If port 1 has been configured as an output port, to make it an input port again, it must
programmed as such by writing 1 to all its bits. The reason for this is discussed in Appendix C.2.
In the following code, port 1 is configured first as an input port by writing Is to it, then data is
received from that port and saved in R7, R6, and R5.
Port 2
Port 2 occupies a total of 8 pins (pins 21 through 28). It can be used as input or output. Just like
PI, port 2 does not need any pull-up resistors since it already has pull-up resistors internally.
Upon reset, port 2 is configured as an input port. The following code will send out continuously
to port 2 the alternating values 55H and AAH. That is, all the bits of P2 toggle continuously.
Port 2 as input
To make port 2 an input, it must programmed as such by writing 1 to all its bits. In the following
code, port 2 is configured first as an input port by writing 1 s to it. Then data is received from
that port and is sent to PI continuously.
provides the lower 8 bits via AO - A7, it is the job of P2 to provide bits A8 -A15 of the address.
In other words, when the 8051/31 is connected to external memory, P2 is used for the upper 8
bits of the 16-bit address.
The instruction ADD is used to add two operands. The destination operand is always in
register A while the source operand can be a register, immediate data, or in memory.
Remember that memory-to-memory arithmetic operations are never allowed in 8051
Assembly language. The instruction could change any of the AF, CF, or P bits of the flag
register, depending on the operands involved.
Example
Show how the flag register is affected by the following instructions.
After the addition, register A (destination) contains 00 and the flags are as follows:
CY = 1 since there is a carry out from D7.
P = 0 because the number of Is is zero (an even number).
AC = 1 since there is a carry from D3 to D4.
Example
In byte-by-byte multiplication, one of the operands must be in register A, and the second operand
must be in register B. After multiplication, the result is in the A and B registers; the lower byte is
in A, and the upper byte is in B. The following example multiplies 25H by 65H. The result is a
16-bit data that is held by the A and B registers.
Table
When dividing a byte by a byte, the numerator must be in register A and the denominator must
be in B. After the DIV instruction is performed, the quotient is in A and the remainder is in B.
See the following example.
This instruction will perform a logical AND on the two operands and place the result in
the destination. The destination is normally the accumulator. The source operand can be a
register, in memory, or immediate. . The ANL instruction for byte-size operands has no effect on
any of the flags. The ANL instruction is often used to mask (set to 0) certain bits of an operand.
See following Example.
OR
Logical OR Function
ORL destination,source ;dest = dest OR source
The destination and source operands are ORed, and the result is placed in the destination. The
ORL instruction can be used to set certain bits of an operand to 1. The destination is normally the
accumulator. The source operand can be a register, in memory, or immediate. See Appendix A for
more on the addressing modes supported by this instruction. The ORL instruction for byte-size
operands has no effect on any of the flags
XOR
XRL destination,source ;dest = dest XOR source
This instruction will perform the XOR operation on the two operands, and place the result in the
destination. The destination is normally the accumulator. The source operand can Logical XQR
Function be a register, in memory, or immediate. See Appendix A.I for the addressing modes of
this instruction. The XRL instruction for byte-size operands has no effect on any of the flags.
XRL can also be used to see if two registers have the same value. "XRL A, Rl" will
exclusive-or register A and register Rl, and put the result in A. If both registers have the same
value, 00 is placed in A.
The XRL instruction can be used to clear the contents of a register by XORing it
with itself. Show how "XRL A, A" clears A, assuming that A = 45H.
Example
Run the above program on your simulator to see how PI displays values 30H, 31H, 32H. 33H.
34H. 35H. 41H. 42H, 43H, and 44H, the hex values for ASCII 0, 1, 2, and so on.
Signed char
The signed char is an 8-bit data type that uses the most significant bit (D7 of D7 DO) to represent the - or + value. As a result, we have only 7 bits for the magnitude of
the signed number, giving us values from -128 to +127. In situations where + and - are needed to
represent a given quantity such as temperature, the use of the signed char data type is a must.
Again notice that if we do not use the keyword unsigned, the default is the signed value. For that
reason we should stick with the unsigned char unless the data needs to be represented as signed
numbers.
Example
Run the above program on your simulator to see how PI displays values of 1, FFH, 2, FEH, 3,
FDH, 4, and FCH, the hex values for +!,-!, +2, -2, and so on.