Vous êtes sur la page 1sur 24


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.


In this section we examine the role of the program counter (PC) register in executing an
8051 program. We also discuss ROM memory space for various 8051 family members.
Program counter in the 8051
Another important register in the 8051 is the PC (program counter). The program counter
points to the address of the next instruction to be executed. As the CPU fetches the opcode from
the program ROM, the program counter is incremented to point to the next instruction. The
program counter in the 8051 is 16 bits wide. This means that the 8051 can access program
addresses 0000 to FFFFH, a total of 64K bytes of code.
Placing code in program ROM
To get a better understanding of the role of the program counter in fetching and executing
a program, we examine the action of the program counter as each instruction is fetched and
executed. First, we examine once more the list file of the sample program and how the code is
placed in the ROM of an 8051 chip.

Give the short notes on data types and Directives.


In this section we look at some widely used data types and directives supported by the
8051 assembler.

8051 data type and directives

The 8051 microcontroller has only one data type. It is 8 bits, and the size of each register
is also 8 bits. It is the job of the programmer to break down data larger than 8 bits (00 to FFH, or
0 to 255 in decimal) to be processed by the CPU.
DB (define byte)
The DB directive is the most widely used data directive in the assembler. It is used to
define the 8-bit data. When DB is used to define data, the numbers can be in decimal, binary,
hex, or ASCII formats. For decimal, the "D" after the decimal number is optional, but using "B"
(binary) and "H" (hexadecimal) for the others is required. Regardless of which is used, the
assembler will convert the numbers into hex. To indicate ASCII, simply place the characters in
quotation marks ('like this'). The assembler will assign the ASCII code for the numbers or

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".

Rules for labels in Assembly language

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.


In the 8051 there are a total of four ports for I/O operations. Examining Figure 4-1, note
that of the 40 pins, a total of 32 pins are set aside for the four ports PO, PL P2, and P3, where
each port takes 8 pins. The rest of the pins are designated as V rt, GND, XTAL1, XTAL2. RST,

I/O port pins and their functions

The four ports PO, Pi, P2, and P3 each use 8 pins, making them 8-bit ports. All the ports
upon RESET are configured as inputs, ready to be used as input ports. When the first 0 is written
to a port, it becomes an output. To reconfigure it as an input, a 1 must be sent to the port. To use
any of these ports as an input port, it must be programmed, as we will explain throughout this
section. First, we describe each port.

Figure . 8051 Pin Diagram

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.

Dual role of port 2

In many systems based on the 8051, P2 is used as simple I/O. However, in 8031-based
systems, port 2 must be used along with PO to provide the 16-bit address for external memory.,
port 2 is also designated as A8 - A15, indicating its dual function. Since an 8051/31 is capable of
accessing 64K bytes of external memory, it needs a path for the 16 bits of the address. While PO

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.


Unsigned numbers are defined as data in which all the bits are used to represent
data, and no bits are set aside for the positive or negative sign. This means that the
operand can be between 00 and FFH (0 to 255 decimal) for 8-bit data.
Addition of unsigned numbers
In the 8051, in order to add numbers together, the accumulator register (A) must be
involved. The form of the ADD instruction is

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.
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.

Addition of individual bytes

Assume that RAM locations 40 - 44 have the following values. Write a program to find the sum
of the values. At the end of the program, register A should contain the low byte and R7 the high
byte. All values are in hex.
40=(7D) 41=(EB) 42=(C5) 43=(5B) 44=(30)

Subtraction of unsigned numbers

SUBB (subtract with borrow) when CY=0
In subtraction, the 8051 microprocessors (indeed, all modern CPUs) use the 2's
complement method. Although every CPU contains adder circuitry, it would be too
cumbersome (and take too many transistors) to design separate subtracter circuitry. For
this reason, the 8051 uses adder circuitry to perform the subtraction command. Assuming
that the 8051 is executing a simple subtract instruction and that CY = 0 prior to the
execution of the instruction, one can summarize the steps of the hardware of the CPU in
executing the SUBB instruction for unsigned numbers, as follows.
1. Take the 2's complement of the subtrahend (source operand).
2. Add it to the minuend (A).
3. Invert the carry.
These three steps are performed for every SUBB instruction by the internal hardware of the 8051
CPU, regardless of the source of the operands, provided that the addressing mode is supported.
After these three steps the result is obtained and the flags are set.



In multiplying or dividing two numbers in the 8051, the use of registers A and B is
required since the multiplication and division instructions work only with these two registers. We
first discuss multiplication.
Multiplication of unsigned numbers
The 8051 supports byte-by-byte multiplication only. The bytes are assumed to be unsigned data.
The syntax is as follows:

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.


Division of unsigned numbers

In the division of unsigned numbers, the 8051 supports byte over byte only. The syntax is as

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.

Notice the following points for instruction "DIV AB":

This instruction always makes CY = 0 and OV = 0 if the denominator is not 0.

If the denominator is 0 (B = 0), OV = 1 indicates an error, and CY = 0. The standard practice in

all microprocessors when dividing a number by 0 is to indicate in some way the invalid result of
infinity. In the 8051, the OV flag is set to 1.
Table : Unsigned Division Summary (DIV AB)


Apart from I/O and arithmetic instructions, logic instructions are some of most widely
used instructions. In this section we cover Boolean logic instructions such as AND, OR,
exclusive-or (XOR), and complement. We will also study the compare instruction.

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.

Logical AND Function

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

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.


Compilers produce hex files that we download into the ROM of the microcontroller. The
size of the hex file produced by the compiler is one of the main concerns of microcontroller
programmers, for two reasons:

1. Microcontrollers have limited on-chip ROM.

2. The code space for the 8051 is limited to 64K bytes.
How does the choice of programming language affect the compiled program size? While
Assembly language produces a hex file that is much smaller than C, programming in Assembly
language is tedious and time consuming. C programming, on the other hand, is less time
consuming and much easier to write, but the hex file size produced is much larger than if we
used Assembly language. The following are some of the major reasons for writing programs in C
instead of Assembly:
1. It is easier and less time consuming to write in C than Assembly.
2. C is easier to modify and update.
3. You can use code available in function libraries.
4. C code is portable to other microcontrollers with little or no modification.
Discuss about Data types and time delay in 8051C.
C data types for the 8051
Since one of the goals of 8051 C programmers is to create smaller hex files, it is worthwhile to
re-examine C data types for 8051 C. In other words, a good understanding of C data types for the
8051 can help programmers to create smaller hex files. In this section we focus on the specific C
data types that are most useful and widely used for the 8051 microcontroller.
Unsigned char
Since the 8051 is an 8-bit microcontroller, the character data type is the most natural choice for
many applications. The unsigned char is an 8-bit data type that takes a value in the range of 0 255 (00 - FFH). It is one of the most widely used data types for the 8051. In many situations,
such as setting a counter value.
In declaring variables, we must pay careful attention to the size of the data and try to use
unsigned char instead of int if possible. Because the 8051 has a limited number of registers and
data RAM locations, using the int in place of the char data type can lead to a larger size hex file.
Such a misuse of the data types in compilers such as Microsoft Visual C++ for x86 IBM PCs is
not a significant issue.


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

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.


In this section we look at C programming of the I/O ports for the 8051. We look at both
byte and bit I/O programming.
Byte size I/O
LEDs are connected to bits PI and P2. Write an 8051 C program that shows the count from 0 to
FFH (0000 0000 to 1111 1111 in binary) on the LEDs.

Bit-addressable I/O programming

The I/O ports of PO - P3 are bit-addressable. We can access a single bit without disturbing the
rest of the port. We use the sbit data type to access a single bit of PO - P3'. One way to do that is
to use the PxAy format where x is the port 0, 1, 2, or 3, and y is the bit 0 - 7 of that port.
Write an 8051 C program to toggle only bit P2.4 continuously without disturbing the rest of the
bits of P2.

Discuss About logical and arithmetic oerations in 8051C.

One of the most important and powerful features of the C language is its ability to
perform bit manipulation. This section describes the action of bit-wise logic operators and
provides some examples of how they are used.
Bit-wise operators in C
While every C programmer is familiar with the logical operators AND (&&), OR (||), and
NOT (!), many C programmers are less familiar with the bitwise operators AND (&), OR (|), EXOR (A), Inverter (~), Shift Right (), and Shift Left (). These bit-wise operators are widely used
in software engineering for embedded systems and control; consequently, understanding and
mastery of them are critical in microprocessor-based system design and interfacing. See Table .

Table : Bit-wise Logic Operators for C

Basic registers of timer programming 8051 timer counter

programming basics of serial communication 8051 connection to RS 232
8051 serial communication. Programming 8051 interrupts
programming external hardware interrupts.