0% found this document useful (0 votes)
3 views37 pages

Module 2

The document provides an overview of the 8051 microcontroller's instruction set, focusing on addressing modes, data transfer, arithmetic, logical, and control instructions. It details the various addressing modes (immediate, register, direct, and indirect) and their corresponding opcodes for moving data, along with examples. Additionally, it covers logical operations and the importance of efficient data handling in machine control applications.

Uploaded by

goldtrigger08
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views37 pages

Module 2

The document provides an overview of the 8051 microcontroller's instruction set, focusing on addressing modes, data transfer, arithmetic, logical, and control instructions. It details the various addressing modes (immediate, register, direct, and indirect) and their corresponding opcodes for moving data, along with examples. Additionally, it covers logical operations and the importance of efficient data handling in machine control applications.

Uploaded by

goldtrigger08
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Module-2

Instruction Set: 8051 Addressing Modes, Data Transfer Instructions, Arithmetic instructions,
Logical Instructions, Jump & Call Instructions Stack & Subroutine Instructions of 8051 (with
examples in assembly
Language). (Text book 2- Chapter 5,6,7,8,
Moving Data
A computer typically spends more time moving data from one location to another than it spends
on any other operation. It is not surprising, therefore, to find that more instructions are provided
for moving data than for any other type of operation.
Data is stored at a source address and moved (actually, the data is copied) to a destination address.
The ways by which these addresses are specified are called the addressing modes. The 8051
mnemonics are written with the destination address named first, followed by the source address.
A detailed study of the operational codes (opcodes) of the 805 1 begins in this chapter. Although
there are 28 distinct mnemonics that copy data from a source to a destination, they may be divided
into the following three main types:
1. MOV destination, source
2. PUSH source or POP destination
3. XCH destination, source
The following four addressing modes are used to access data:
1. Immediate addressing mode
2. Register addressing mode
3. Direct addressing mode
4. Indirect addressing mode
The MOV opcodes involve data transfers within the 805 1 memory. This memory is divided into
the following four distinct physical parts:
1. Internal RAM
2. Internal special-function registers
3. External RAM
4. Internal and external ROM
Finally, the following five types of opcodes are used to move data:
1. MOV
2. MOVX
3. MOVC
4. PUSH and POP
5. XCH
Addressing Modes
The way in which the data sources or destination addresses are specified in the mnemonic that
moves that data determines the addressing mode. Figure 3.1 diagrams the four addressing modes:
immediate, register, direct, and indirect.
Immediate Addressing Mode
The simplest way to get data to a destination is to make the source of the data part of the opcode.
The data source is then immediately available as part of the instruction itself.
When the 8051 executes an immediate data move. the program counter is automatically
incremented to point to the byte(s) following the opcode byte in the program memory. Whatever
data is found there is copied to the destination address.
The mnemonic for immediate data is the pound sign (#). Occasionally, in the rush to meet a
deadline, one forgets to use the # for immediate data. The resulting opcode is often a legal
command that is assembled with no objections by the assembler. This omission guarantees that
the rush will continue.
Register Addressing Mode
Certain register names may be used as part of the opcode mnemonic as sources or destinations of
data. Registers A, DPTR, and RO to R7 may be named as part of the opcode mnemonic. Other
registers in the 8051 may be addressed using the direct addressing mode. Some assemblers can
equate many of the direct addresses to the register name (as is the case with the assembler discussed
in this text) so that register names may be used in lieu of register addresses. Remember that the
registers used in the opcode as RO to R7 are the ones that are currently chosen by the bank-select
bits, RSO and RSI in the PSW.
The following table shows all possible MOV opcodes using immediate and register addressing
modes:
Mnemonic Operation
MOV A,#n Copy the immediate data byte n to the A register
MOV [Link] Copy data from register Rr to register A
MOV Rr,A Copy data from register A to register Rr
MOV Rr,#n Copy the immediate data byte n to register Rr
MOV DPTR,#nn Copy the immediate 16-bit number no to the DPTR register
Addressing Modes

A data MOV does not alter the contents of the data source address. A ropy of the data is made
from the source and moved to the destination address. The contents of the destination address are
replaced by the source address contents. The following table shows examples of MOV opcodes
with immediate and register addressing modes:
Mnemonic Operation
MOV A,#OFlh Move the immediate data byte Fl h to the A register
MOV A,RO Copy the data in register RO to register A
MOV DFTR,#OABCDh Move the immediate data bytes ABCDh to the DFTR
MOV R5,A Copy the data in register A to register R5
MOV R3,#1Ch Move the immediate data byte 1Ch to register R3
Direct Addressing Mode
All 128 bytes of internal RAM and the SFRs may be addressed directly using the single byte
address assigned to each RAM location and each special-function register.
Internal RAM uses addresses from 00 to 7Fh to address each byte. The SFR addresses
exist from 80h to FFh at the following locations:
SFR ADDRESS (HEX)
A OEO
B OF0
DPL 82
DPH 83
IE OA8
IP 0B8
PO 80
PI 90
P2 OAO
P3 080
PCON 87
PSW OD0
SBUF 99
SCON 98
SP 81
TCON 88
TMOD 89
THO 8C
TLO 8A
TH1 8D
TLl 8B

RAM addresses 00 to IFh are also the locations assigned to the four banks of eight working
registers, RO to R7. This assignment means that R2 of register bank O can be addressed in the
register mode as R2 or in the direct mode as 02h. The direct addresses of the working registers are
as follows:
Only one bank of working registers is active at any given time. The PSW special function register
holds the bank-select bits, RSO and RSI , which determine which register bank is in use.
When the 8051 is reset, RSO and RS I are set to OOb to select the working registers in bank 0,
located from OOh to 07h in internal RAM. Reset also sets SP to07h. and the stack will grow up as
it is used. This growing stack will overwrite the register banks above bank 0. Be sure to set the SP
to a number above those of any working registers the program may use.
The programmer may choose any other bank by setting RSO and RSI as desired; this bank change
is often done to "save" one bank and choose another when servicing an interrupt or using a
subroutine. The moves made possible using direct, immediate, and register addressing modes are
as follows:

The following table shows examples of MOV opcodes using direct, immediate, and register
addressing modes:

lndirect Addressing Mode


For all the addressing modes covered to this point, the source or destination of the data is an
absolute number or a name. Inspection of the opcode reveals exactly what are the addresses of the
destination and source. For example, the opcode MOV A,R7 says that the A register will get a
copy of whatever data is in register R7; MOV 33h,#32h moves the hex number 32 to hex RAM
address 33.
The indirect addressing mode uses a register to hold the actual address that will finally be used in
the data move; the register itself is not the address, but rather the number in the register. Indirect
addressing for MOV opcodes uses register RO or R1, often called "data pointers," to hold the
address of one of the data locations, which could be a RAM or an SFR address. The number that
is in the pointing register (Rp) cannot be known unless the history of the register is known. The
mnemonic symbol used for indirect addressing is the "at" sign, which is printed as @.
The moves made possible using immediate, direct, register and indirect addressing modes are as
follows:

The following table shows examples of MOV opcodes, using immediate, register, direct. and
indirect modes

External Data Moves


As discussed, it is possible to expand RAM and ROM memory space by adding external memory
chips to the 805 1 microcontroller. The external memory can be as large as 64K bytes for each of
the RAM and ROM memory areas. Opcodes that access this external memory always use indirect
addressing to specify the external memory.
Figure 3.2 shows that registers RO, RI, and the aptly named DPTR can be used to hold the address
of the data byte in external RAM. RO and RI are limited to external RAM address ranges of OOh
to OFFh, while the DPTR register can address the maximum RAM space of OOOOh to OFFFFh.

An X is added to the MOV mnemonics to serve as a reminder that the data move is external to the
8051, as shown in the following table.
The following table shows examples of external moves using register and indirect addressing
modes:

Code Memory Read-Only Data Moves


Data moves between RAM locations and 8051 registers are made by using MOV and MOVX
opcodes. The data is usually of a temporary or "scratch pad" nature and disappears when the system
is powered down.
There are times when access to a preprogrammed mass of data is needed, such as when using tables
of predefined bytes. This data must be permanent to be of repeated use and is stored in the program
ROM using assembler directives that store programmed data anywhere in ROM that the
programmer wishes.
Access to this data is made possible by using indirect addressing and the A register in conjunction
with either the PC or the DFTR, as shown in Figure 3.2. In both cases, the number in register A is
added to the pointing register to form the address in ROM where the desired data is to be found.
The data is then fetched from the ROM address so formed and placed in the A register. The original
data in A is lost, and the addressed data takes its place.
As shown in the following table, the letter C is added to the MOV mnemonic to highlight the use
of the opcodes for moving data from the source address in the Code ROM to the A register in the
8051:

Note that the DPTR and the PC are not changed; the A register contains the ROM byte found at
the address formed.
The following table shows examples of code ROM moves using register and indirect addressing
modes:
PUSH and POP Opcodes
The PUSH and POP opcodes specify the direct address of the data. The data moves between an
area of internal RAM, known as the stack, and the specified direct address. The stack pointer
special-function register (SP) contains the address in RAw~here data from the source address will
be PUSHed, or where data to be POPed to the destination address is found. The SP register actually
is used in the indirect addressing mode but is nor named in the mnemonic. It is implied that the SP
holds the indirect address whenever PUSHing or POPing. Figure 3.3 shows the operation of the
stack pointer as data is PUSHed or POPed to the stack area in internal RAM.
A PUSH opcode copies data from the source address to the stack. SP is incremented by one before
the data is copied to the internal RAM location contained in SP so that the data is stored from low
addresses to high addresses in the internal RAM. The stack grows up in memory as it is PUSHed.
Excessive PUSHing can make the stack exceed 7Fh (the top of internal RAM), after which point
data is lost.
A POP opcode copies data from the stack to the destination address. SP is decremented by one
afler data is copied from the stack RAM address to the direct destination to ensure that data placed
on the stack is retrieved in the same order as it was stored.

The PUSH and POP opcodes behave as explained in the following table:
The SP register is set to 07h when the 8051 is reset, which is the same direct address in internal
RAM as register R7 in bank 0. The first PUSH opcode would write data to RO of bank I. The SP
should be initialized by the programmer to point to an internal RAM address above the highest
address likely to be used by the program.
The following table shows examples of PUSH and POP opcodes:

Data Exchanges
MOV, PUSH, and POP opcodes all involve copying the data found in the source address to the
destination address; the original data in the source is not changed. Exchange instructions actually
move data in two directions: from source to destination and from destination to source. All
addressing modes except immediate may be used in the XCH (exchange) opcodes:

Exchanges between A and any port location copy the data on the port pins to A, while the data in
A is copied to the port larch. Register A is used for so many instructions that the XCH opcode
provides a very convenient way to "save" the contents of A without the necessity of using a PUSH
opcode and then a POP opcode.
The following table shows examples of data moves using exchange opcodes:

Logical Operations
lntroduction
One application area the 8051 is designed to fill is that of machine control. A large part of machine
control concerns sensing the on-off states of external switches, making decisions based on the
switch states, and then turning external circuits on or off.
Single point sensing and control implies a need for byre and bit opcodes that operate on data using
Boolean operators. All 8051 RAM areas, both data and SFRs, may be manipulated using byte
opccdes. Many of the SFRs, and a unique internal RAM area that is bit addressable, may be
operated upon at the individual bit level. Bit operators are notably efficient when speed of response
is needed. Bit operators yield compact program code that enhances program execution speed.
The two data levels, byte or bit, at which the Boolean instructions operate are shown in the
following table
Byte-Level Logical Operations
The byte-level logical operations use all four addressing modes for the source of a data byte. The
A register or a direct address in internal RAM is the destination of the logical operation result.
Keep in mind that all such operations are done using each individual bit of the destination and
source bytes. These operations, called byre-level Boolean operations because the entire byte is
affected, are listed in the following table:
Note that no flags are affected unless !he direct RAM address is the PSW.
Many of these byte-level operations use a direct address, which can include the port SFR addresses,
as a destination. The normal source of data from a port is the port pins; the normal destination for
port data is the port latch. When the destination of a logical operation is the direct address of a
port, the latch register, not the pins, is used both as the source for the original data and then the
destination for the altered byte of data. Any port operation that must first read the source data,
logically operate on it, and then write it back to the source (now the destination) must use the larch.
Logical operations that use the port as a source, but nor as a destination, use the pins of the port as
the source of the data.
For example, the port 0 latch contains FW, but the pins are all driving transistor bases and are close
to ground level. The logical operation
ANL PO,#OFh
Which is designed to turn the upper nibble transistors off, reads FFh from the latch, ANDs it with
OFh to produce OFh as a result, and then writes it back to the latch to turn these transistors off.
Reading the pins produces the result OOh, turning all transistors off, in error. But, the operation
ANL A,P0
produces A = OOh by using the port 0 pin data, which is OOh. The following table shows byte-
level logical operation examples:

Note that instructions that can use the SFR port latches as destinations are ANL, ORL, and XRL.
Bit-Level Logical Operations
Certain internal RAM and SFRs can be addressed by their byte addresses or by the address of each
bit within a byte. Bit addressing is very convenient when you wish to alter a single bit of a byte,
in a control register for instance, without having to wonder what you need to do to avoid altering
some other crucial bit of the same byte. The assembler can also equate bit addresses to labels that
make the program more readable. For example, bit 4 of TCON can become TRO, a label for the
timer 0 run bit.
The ability to operate on individual bits creates the need for an area of RAM that contains data
addresses that hold a single bit. Internal RAM byte addresses 20h to 2Fh serve this need and are
both byte and bit addressable. The bit addresses are numbered from OOh to 7Fh to represent the
128d bit addresses (16d bytes X 8 bits) that exist from byte addresses 20h to 2Fh. Bit 0 of byre
address 20h is bit address OOh, and bit 7 of byte address 2Fh is bit address 7Fh. You must know
your bits from your bytes to take advantage of this RAM area.
Internal RAM Bit Addresses
The availability of individual bit addresses in internal RAM makes the use of the RAM very
efficient when storing bit information. Whole bytes do not have to be used up to store one or two
bits of data.
The correspondence between byte and bit addresses are shown in the following table:

Interpolation of this table shows, for example, the address of bit 3 of internal RAM byte address
2Ch is 63h. the bit address of bit 5 of RAM address 21h is ODh, and bit address 47h is bit 7 of
RAM byte address 28h.
SFR Bit Addresses
All SFRs may be addressed at the byte level by using the direct address assigned to it, but not all
of the SFRs are addressable at the bit level. The SFRs that are also bit addressable form the bit
address by using the five most significant bits of the direct address for that SFR, together with the
three least significant bits that identify the bit position from position 0 (LSR) to 7 (MSB).
The bit-addressable SFR and the corresponding bit addresses are as follows:
The patterns in this table show the direct addresses assigned to the SFR bytes all have bits 0-3
equal to zero so that the address of the byte is also the address of the LSB. For example, bit OE3h
is bit 3 of the A register. The carry flag, which is bit 7 of the PSW, is bit addressable as OD7h.
The assembler can also "understand" more descriptive mnemonics, such as P0.5 for bit 5 of port
0, which is more formally addressed as 85h.
Figure 4.1 shows all the bit-addressable SFRs and the function of each addressable bit.
Bit-level logical operation examples are shown in the following table:
Rotate and Swap Operations
The ability to mate data is useful for inspecting bits of a byte without using individual bit opcodes.
The A register can be rotated one bit position to the left or right with or without including the C
flag in the rotation. If the C flag is not included, then the rotation involves the eight bits of the A
register. If the C flag is included, then nine bits are involved in the rotation. Including the C flag
enables the programmer to construct rotate operations involving any number of bytes.
The SWAP instruction can be thought of as a rotation of nibbles in the A register. Figure 4.2
diagrams the rotate and swap operations. which are given in the following table:

Note that no flags, other than the carry flag in RRC and RLC, are affected. If the carry is used as
part of a rotate instruction, the state of the carry flag should be known before the rotate is done.
Arithmetic Operations

The 805 1 has four arithmetic flags: the carry (C), auxiliary carry (AC), overflow (OV), and parity
(P).
Instructions Affecting Flags
The C. AC, and OV flags are arithmetic flags. They are set to I or cleared to 0 automatically.
depending upon the outcomes of the following instructions. The following instruction set includes
all instructions that modify the flags and is not confined to arithmetic instructions:
One should remember, however, that the flags are all stored in the PSW. Any instruction that can
modify a bit or a byte in that register (MOV, SETB, XCH, etc.) changes the flags. This type of
change takes conscious effort on the part of the programmer.
A flag may be used for more than one type of result. For example, the C flag indicates a carry out
of the lower byte position during addition and indicates a borrow during subtraction.
The instruction that last affects a flag determines the use of that flag.
The parity flag is affected by every instruction executed. The P flag will be set to a 1 if the number
of 1's in the A register is odd and will be set to 0 if the number of 1's is even.
All 0's in A yield a 1's count of 0, which is considered to be even. Parity check is an elementary
error-checking method and is particularly valuable when checking data received via the serial port.

lncrementing and Decrementing


The simplest arithmetic operations involve adding or subtracting a binary 1 and a [Link]
simple operations become very powerful when coupled with the ability to repeat theoperation-that
is, to "INCrement" or "DECrement"-until a desired result is reached.'

Register, Direct, and Indirect addresses may be INCremented or DECremented. No math flags (C,
AC, OV) are affected.
The following table lists the increment and decrement mnemonics.

Note that increment and decrement instructions that operate on a port direct address alter the latch
for that port. The following table shows examples of increment and decrement arithmetic
operations:
Addition
All addition is done with the A register as the destination of the result. All addressing modes may
be used for the source: an immediate number, a register, a direct address, and an indirect address.
Some instructions include the carry flag as an additional source of a single bit that is included in
the operation at the least significant bit position.
The following table lists the addition mnemonics.

Unsigned and Signed Addition


The programmer may decide that the numbers used in the program are to be unsigned numbers-
that is, numbers that are 8-bit positive binary numbers ranging from OOh to FFh. Alternatively,
the programmer may need to use both positive and negative signed numbers.
Signed numbers use bit 7 as a sign bit in the most significant byte (MSB) of the group of bytes
chosen by the programmer to represent the largest number to be needed by the program. Bits 0 to
6 of the MSB, and any other bytes, express the magnitude of the number.
Signed numbers use a I in bit position 7 of the MSB as a negative sign and a 0 as a positive sign.
Further, all negative numbers are not in true form, but are in 2's complement form. When doing
signed arithmetic, the programmer must know how large the largest number is to be-that is, how
many bytes are needed for each number.
In signed form, a single byte number may range in size from 10000000b. which is - 12Rd to 01 11
11 1 I b, which is + 127d. The number OOOOOOOOb is OOOd and has a positive sign, so there
are 128d negative numbers and 128d positive numbers. The C and OV flags have been included
in the 8051 to enable the programmer to use either numbering scheme.

Adding or subtracting unsigned numbers may generate a carry flag when the sum exceeds FFh or
a borrow flag when the minuend is less than the subtrahend. The OV flag is not used for unsigned
addition and subtraction. Adding or subtracting signed numbers can lead to carries and borrows in
a similar manner, and to overflow conditions due to the actions of the sign bits.
Subtraction
Subtraction can be done by taking the 2's complement of the number to be subtracted, the
subtrahend, and adding it to another number, the minuend. The 8051, however, has commands to
perform direct subtraction of two signed or unsigned numbers. Register A is the destination address
for subtraction. All four addressing modes may be used for source addresses. The commands treat
the carry flag as a borrow and always subtract the carry flag as part of the operation.
The following table lists the subtract mnemonics.

Note that the C flag is set if a borrow is needed into bit 7 and reset otherwise. The AC flag
is set if a borrow is needed into bit 3 and reset otherwise. The OV flag is set if there is a borrow
into hit 7 and not bit 6 or if there is a borrow into bit 6 and not bit 7. As in the case for addition,
the OV Flag is the XOR of the borrows into bit positions 7 and 6.
Unsigned and Signed Subtraction
Again, depending on what is needed, the programmer may choose to use bytes as signed or
unsigned numbers. The carry flag is now thought of as a borrow flag to account for situations when
a larger number is subtracted from a smaller number. The OV flag indicates results that must be
adjusted whenever two numbers of unlike signs are subtracted the result exceeds the planned
signed magnitudes.
Unsigned Subtraction
Because the C flag is always subtracted from A along with the source byte, it must be set to 0 if
the programmer does not want the flag included in the subtraction. If a multi-byte subtraction is
done, the C flag is cleared for the first byte and then included in subsequent higher byte operations.
Multiplication and Division
The 8051 has the capability to perform 8-bit integer multiplication and division using the A and B
registers. Register B is used solely for these operations and has no other use except as a location
in the SFR space of RAM that could be used to hold data. The A register holds one byte of data
before a multiply or divide operation, and one of the result bytes after a multiply or divide
operation.
Multiplication and division treat the numbers in registers A and B as unsigned. The programmer
must devise ways to handle signed numbers.
Multiplication
Multiplication operations use registers A and B as both source and destination addresses for the
operation. The unsigned number in register A is multiplied by the unsigned number in register B,
as indicated in the following table:

Division
Division operations use registers A and B as both source and destination addresses for the
operation. The unsigned number in register A is divided by the unsigned number in register B, as
indicated in the following table:
Decimal Arithmetic
Most 8051 applications involve adding intelligence to machines where the hexadecimalnumbering
system works naturally. There are instances, however, when the application involves interacting
with humans, who insist on using the decimal number system. In such cases, it may be more
convenient for the programmer to use the decimal number system to represent all numbers in the
program.
Four bits are required to represent the decimal numbers from 0 to 9 (0000 to 1001) and the numbers
are often called Binary coded decimal (BCD) numbers. Two of these BCD numbers can then be
packed into a single byte of data.
The 8051 does all arithmetic operations in pure binary. When BCD numbers are being used the
result will often be a non-BCD number, as shown in the following example:
Jump and Call Opcodes
The jumps and calls are decision codes that alter the flow of the program by examining the results
of the action codes and changing the contents of the program counter. A jump permanently changes
the contents of the program counter if certain program conditions exist. A call temporarily changes
the program counter to allow another part of the program to run. These decision codes make it
possible for the programmer to let the program adapt itself, as it runs, to the conditions that exist
at the time.
using the following decision opcodes:
Jump on bit conditions
Compare bytes and jump if not equal
Decrement byte and jump if zero
Jump unconditionally
Call a subroutine
Return from a subroutine
Jumps and calls may also be generically referred to as "branches," which emphasizes that two
divergent paths are made possible by this type of instruction.
The Jump and Call Program Range
A jump or call instruction can replace the contents of the program counter with a new program
address number that causes program execution to begin at the code located at the new address. The
difference, in bytes, of this new address from the address in the program
where the jump or call is located is called the range of the jump or call. For example, if a jump
instruction is located at program address 0100h, and the jump causes the program counter to
become 0120h. then the range of the jump is 20h bytes.
Jump or call instructions may have one of three ranges: a relative range of + 127d. - 128d bytes
from the instruction following the jump or call instruction; an absolute range on the same 2K byte
page as the instruction following the jump or call; or a long range of any address from OOOOh to
FFFFh, anywhere in program memory. Figure 6.1 shows the relative range of all the jump
instructions.

Jumps that replace the program counter contents with a new address that is greater than the address
of the instruction following the jump by 127d or less than the address of the instruction following
the jump by 128d are called relative jumps. They are so named because the address that is placed
in the program counter is relative to the address where the jump occurs. If the absolute address of
the jump instruction changes, then the jump address changes also but remains the same distance
away from the jump instruction. The address following the jump is used to calculate the relative
jump because of the action of the PC. The PC is incremented to point to the next instruction before
the current instruction is executed. Thus. the PC is set to the following address before the jump
instruction is executed, or in the vernacular "before the jump is taken."
Relative jumping has two advantages. First, only one byte of data need be specified, either in
positive format for jumps ahead in the program or in 2's complement negative format for jumps
behind. The jump address displacement byte can then be added to the PC to get the absolute
address. Specifying only one byte saves program bytes and speeds up program execution. Second,
the program that is written using relative jumps can be located anywhere in the program address
space without re-assembling the code to generate absolute addresses.
The disadvantage of using relative addressing is the requirement that all addresses jumped be
within a range of + 127d. - 128d bytes of the jump instruction. This range is not a serious problem.
Most jumps form program loops over short code ranges that are within the relative address
capability. Jumps are the only branch instructions that can use the relative range.
If jumps beyond the relative range are needed, then a relative jump can be done to another relative
jump until the desired address is reached.
Short Absolute Range
Absolute range makes use of the concept of dividing memory into logical divisions called "pages."
Program memory may be regarded as one continuous stretch of addresses from OOOOh to FFFFh.
Or, it may be divided into a series of pages of any convenient binary size. such as 256 bytes. 2K
bytes, 4K bytes. and so on.
The 8051 program memory is arranged as 2K byte pages, giving a total of 32d (20h) pages. The
hexadecimal address of each page is shown in the following table:

Relative Range
Jumps that replace the program counter contents with a new address that is greater than the address
of the instruction following the jump by 127d or less than the address of the instruction following
the jump by 128d are called relative jumps. They are so named because the address that is placed
in the program counter is relative to the address where the jump occurs. If the absolute address of
the jump instruction changes, then the jump address changes also but remains the same distance
away from the jump instruction. The address following the jump is used to calculate the relative
jump because of the action of the PC. The PC is incremented to point to the next instruction before
the current instruction is executed. Thus. the PC is set to the following address before the jump
instruction is executed, or in the vernacular "before the jump is taken."
Relative jumping has two advantages. First, only one byte of data need be specified, either in
positive format for jumps ahead in the program or in 2's complement negative format for jumps
behind. The jump address displacement byte can then be added to the PC to get the absolute
address. Specifying only one byte saves program bytes and speeds up program execution. Second,
the program that is written using relative jumps can be located anywhere in the program address
space without re-assembling the code to generate absolute addresses.
The disadvantage of using relative addressing is the requirement that all addresses jumped be
within a range of + 127d. - 128d bytes of the jump instruction. This range is not a serious problem.
Most jumps form program loops over short code ranges that are within the relative address
capability. Jumps are the only branch instructions that can use the relative range.
If jumps beyond the relative range are needed, then a relative jump can be done to another relative
jump until the desired address is reached.
Short Absolute Range
Absolute range makes use of the concept of dividing memory into logical divisions called "pages."
Program memory may be regarded as one continuous stretch of addresses from OOOOh to FFFFh.
Or, it may be divided into a series of pages of any convenient binary size. such as 256 bytes. 2K
bytes, 4K bytes. and so on.
The 8051 program memory is arranged as 2K byte pages, giving a total of 32d (20h) pages. The
hexadecimal address of each page is shown in the following table:

Inspection of the page numbers shows that the upper five bits of the program counter hold the page
number, and the lower eleven bits hold the address within each page. An absolute address is formed
by taking the page number of the instruction following the branch and attaching the absolute page
range address of eleven bits to it to form the 16-bit address.
Branches on page boundaries occur when the jump or call instruction finishes at X7FFh or XFFFh.
The next instruction starts at X800h or X000h. which places the jump or call address on the same
page as the next instruction after the jump or call. The page change presents no problem when
branching ahead but could be troublesome if the branch is backwards in the program. The
assembler should flag such problems as errors, so adjustments can be made by the programmer to
use a different type of range.
Absolute range addressing has the same advantages as relative addressing; fewer bytes are needed
and the code is relocatable as long as the relocated code begins at the start of a page. Absolute
addressing has the advantage of allowing jumps or calls over longer programming distances than
does relative addressing.
Long Absolute Range
Addresses that can access the entire program space from OOOOh to FFFFh use long range
addressing. Long-range addresses require more bytes of code to specify and are relocatable only
at the beginning of 64K byte pages. Since we are limited to a nominal ROMaddress range of 64K
bytes, the program must be re-assembled every time a long-range address changes and these
branches are not generally relocatable.
Long-range addressing has the advantage of using the entire program address space available to
the 8051. It is most likely to be used in large programs.
Jumps
The ability of a program to respond quickly to changes in conditions depends largely upon the
number and types of jump instructions available to the programmer. The 8051 has a rich set of
jumps that can operate at the bit and byte levels. These jump opcodes are one reason the 8051 is
such a powerful microcontroller.
Jumps operate by testing for conditions that are specified in the jump mnemonic. If the condition
is true, then the jump is taken-that is, the program counter is altered to the address that is part of
the jump instruction. If the condition is false, then the instruction immediately following the jump
instruction is executed because the program counter is not altered. Keep in mind that the condition
of true does not mean a binary 1 and that false does not mean binary 0. The condition specified by
the mnemonic is either true or false.
Bit Jumps
Bit jumps all operate according to the status of the carry flag in the PSW or the status of any bit-
addressable location. All bit jumps are relative to the program counter.
Jump instructions that test for bit conditions are shown in the following table:

Note that no flags are affected unless the bit in JBC is a flag bit in the PSW. When the bit used in
a JBC instruction is a port bit, the SFR latch for that port is read, tested, and altered.
Byte Jumps
Byte jumps-jump instructions that test bytes of data-behave as bit jumps. If the condition that is
tested is true, the jump is taken; if the condition is false, the instruction after the jump is executed.
All byte jumps are relative to the program counter. The following table lists examples of byte
jumps:
Unconditional Jumps
Unconditional jumps do not test any bit or byte to determine whether the jump should be taken.
The jump is always taken. All jump ranges are found in this group of jumps, and these are the only
jumps that can jump to any location in memory.
The following table shows examples of unconditional jumps:

Calls and Subroutines


A program that does not have to deal unexpectedly with the world outside of the microcontroller
could be written using jumps to alter program flow as external conditions require. This sort of
program can determine external conditions by moving data from the port pins to a location and
jumping on the conditions of the port pin data. This technique is called "polling" and requires that
the program does not have to respond to external conditions quickly. (Quickly means in
microseconds; slowly means in milliseconds.)
Another method of changing program execution is using "interrupt" signals on certain external
pins or internal registers to automatically cause a branch to a smaller program that deals with the
specific situation. When the event that caused the interruption has been dealt with, the program
resumes at the point in the program where the interruption took place. Interrupt action can also be
generated using software instructions named calls.
Call instructions may be included explicitly in the program as mnemonics or implicitly included
using hardware interrupts. In both cases, the call is used to execute a smaller, stand-alone program,
which is termed a routine or, more often, a subroutine.
Subroutines
A subroutine is a program that may be used many times in the execution of a larger program.
The subroutine could be written into the body of the main program everywhere it is needed,
resulting in the fastest possible code execution. Using a subroutine in this manner has several
serious drawbacks.
Common practice when writing a large program is to divide the total task among many
programmers in order to speed completion. The entire program can be broken into smaller parts
and each programmer given a part to write and debug. The main program can then call each of the
parts, or subroutines, that have been developed and tested by each
individual of the team.
Even if the program is written by one individual, it is more efficient to write an oft-used routine
once and then call it many times as needed. Also, when writing a program, the programmer does
the main part first. Calls to subroutines, which will be written later, enable the larger task to be
defined before the programmer becomes bogged down in the details of the application.
Finally, it is quite common to buy "libraries" of common subroutines that can be called by a main
program. Again, buying libraries leads to faster program development.
Calls and the Stack
A call, whether hardware or software initiated, causes a jump to the address where the called
subroutine is located. At the end of the subroutine the program resumes operation at the opcode
address immediately following the call. As calls can be located anywhere in the program address
space and used many times, there must be an automatic means of storing the address of the
instruction following the call so that program execution can continue after the subroutine has
executed.
The stack area of internal RAM is used to automatically store the address, called the return address,
of the instruction found immediately after the call. The stack pointer register holds the address of
the last space used on the stack. It stores the return address above this space, adjusting itself upward
as the return address is stored. The terms "stack" and "stack pointer" are often used interchangeably
to designate the mop of the stack area in RAM that is pointed to by the stack pointer.
Figure 6.2 diagrams the following sequence of events:
1. A call opcode occurs in the program software, or an interrupt is generated in the
hardware circuitry.
2. The return address of the next instruction after the call instruction or interrupt is
found in the program counter.
3. The return address bytes are pushed on the stack, low byte jrsr
4. The stack pointer is incremented for each push on the stack
5. The subroutine address is placed in the program counter.
6. The subroutine is executed.
7. A RET (return) opcode is encountered at the end of the subroutine.
8. Two pop operations restore the return address to the PC from the stack area in internal RAM.
9. The stack pointer is decremented for each address byte pop.
Calls and Returns
Calls use short- or long-range addressing; returns have no addressing mode specified but are
always long range. The following table shows examples of call opcodes:

Interrupts and Returns


As mentioned previously, an interrupt is a hardware-generated call. Just as a call opcode can be
located within a program to automatically access a subroutine, certain pins on the 805 1 can cause
a call when external electrical signals on them go to a low state. Internal operations of the timers
and the serial port can also cause an interrupt call to take place.
The subroutines called by an interrupt are located at fixed hardware addresses. The following table
shows the interrupt subroutine addresses.
When an interrupt call takes place, hardware interrupt disable flip-flops are set to prevent another
interrupt of the same priority level from taking place until an interrupt return instruction has been
executed in the interrupt subroutine. The action of the interrupt routine is shown in the table below.

Note that the only difference between the RET and RETl instructions is the enabling of the
interrupt logic when RETI is used. RET is used at the ends of subroutines called by an opcnde.
RETl is used by subroutines called by an interrupt.

You might also like