8085 Microprocessor 1
8085 Microprocessor 1
3.03 MHz Clock Speed: Operates at a maximum clock frequency of 3.03 MHz.
16-bit Address Bus: It has a 16-bit address bus, allowing it to address up to 2^16
= 65,536 bytes (64 KB) of memory.
Multiplexed Address/Data Bus: The lower 8 bits of the address bus (A0-A7) are
multiplexed with the data bus (AD0-AD7) to reduce the number of pins.
Flag Register: An 8-bit register that indicates the status of various operations
(Sign, Zero, Auxiliary Carry, Parity, Carry flags).
Program Counter (PC): A 16-bit register that stores the memory address of the
next instruction to be fetched.
Stack Pointer (SP): A 16-bit register that points to the top of the stack in
memory.
Interrupts: Supports five hardware interrupts (TRAP, RST 7.5, RST 6.5, RST 5.5,
INTR) and one software interrupt (RST n).
Serial I/O Ports: Includes two serial I/O pins (SID and SOD) for serial data
communication.
Control and Status Signals: Provides various control and status signals for
communication with peripheral devices and memory.
Pin Description
The 8085 microprocessor is a 40-pin IC (Integrated Circuit) package. Each pin has a
specific function for power supply, clock signals, address/data bus, control signals,
interrupt signals, and serial I/O signals. The pins can be broadly categorized as follows:
Address Bus (A8-A15): These are the higher-order 8 bits of the address bus. They
are unidirectional and are used to send the most significant 8 bits of the memory
address or I/O address.
Interrupt Signals:
TRAP: Non-maskable interrupt, highest priority.
RST 7.5, RST 6.5, RST 5.5: Maskable interrupts with decreasing priority.
X1, X2: Crystal or RC network connection for the internal clock generator.
Internal Architecture
Registers: The 8085 has several registers for storing data and addresses:
Accumulator (A): An 8-bit register used for most arithmetic and logical
operations. The result of an operation is usually stored in the accumulator.
Stack Pointer (SP): A 16-bit register that holds the address of the top of the
stack in memory. The stack is used for temporary storage of data and return
addresses during subroutine calls and interrupts.
Program Counter (PC): A 16-bit register that stores the memory address of
the next instruction to be fetched from memory. It is automatically
incremented after each instruction fetch.
Timing and Control Unit: Generates the necessary timing and control signals for
all internal and external operations of the microprocessor. It controls the flow of
data between the CPU and peripheral devices.
Interrupt Control: Manages the interrupt requests from external devices and
internal events, prioritizing them and directing the microprocessor to the
appropriate interrupt service routine.
Serial I/O Control: Handles serial data communication through the SID and SOD
pins.
Address Buffer and Data/Address Buffer: These buffers are used to drive the
address and data buses, respectively, providing the necessary current to external
devices.
Here is a diagram illustrating the internal architecture of the 8085 Microprocessor:
Instruction Formats
8085 instructions can be classified into three formats based on their byte size:
Examples:
MOV A, B (Move the content of register B to register A)
Examples:
MVI A, 32H (Move immediate data 32H to Accumulator)
Examples:
LXI H, 2050H (Load immediate 16-bit data 2050H into HL register
pair)
Data Formats
The 8085 microprocessor primarily handles 8-bit data. Data can be represented in
various formats:
Binary: Data is stored and processed in binary (0s and 1s). For example, an 8-bit
data can range from 00000000B to 11111111B.
Decimal: While not directly used by the microprocessor for internal operations,
decimal values are used by programmers for input and output, which are then
converted to binary or hexadecimal.
When dealing with 16-bit operations (e.g., addresses, or data in register pairs like BC,
DE, HL, SP, PC), the 8085 handles them as two 8-bit bytes. The convention is typically
little-endian, where the lower-order byte is stored at the lower memory address and
the higher-order byte at the higher memory address.
Addressing Modes
Addressing modes refer to the different ways in which the microprocessor can specify
the operand (data or memory address) for an instruction. The 8085 microprocessor
supports five addressing modes:
3. Direct Addressing Mode: In this mode, the instruction contains the 16-bit
memory address of the operand. The microprocessor directly accesses the
specified memory location to fetch or store data.
Instruction Set
1. Data Transfer Group: These instructions are used to move data between
registers, memory, and I/O devices. They do not affect the contents of the source
location.
Examples: MOV , MVI , LDA , STA , LHLD , SHLD , XCHG , PUSH , POP , IN ,
OUT .
2. Arithmetic Group: These instructions perform arithmetic operations like
addition, subtraction, increment, and decrement on 8-bit data. They affect the
flag register.
3. Logical Group: These instructions perform logical operations like AND, OR, XOR,
compare, and rotate. They also affect the flag register.
Examples: ANA , ORA , XRA , CMP , CPI , RLC , RRC , RAL , RAR .
4. Branch Control Group: These instructions alter the normal sequential flow of
program execution. They include jumps, calls, returns, and restarts.
5. Stack, I/O, and Machine Control Group: These instructions deal with stack
operations, input/output operations, and controlling the microprocessor's state.
Here are some common 8085 assembly programming examples for basic data transfer
operations:
This instruction loads the content of a specified 16-bit memory address into the
Accumulator.
This instruction stores the content of the Accumulator into a specified 16-bit memory
address.
5. Loading 16-bit data to a register pair (LXI - Load Register Pair Immediate)
This instruction loads a 16-bit immediate data into a specified register pair.
LXI H, 3000H ; Load immediate value 3000H into HL register pair (H=30H,
L=00H)
LXI B, 1234H ; Load immediate value 1234H into BC register pair (B=12H,
C=34H)
6. Moving data from memory to a register using register indirect addressing (MOV
R, M)
This instruction copies the content of the memory location pointed to by the HL
register pair into a specified register.
This instruction copies the content of a specified register into the memory location
pointed to by the HL register pair.
This instruction exchanges the 16-bit contents of the HL register pair with the DE
register pair.
These examples demonstrate the basic data transfer capabilities of the 8085
microprocessor, which are essential for moving data around within the system to
facilitate various operations.
Arithmetic and logical operations are core functions of any microprocessor, enabling it
to perform calculations and manipulate data at the bit level. The 8085 provides a set of
instructions for these operations, primarily using the Accumulator as one of the
operands and often storing the result back into the Accumulator. These operations
also affect the flag register, indicating the status of the result.
Here are some common 8085 assembly programming examples for basic arithmetic
and logical operations:
Arithmetic Operations
ADD R : Adds the content of register R to the Accumulator. The result is stored in
the Accumulator.
ADI data : Adds the 8-bit immediate data to the Accumulator. The result is
stored in the Accumulator.
2. Addition with Carry (ADC - Add Register with Carry to Accumulator, ACI - Add
Immediate with Carry to Accumulator)
ADC R : Adds the content of register R and the Carry flag (CY) to the Accumulator.
The result is stored in the Accumulator.
ACI data : Adds the 8-bit immediate data and the Carry flag (CY) to the
Accumulator. The result is stored in the Accumulator.
SUB R : Subtracts the content of register R from the Accumulator. The result is
stored in the Accumulator.
SUI data : Subtracts the 8-bit immediate data from the Accumulator. The result
is stored in the Accumulator.
SBB R : Subtracts the content of register R and the Borrow (Carry) flag (CY) from
the Accumulator. The result is stored in the Accumulator.
SBI data : Subtracts the 8-bit immediate data and the Borrow (Carry) flag (CY)
from the Accumulator. The result is stored in the Accumulator.
Logical Operations
1. Logical AND (ANA - AND Register with Accumulator, ANI - AND Immediate with
Accumulator)
ANA R : Performs a bitwise AND operation between the content of register R and
the Accumulator. The result is stored in the Accumulator.
ANI data : Performs a bitwise AND operation between the 8-bit immediate data
and the Accumulator. The result is stored in the Accumulator.
MVI A, 0F0H ; Accumulator = 11110000B
MVI B, 00FH ; Register B = 00001111B
ANA B ; A = A AND B (11110000B AND 00001111B = 00000000B = 00H).
Accumulator now holds 00H.
ORI data : Performs a bitwise OR operation between the 8-bit immediate data
and the Accumulator. The result is stored in the Accumulator.
3. Logical XOR (XRA - XOR Register with Accumulator, XRI - XOR Immediate with
Accumulator)
XRA R : Performs a bitwise XOR operation between the content of register R and
the Accumulator. The result is stored in the Accumulator.
XRI data : Performs a bitwise XOR operation between the 8-bit immediate data
and the Accumulator. The result is stored in the Accumulator.
CPI data : Compares the 8-bit immediate data with the Accumulator. Flags are
set based on the comparison.
5. Rotate (RLC - Rotate Accumulator Left, RRC - Rotate Accumulator Right, RAL -
Rotate Accumulator Left through Carry, RAR - Rotate Accumulator Right through
Carry)
These instructions shift the bits of the Accumulator to the left or right, often involving
the Carry flag.
RLC : Rotates the Accumulator left by one bit. The most significant bit (MSB)
moves to the Carry flag and also to the least significant bit (LSB).
RRC : Rotates the Accumulator right by one bit. The least significant bit (LSB)
moves to the Carry flag and also to the most significant bit (MSB).
RAL : Rotates the Accumulator left by one bit through the Carry flag. The MSB
moves to the Carry flag, and the Carry flag's old value moves to the LSB.
RAR : Rotates the Accumulator right by one bit through the Carry flag. The LSB
moves to the Carry flag, and the Carry flag's old value moves to the MSB.
Conditional statements and loops are essential programming constructs that allow a
program to make decisions and repeat sequences of instructions, respectively. In 8085
assembly language, these are primarily implemented using conditional and
unconditional jump instructions, which alter the flow of program execution based on
the status of the flag register.
JZ (Jump if Zero): Jumps if the Zero flag (Z) is set (Z=1), meaning the previous
operation resulted in zero.
JNZ (Jump if Not Zero): Jumps if the Zero flag (Z) is reset (Z=0), meaning the
previous operation resulted in a non-zero value.
JC (Jump if Carry): Jumps if the Carry flag (CY) is set (CY=1), meaning the
previous operation generated a carry or borrow.
JNC (Jump if No Carry): Jumps if the Carry flag (CY) is reset (CY=0), meaning the
previous operation did not generate a carry or borrow.
JP (Jump if Plus): Jumps if the Sign flag (S) is reset (S=0), meaning the result is
positive.
JM (Jump if Minus): Jumps if the Sign flag (S) is set (S=1), meaning the result is
negative.
JPE (Jump if Parity Even): Jumps if the Parity flag (P) is set (P=1), meaning the
result has an even number of set bits.
JPO (Jump if Parity Odd): Jumps if the Parity flag (P) is reset (P=0), meaning the
result has an odd number of set bits.
Example: Check if a number is zero
Loops
Loops are used to repeat a block of instructions a certain number of times or until a
specific condition is met. In 8085 assembly, loops are typically implemented using a
counter and conditional jump instructions.
This type of loop uses a register as a counter, which is decremented in each iteration.
The loop continues until the counter reaches zero.
LOOP_START:
ADD C ; Add current value of C to Accumulator
DCR C ; Decrement counter
JNZ LOOP_START ; Jump back to LOOP_START if C is not zero
Explanation:
The MVI C, 05H instruction initializes the counter register C with the value 5.
This means the loop will execute 5 times. (Note: This example sums 5, 4, 3, 2, 1
into A, not 1 to 5 directly. For summing 1 to N, a different approach would be
needed, perhaps adding 1 in each iteration and incrementing a separate
counter.)
MVI A, 00H initializes the Accumulator to 0, where the sum will be stored.
Inside the LOOP_START , ADD C adds the current value of C to the Accumulator.
JNZ LOOP_START checks the Zero flag. If C is not zero, the program jumps back to
LOOP_START to continue the loop. If C becomes zero, the loop terminates.
Loops can also be used to create time delays in programs. This is often done by
running a loop for a specific number of iterations, where each iteration takes a known
amount of time.
DELAY_LOOP:
MVI B, FFH ; Load B with a large value (inner loop counter)
INNER_LOOP:
DCR B ; Decrement B
JNZ INNER_LOOP ; Loop until B becomes zero
Explanation:
This example shows a nested loop structure. The INNER_LOOP decrements
register B until it becomes zero. This creates a short delay.
The total delay depends on the initial values loaded into B and C, and the clock
frequency of the 8085.
These examples illustrate how conditional jumps and loops are fundamental for
controlling program flow and implementing iterative processes in 8085 assembly
language.
Array and table processing are common tasks in programming, involving operations
on sequences of data stored in contiguous memory locations. In 8085 assembly
language, these tasks are typically handled using register pairs (especially HL) as
memory pointers, combined with looping and indexing techniques.
Array Processing
Arrays are collections of data elements of the same type, stored in consecutive
memory locations. Processing an array often involves iterating through its elements to
perform operations like summation, searching, sorting, or finding the largest/smallest
element.
This program adds N 8-bit numbers stored in a memory array and stores the sum in a
designated memory location. Assume the number of elements (N) is at memory
location 2000H , and the array starts from 2001H .
ORG 2000H ; Origin of the program
START:
LXI H, 2001H ; Load HL with the starting address of the array
MOV C, M ; Move the number of elements (N) from 2000H to Register C
(counter)
INR L ; Increment L to point to the first element of the array
(2001H)
MVI A, 00H ; Initialize Accumulator (sum) to 00H
MVI B, 00H ; Initialize Register B (carry) to 00H
LOOP_SUM:
ADD M ; Add the content of memory pointed by HL to Accumulator
JNC NEXT_ELEMENT ; If no carry, jump to next element
INR B ; If carry, increment Register B (carry counter)
NEXT_ELEMENT:
INR L ; Increment L to point to the next element
DCR C ; Decrement element counter
JNZ LOOP_SUM ; If C is not zero, continue loop
Explanation:
LXI H, 2001H sets the HL register pair to point to the first element of the array.
MOV C, M loads the count of elements (N) into register C, which acts as a loop
counter.
MVI A, 00H and MVI B, 00H initialize the sum (Accumulator) and carry
(Register B) to zero.
JNZ LOOP_SUM continues the loop until all elements are processed.
This program searches for a specific 8-bit number in an array. If found, it sets a flag;
otherwise, it clears the flag. Assume the number to search is at 2000H , array size at
2001H , and array starts from 2002H . Result flag (00H for not found, FFH for found) at
2050H .
ORG 2000H
START:
LDA 2000H ; Load the number to search into Accumulator
MOV B, A ; Copy it to Register B
LXI H, 2001H ; Load HL with address of array size
MOV C, M ; Move array size to Register C (counter)
INR L ; Point HL to the first element of the array (2002H)
SEARCH_LOOP:
MOV A, M ; Load current array element into Accumulator
CMP B ; Compare with the number to search (in Register B)
JZ FOUND ; If equal, jump to FOUND
INR L ; Increment HL to next element
DCR C ; Decrement counter
JNZ SEARCH_LOOP; If C is not zero, continue search
NOT_FOUND:
MVI A, 00H ; Set flag to 00H (Not Found)
STA 2050H ; Store flag
JMP END_PROG ; Jump to end
FOUND:
MVI A, FFH ; Set flag to FFH (Found)
STA 2050H ; Store flag
END_PROG:
HLT ; Halt the processor
Table Processing
This program takes a BCD digit (0-9) and finds its corresponding 7-segment display
code from a lookup table. Assume the BCD digit is at 2000H , and the 7-segment codes
table starts at 2100H . The result will be stored at 2050H .
ORG 2000H
SEVEN_SEG_TABLE:
DB 3FH ; Code for 0
DB 06H ; Code for 1
DB 5BH ; Code for 2
DB 4FH ; Code for 3
DB 66H ; Code for 4
DB 6DH ; Code for 5
DB 7DH ; Code for 6
DB 07H ; Code for 7
DB 7FH ; Code for 8
DB 6FH ; Code for 9
START:
LDA 2000H ; Load BCD digit into Accumulator (e.g., 05H)
MOV L, A ; Move BCD digit to L register (acts as offset)
MVI H, 21H ; Set H register to the high byte of table start address
(2100H)
; Now HL points to 2100H + offset (e.g., 2105H for BCD 05H)
MOV A, M ; Load the 7-segment code from the table into Accumulator
STA 2050H ; Store the 7-segment code at 2050H
Explanation:
The SEVEN_SEG_TABLE defines the 7-segment codes for digits 0-9. DB (Define
Byte) is an assembler directive to store byte data.
LDA 2000H fetches the BCD digit (e.g., 05H) into the Accumulator.
MOV L, A copies this digit to the L register. Since the table starts at 2100H , and
each entry is 1 byte, the BCD digit can directly serve as an offset from the table's
starting address.
MVI H, 21H sets the H register to the high byte of the table's base address.
Together, HL now forms the effective address of the desired 7-segment code (e.g.,
2100H + 05H = 2105H ).
MOV A, M fetches the byte from the memory location pointed to by HL (which is
the 7-segment code) into the Accumulator.
STA 2050H stores the fetched 7-segment code to the result location.
These examples illustrate how arrays and tables can be effectively processed in 8085
assembly language using indexing and direct memory access techniques.
2.5.5 8-bit and 16-bit multiplication and division operations
The 8085 microprocessor does not have dedicated hardware instructions for
multiplication and division. These operations must be implemented using software
routines, typically by repeatedly applying addition/subtraction and bit shifting
operations. This makes multiplication and division more complex and time-consuming
compared to basic arithmetic operations.
8-bit Multiplication
Assume the multiplicand is in memory location 2000H and the multiplier is in 2001H .
The 16-bit result (product) will be stored in 2050H (lower byte) and 2051H (higher
byte).
ORG 2000H
START:
LDA 2000H ; Load multiplicand into Accumulator
MOV B, A ; Move multiplicand to Register B
LDA 2001H ; Load multiplier into Accumulator
MOV C, A ; Move multiplier to Register C (counter)
LOOP_MUL:
ADD B ; Add multiplicand (B) to Accumulator (A)
JNC NO_CARRY ; If no carry, jump to NO_CARRY
INR D ; If carry, increment Register D (higher byte of product)
NO_CARRY:
DCR C ; Decrement multiplier (counter)
JNZ LOOP_MUL ; If C is not zero, continue loop
Explanation:
The program initializes the Accumulator (A) and Register D to 0. A will hold the
lower 8 bits of the product, and D will hold the higher 8 bits (carry).
The LOOP_MUL repeatedly adds the multiplicand (stored in B) to the Accumulator.
The number of additions is controlled by the multiplier (stored in C).
After the loop completes, the 16-bit product is formed by the contents of D
(higher byte) and A (lower byte).
16-bit Multiplication
Let the two 16-bit numbers be HL (H: high byte, L: low byte) and DE (D: high byte, E:
low byte).
5. Align and add the partial products, considering their positional values (e.g., L*D
result needs to be shifted left by 8 bits before adding).
This process involves many ADD , ADC , RLC / RRC (for shifting), and DAD (Double Add)
instructions, along with careful management of intermediate results in register pairs
and memory.
8-bit Division
Assume the dividend is in memory location 2000H and the divisor is in 2001H . The
quotient will be stored in 2050H and the remainder in 2051H .
ORG 2000H
START:
LDA 2000H ; Load dividend into Accumulator
MOV B, A ; Move dividend to Register B
LDA 2001H ; Load divisor into Accumulator
MOV C, A ; Move divisor to Register C
CHECK_DIVISOR:
CMP C ; Compare dividend (B) with divisor (C)
JC END_DIV ; If B < C, division is complete (jump if carry)
LOOP_DIV:
SUB C ; Subtract divisor (C) from dividend (A)
INR A ; Increment quotient (Accumulator)
MOV B, A ; Update dividend in B
JMP CHECK_DIVISOR ; Check again
END_DIV:
MOV A, B ; Move remainder (from B) to Accumulator
STA 2051H ; Store remainder at 2051H
MOV A, D ; Move quotient (from D) to Accumulator (assuming D holds
quotient)
STA 2050H ; Store quotient at 2050H
Note: The above division example is a simplified conceptual one. A more robust
division algorithm would involve careful handling of the dividend and quotient
registers, and ensuring the correct remainder is left in the accumulator. A common
approach is to use the Accumulator for the current dividend, and a separate register
for the quotient, incrementing the quotient each time a subtraction is successful. The
loop continues until the dividend is less than the divisor. The final value in the
Accumulator is the remainder, and the count is the quotient.
16-bit Division
To divide a 16-bit number (HL) by an 8-bit number (C), one common method is to
repeatedly subtract the divisor from the higher byte of the dividend, then combine the
remainder with the lower byte and continue the process. This is analogous to manual
long division.
BCD (Binary Coded Decimal) represents each decimal digit with its 4-bit binary
equivalent. For example, decimal 23 is represented as 0010 0011 in BCD. To convert a
two-digit BCD number to its binary equivalent, you can multiply the higher BCD digit
by 10 (0AH in hex) and add the lower BCD digit.
Assume the two-digit BCD number is stored in memory location 2000H (e.g., 23H for
decimal 23). The binary result will be stored in 2050H .
ORG 2000H
START:
LDA 2000H ; Load BCD number (e.g., 23H) into Accumulator
MOV B, A ; Copy BCD number to Register B
MULTIPLY_LOOP:
ADD C ; Add higher BCD digit (C) to Accumulator
DCR E ; Decrement counter (E)
JNZ MULTIPLY_LOOP ; Loop 10 times
Explanation:
The program first separates the two BCD digits. The higher nibble (e.g., 2 from
23H) is isolated and rotated to become a single digit. The lower nibble (e.g., 3
from 23H) is also isolated.
The higher BCD digit is then multiplied by 10 using a repeated addition loop.
Finally, the lower BCD digit is added to the result of the multiplication to get the
final binary value.
Converting a binary number to BCD is generally more complex than the reverse. A
common method is the
Assume the 8-bit binary number is stored in memory location 2000H (e.g., 0FH for
decimal 15). The BCD result will be stored in 2050H (lower BCD digit) and 2051H
(higher BCD digit).
ORG 2000H
START:
LDA 2000H ; Load binary number into Accumulator (e.g., 0FH)
MOV B, A ; Copy binary number to Register B
LOOP_BCD:
MOV A, E ; Move lower BCD digit to Accumulator
ADD A ; Double (shift left) lower BCD digit
DAA ; Decimal Adjust Accumulator
MOV E, A ; Store back to lower BCD digit
NO_ADD_3:
DCR C ; Decrement bit counter
JNZ LOOP_BCD ; Loop until all 8 bits are processed
The provided example attempts to implement a variation of this, where ADD A and
DAA are used to handle the doubling and decimal adjustment. The RAL instruction
shifts the binary number and its MSB into the Carry flag, which is then used to adjust
the BCD digits. This process is repeated for each bit of the binary number.
Implementing a full and robust binary to BCD conversion, especially for larger binary
numbers (e.g., 16-bit), requires careful management of multiple BCD digits and precise
application of the double-dabble algorithm. Due to the complexity, such routines are
often implemented as subroutines.
Interrupt Pins
Interrupt Priorities
The 8085 microprocessor has a fixed priority scheme for its hardware interrupts. In
case multiple interrupts occur simultaneously, the one with the higher priority is
serviced first. The priority order from highest to lowest is:
TRAP > RST 7.5 > RST 6.5 > RST 5.5 > INTR
Types of Interrupts
Interrupts in the 8085 can be broadly classified into two main types:
Interrupt Instructions
Several instructions are used to control and manage interrupts in the 8085:
SIM (Set Interrupt Mask): This instruction is used to mask (disable) or unmask
(enable) individual RST 7.5, RST 6.5, and RST 5.5 interrupts. It also controls the
Serial Output Data (SOD) pin.
RIM (Read Interrupt Mask): This instruction reads the current status of the
interrupt masks and the pending interrupts into the Accumulator. It also reads
the Serial Input Data (SID) pin.
RST n (Restart): These are software interrupt instructions (RST 0 to RST 7). When
executed, they save the current PC on the stack and jump to a specific vector
address ( n * 8 ).
The general sequence of events when an interrupt occurs in the 8085 is as follows:
4. Save Program Counter: The current content of the Program Counter (PC), which
points to the next instruction to be executed, is automatically pushed onto the
stack. This ensures that the microprocessor can return to the main program after
servicing the interrupt.
For INTR, the RST or CALL instruction provided by the interrupting device
is fetched and executed, which then directs the PC to the ISR address.
6. Execute ISR: The microprocessor starts executing the Interrupt Service Routine
(ISR) located at the vector address. The ISR contains the code to handle the
specific event that caused the interrupt.
7. Return from Interrupt: The ISR typically ends with a RET (Return) instruction.
This instruction pops the previously saved PC value from the stack back into the
Program Counter.
This interrupt mechanism allows the 8085 to respond efficiently to external events
without constantly polling devices, thus improving system responsiveness and overall
performance.