You are on page 1of 34

UNIT II INTRODUCTION TO 8086 MICROPROCESSOR 2.

1 Introduction The Intel 8086 is a 16-bit microprocessor that is intended to be used as the CPU in a microcomputer. 16-bit indicates that the word length of the microprocessor. The 8086 microprocessor has a 16-bit data bus and hence its ALU and internal registers are able to process 16 bits of information at a time. To speed up the processing, 8086 divides the work to be done into two functional units namely Execution Unit (EU) and Bus Interface Unit (BIU). The BIU is responsible for the transfer of data and addresses on the buses for the EU. The EU instructs the BIU to fetch the instructions or data from the memory, decodes the instructions and executes instructions. The 8086 microprocessor produces the physical address by adding the effective address to the contents of any one of the four segment registers and this way of addressing the memory is called segment:offset notation. The effective address of the operands can be calculated in different ways and hence effective address calculation leads to different addressing modes. To program 8086 and to develop 8086 based systems it is necessary to study about the instruction set of 8086. Overall, this unit makes you to learn the architecture, memory addressing and instruction set of 8086 microprocessor. 2.2 Learning Objectives To study about the architecture of 8086 To study about the segment registers and memory addressing of 8086 To learn the various addressing modes supported by 8086 To study the various types of instructions provided by 8086 To study the pin diagram and the signals of various pins of 8086

2.3 8086 Architecture The architecture of 8086 includes Arithmetic Logic Unit (ALU), flags, general registers, instruction byte queue and segment registers. The 8086 CPU logic has been partitioned into two functional units namely Bus Interface Unit (BIU) and Execution Unit (EU) as shown in figure 2.1. The major reason for this separation is to increase the processing speed of the processor. You please observe that this separation and the increase in the word length improve the performance of 8086 in comparison with that of 8085. These two units cooperate asynchronously. The BIU has to interact with memory and input and output devices in fetching the instructions and data required by the EU and in sending the results produced by EU to the memory or the output device. As the name implies, the EU is responsible for executing the instructions of the programs and to carry out the required processing. EU gives the instructions to the BIU to decide where to fetch instructions or data from and where to send the result. In

addition to giving the instructions to the BIU, EU decodes instructions and executes instructions.

Figure 2.1 Functional Components of 8086 Architecture Detailed view of 8086 architecture is shown in figure 2.2.

Figure 2.2 Detailed Architecture of 8086 Microprocessor 2.3.1 The Execution Unit (EU) The Execution Unit (EU) of 8086 microprocessor has control unit, instruction decoder, Arithmetic and Logical Unit (ALU), general registers, flag register, pointers and index registers. Control unit is responsible for the co-ordination of all other units of the processor. It generates timing and control signals which are necessary for the execution of instructions. It controls the data flow between CPU and peripherals (including memory). It provides status, control and timing signals which are required for the operation of memory and I/O devices. It directs the internal operations of the processor. In short, we can say that it controls the entire operations of the microprocessor and peripherals connected to the microprocessor. Hence you can understand that control unit is like the brain of an 8086 based microcomputer system. The EU of 8086 has a 16-bit ALU. ALU performs various arithmetic and logical operations over the data. It takes care of all manipulations required over the data to produce the required output. Some frequently performed operations are addition, subtraction, logical AND, logical OR, logical XOR, complement, left shift, right shift etc. The instruction decoder translates the instructions fetched from the memory into a series of actions that are carried out by the EU. Instruction decoding is the process of segregating the instruction into opcode and operands. Registers Various registers present in the EU can be divided into three categories namely general registers, flag register and pointers and index register. General Registers General registers are used for temporary storage and manipulation of data and instructions. Data remain in the registers till they are sent to the memory or I/O devices. The various general registers are shown in figure 2.3. Accumulator register consists of two 8-bit registers AL and AH, which can be combined together and used as a 16-bit register AX. AL in this case contains the low-order byte of the word, and AH contains the high-order byte. Accumulator can be used for I/O operations and string manipulation.

Base register consists of two 8-bit registers BL and BH, which can be combined together and used as a 16-bit register BX. BL in this case contains the low-order byte of the word, and BH contains the high-order byte. BX register usually contains a data pointer used for based, based indexed or register indirect addressing. Count register consists of two 8-bit registers CL and CH, which can be combined together and used as a 16-bit register CX. When combined, CL register contains the low-order byte of the word, and CH contains the high-order byte. Count register can be used as a counter in string manipulation and shift/rotate instructions. Data register consists of two 8-bit registers DL and DH, which can be combined together and used as a 16-bit register DX. When combined, DL register contains the low-order byte of the word, and DH contains the high-order byte. Data register can be used as a port number in I/O operations. In integer 32-bit multiply and divide instruction the DX register contains high-order word of the initial or resulting number.

Figure 2.3 General Registers of 8086 Flag Register This register is a 16-bit register containing a collection of 9 flags (each flag is a flip flop) as shown in figure 2.4. Each of these flip flops holds 1-bit flag that indicates certain conditions which arises during arithmetic and logic operations.

Figure 2.4 Flag Register of 8086 The meanings of each flag are shown below. Overflow Flag (OF) - set if the result is too large positive number, or is too small negative number to fit into destination operand. Direction Flag (DF) - if set then string manipulation instructions will autodecrement index registers. If cleared then the index registers will be autoincremented. Interrupt-enable Flag (IF) - setting this bit enables maskable interrupts. Single-step Flag (TF) - if set then single-step interrupt will occur after the next instruction. Sign Flag (SF) - set if the most significant bit of the result is set. Zero Flag (ZF) - set if the result is zero. Auxiliary carry Flag (AF) - set if there was a carry from or borrow to bits 0-3 in the AL register. Parity Flag (PF) - set if parity (the number of "1" bits) in the low-order byte of the result is even. Carry Flag (CF) - set if there was a carry from or borrow to the most significant bit during last result calculation. Since flag register reflects the happenings inside the 8086 microprocessor, it is called the Program Status Word (PSW). The contents of PSW, accumulator and other registers are saved in the stack during the handling of interrupt. Flag registers can be summarized as follows.

Pointers and Index registers Pointer registers are used to point to a particular location either in memory or stack from which the data is to be read or to which the data is to be written. Index registers are useful in implementing sophisticated addressing modes (identifying the location of the operands). The EU of 8086 has the set of pointers and index registers as shown in figure 2.5. The functions of pointers and index registers are explained as follows. Stack Pointer (SP) is a 16-bit register pointing to program stack. Base Pointer (BP) is a 16-bit register pointing to data in stack segment. BP register is usually used for based, based indexed or register indirect addressing. Source Index (SI) is a 16-bit register. SI is used for indexed, based indexed and register indirect addressing, as well as a source data addresses in string manipulation instructions. Destination Index (DI) is a 16-bit register. DI is used for indexed, based indexed and register indirect addressing, as well as a destination data addresses in string manipulation instructions.

Figure 2.5 Pointers and Index registers of 8086 2.3.2 The Bus Interface Unit (BIU) The BIU has an instruction stream byte queue, a set of segment registers and instruction pointer. Instruction Byte Queue 8086 instructions vary from 1 to 6 bytes. Therefore fetch and execution are taking place concurrently in order to improve the performance of the microprocessor. The BIU feeds the instruction stream to the execution unit through a 6 byte prefetch queue. This prefetch queue can be considered as a form of loosely coupled pipelining. Execution and decoding of certain instructions do not require the use of buses. While such instructions are executed, the BIU fetches up to six instruction bytes for the following instructions (the subsequent instructions). The BIU store these prefetched bytes in a first-in-first out register by name instruction byte queue. When the EU is ready for its next instruction, it simply reads the instruction byte(s) for the instruction from the queue in BIU. This process is much faster since it forms a pipeline. Segment Registers In 8086, program, data and stack memories occupy the same memory space. The total addressable memory size is 1MB KB. As the most of the processor instructions use 16-bit pointers the processor can effectively address only 64 KB of memory. To access memory outside of 64 KB the CPU uses special segment registers to specify where the code, stack and data 64 KB segments are positioned within 1 MB of memory. Memory can be thought of as a vast collection of bytes. These bytes need to be organized in some efficient manner in order to be of any use. A simple scheme

would be to order the bytes in a serial fashion and number them from 0 (or 1) to the end of memory. The numbers thus given to the individual positions in memory are called ADDRESSES. The problem with this approach is that towards the end of memory, the addresses become very large. For example, if a computer has 1 Megabyte of RAM, the highest address would be 1048575 (=1024*1024-1). This definitely would not fit in a 16-bit register and therefore addresses need to be stored in two registers. The scheme used in the 8086 is called segmentation. Every address has two parts, a SEGMENT and an OFFSET. The segment indicates the starting of a 64 kilobyte portion of memory, in multiples of 16. The offset indicates the position within the 64k portion. Absolute address = (segment * 16) + offset The memory of 8086 is divided into 4 segments namely code segment (program memory), data segment (data memory), stack memory (stack segment) and extra memory (extra segment). The various segments of the memory and the corresponding segment registers are shown in figure 2.6 and they are explained as follows. Program memory Program can be located anywhere in memory. Jump and call instructions can be used for short jumps within currently selected 64 KB code segment, as well as for far jumps anywhere within 1 MB of memory. All conditional jump instructions can be used to jump within approximately +127 - 127 bytes from current instruction. Data memory The processor can access data in any one out of 4 available segments, which limits the size of accessible memory to 256 KB (if all four segments point to different 64 KB blocks). Stack memory A stack is a section of the memory set aside to store addresses and data while a subprogram executes. The stack segment register is used to hold the upper 16 bits of the starting address for the program stack. Extra segment This segment is also similar to data memory where additional data may be stored and maintained. This area is very often used for string related operations. Accessing data from the Data, Code, Stack or Extra segments can be usually done by prefixing instructions with the DS:, CS:, SS: or ES: (some registers and instructions by default may use the ES or SS segments instead of DS segment). Word data can be located at odd or even byte boundaries. The processor uses two memory accesses to read 16-bit word located at odd byte boundaries. Reading word data from even byte boundaries requires only one memory access.

Stack memory can be placed anywhere in memory. The stack can be located at odd memory addresses, but it is not recommended for performance reasons. Code Segment (CS) register is a 16-bit register containing address of 64 KB segment with processor instructions. The processor uses CS segment for all accesses to instructions referenced by instruction pointer (IP) register. CS register cannot be changed directly. The CS register is automatically updated during far jump, far call and far return instructions. Stack Segment (SS) register is a 16-bit register containing address of 64KB segment with program stack. By default, the processor assumes that all data referenced by the stack pointer (SP) and base pointer (BP) registers is located in the stack segment. SS register can be changed directly using POP instruction. Data Segment (DS) register is a 16-bit register containing address of 64KB segment with program data. By default, the processor assumes that all data referenced by general registers (AX, BX, CX, DX) and index register (SI, DI) is located in the data segment. DS register can be changed directly using POP and LDS instructions. Extra Segment (ES) register is a 16-bit register containing address of 64KB segment, usually with program data. By default, the processor assumes that the DI register references the ES segment in string manipulation instructions. ES register can be changed directly using POP and LES instructions.

Figure 2.6 Memory Segments and Segment Register Instruction Pointer The instruction pointer contains a 16-bit offset which tells where in that 64-Kbyte code segment the next instruction byte is to be fetched from. The actual physical address sent to memory is produced by adding the offset contained in the IP register to the segment base represented by the upper 16 bits in the CS register. Segmnet:Offset Notation Segment:Offset addressing was introduced at a time when the largest register in a CPU was only 16-bits (or two bytes) which meant that it could address only 65,536 bytes (64kb) of memory directly. But everyone was hungry for a way to run programs that were much larger than 64kb. Rather than creating a CPU with 9

larger register sizes (of at least 24-bits just to add another byte), the CPU designers at Intel decided to stick with only 16-bit registers for their 8086 CPU and change the way it would use them: They expanded the instruction set so it could group two 16-bit registers together whenever the program needed to tell the CPU to use an Absolute memory location that was too far off for a single two byte register to contain the reference. Unfortunately, they didn't simply combine two registers into a high and low order (which would have given us a way to access up to 4 Gigabytes of memory. Instead, they came up with the Segment:Offset scheme which allowed a CPU to effectively address only about 1 Megabyte of memory. Keep in mind, however, that this was at a time when no one could dream of a PC with more than 640kb of memory The scheme works like this: The value in any register considered being a Segment register is multiplied by 16 (or shifted one hexadecimal byte to the left; add an extra 0 to the end of the hex number) and then the value in an Offset register is added to it. So, the Absolute address for any combination of Segment and Offset pairs is found by using the formula Physical Memeory Location = (Segment value * 16) + Offset Value This will become a lot easier once you've seen a few examples. The Absolute or Linear address for the Segment:Offset pair, F000:FFFD can be computed quite easily in your mind by simply inserting a zero at the end of the Segment value ( which is the same as multiplying by 16 ) and then adding the Offset value: F0000 + FFFD -----FFFFD or 1,048,573(decimal) Here's another example: 923F:E2FF -> 923F0 + E2FF -----A06EF or 657,135(decimal) Now let's compute the Absolute Memory location for the largest value that can be expressed using a Segment:Offset reference FFFF0 + FFFF ------10FFEF or 1,114,095 (decimal)

10

In reality, it wasn't until quite some time after the 8086, that such a large value actually corresponded to a real Memory location. Once it became common for PCs to have over 1MB of memory, programmers developed ways to use it to their advantage and this last byte became part of what's now called the HMA (High Memory Area). But until that time, if a program tried to use a Segment:Offset pair that exceeded a 20-bit Absolute address (1MB), the CPU would truncate the higher bits, effectively mapping any value over FFFFFh (1,048,575) to an address within the first Segment. Thus, 10FFEFh was mapped to FFFEh. One of the downsides in using Segment:Offset pairs (and likely what confuses most of you) is the fact that a large number of these pairs refer to the same exact memory locations. For example, every Segment:Offset pair below, refers to exactly the same location in memory:

0007:7B90 0008:7B80 0009:7B70 000A:7B60 000B:7B50 000C:7B40 0047:7790 0048:7780 0049:7770 004A:7760 004B:7750 004C:7740 0077:7490 0078:7480 0079:7470 007A:7460 007B:7450 007C:7440 01FF:5C10 0200:5C00 0201:5BF0 0202:5BE0 0203:5BD0 0204:5BC0 07BB:0050 07BC:0040 07BD:0030 07BE:0020 07BF:0010 07C0:0000 All the above Segment:Offset pairs are only some of the many ways to refer to the single absolute memory location of 7C00h. As a matter of fact there may be up to 4096 different Segment:Offset pairs for addressing a single byte in Memory; depending upon its particular location. For absolute addresses 0h through FFEFh (o through 65,519), the number of different pairs can be computed as follows: Divide the absolute address by 16 (which shifts all the hex digits one place to the right) Throw away any fractional remainder and add 1

This is the same thing as saying: Add 1 to the segment number if the offset is 000Fh (15) or less. For example, the byte in memory referenced by the Segment:Offset pair 0040:0000 has a total of 41h (or 65) different pairs that might be used. For the Absolute address 7C00h, which was mentioned above, there's a total of: 7C00 / 10h --> 7C0 + 1 = 7C1 (or 1,985) relative ways to address this same memory location using Segment:Offset pairs. For the absolute addresses from FFF0h (65,520) all the way through FFFFFh (1,048,575), there will always be 4,096 Segment:Offset pairs one could use to refer to these

11

addresses. That's a little over 88% of the memory that can be accessed using Segment:Offsets. The last 65,520 bytes that can be accessed by this method are collectively called the High Memory Area (HMA). For each 16 bytes higher in the HMA that we point to, there is one less Segment:Offset pair available to reference that paragraph. Since BIU takes care of the interaction with memory and other peripherals EU is able to concentrate in the processing of data. Moreover the maintenance of the instruction queue enables the 8086 microprocessor unit (MPU) to achieve pipelining. Overall, the performance of 8086 is improved considerably. Have you understood? 1. What are the two functional units of 8086 processor? 2. What is the function of the BIU? 3. What is the function of the EU? 4. What is the purpose of the Instruction Queue of BIU? 5. How does the physical memory location is computed in segment:offset notation? 6. What is the function of the base pointer? 7. What are the functions of SI and DI registers? 8. State the purpose of the four segment registers. 2.4 Properties and Pin Description Intel 8086 is a 16-bit HMOS microprocessor. It is a 40 pin IC. It uses a 5V d.c. supply for its operation. The 8086 uses 20-line address bus. It can directly address up to 1MB (220=1MB) of memory address. It uses 16-line data bus. 16bit data word is sub divided into a low-order byte and a high-order byte. The 20 lines of the address bus operate in multiplexed mode. The 16-low order address bus lines are multiplexed with data and 4 high-order address bus lines are multiplexed with status signals. The schematic diagram of Intel 8086 is shown in figure 2.7. AD0-AD15 (Bidirectional) Address/Data bus. These are low order address bus. They are multiplexed with data. When AD lines are used to transmit memory address the symbol A is used instead of AD, for example A0-A15. When data are transmitted over AD lines the symbol D is used in place of AD, for example D0D7, D8-D15 or D0-D15. A16-A19 (Output) High order address bus. These are multiplexed with status signals. A16/S3, A17/S4, A18/S5, A19/S6 The specified address lines are multiplexed with corresponding status signals.

12

BHE (Active Low)/S7 (Output) Bus High Enable/Status. During T1 it is low. It is used to enable data onto the most significant half of data bus, D8-D15. 8-bit device connected to upper half of the data bus use BHE (Active Low) signal. It is multiplexed with status signal S7. S7 signal is available during T2, T3 and T4. RD (Read) (Active Low) The signal is used for read operation. It is an output signal. It is active when low. READY (Input) The addressed I/O or memory sends acknowledgement through this pin. When HIGH it indicates that the peripheral is ready to transfer data. RESET (Input) System reset. The signal is active high. CLK (Input) Clock. 5, 8 or 10 MHz. INTR Interrupt Request NMI (Input) Non-maskable Interrupt Request TEST (Active Low) (Input) Wait for test control. When it is low the microprocessor continues execution otherwise waits. Vcc Power Supply ( +5V D.C.) GND Ground

13

Figure 2.7 Pin diagram of 8086 2.5 Addressing Modes The way of specifying the address of an operand by a processor is called addressing mode. 8086 microprocessor supports following addressing modes. Implied Addressing The data value/data address is implicitly associated with the instruction. Hence no need to specify the operand explicitly in this addressing mode. Register Addressing The data is specified by referring the register or the register pair in which the data is present. This is also called register direct addressing. Immediate Addressing The data itself is provided in the instruction. Hence in this addressing mode it is not necessary for the microprocessor to refer a memory location or a register/register pair. Direct Addressing The instruction operand specifies the memory address where data is located. Hence a memory reference is required to locate the operand. In all the addressing modes where one or more memory references are required it is necessary for the microprocessor to produce a 20-bit physical

14

address. It does this by adding a 16-bit value called effective address to a segment base address represented by the 16-bit number in one of the four segment registers. In direct addressing mode, we specify the effective address of the operand.

Register indirect addressing The instruction specifies a register containing an address, where data is located. This addressing mode works with SI, DI, BX and BP registers. The effective address is present in a register and that register is specified in the instruction.

Based - 8-bit or 16-bit instruction operand is added to the contents of a base register (BX or BP), the resulting value is a pointer to location where data resides. Indexed - 8-bit or 16-bit instruction operand is added to the contents of an index register (SI or DI), the resulting value is a pointer to location where data resides.

15

Based Indexed - the contents of a base register (BX or BP) is added to the contents of an index register (SI or DI), the resulting value is a pointer to location where data resides. Based Indexed with displacement - 8-bit or 16-bit instruction operand is added to the contents of a base register (BX or BP) and index register (SI or DI), the resulting value is a pointer to location where data resides.

For example, if (BX) = 0158 (DI) = 10A5 Displacement = 1B57 (DS) = 2100

and DS is used as the segment register, then the effective and physical addresses produced by these quantities and the various addressing modes would be Direct: EA = 1B57 Physical address = 1B57+21000 = 22B57 Register: No effective address datum is in specified register. EA = 0158 Physical address = 0158 + 21000 = 21158

16

Register relative assuming register BX EA = 0158 + 1B57 = 1CAF Physical Address = 1CAF + 21000 = 22CAF Based indexed assuming registers BX and DI EA = 0158 + 10A5 + 11FD Physical Address = 11FD + 21000 = 221FD Relative based indexed assuming BX and DI EA = 0158 + 10A5 + 1B57 = 2D54 Physical Address = 2D54 + 21000 = 23D54 Have you understood? 1. What is meant by addressing mode? 2. How is the effective address computed in based indexed addressing mode? 3. In which addressing mode the 16-bit effective address of the datum is a part of the instruction? 4. Differentiate between direct addressing mode and the implied addressing mode. 2.6 Instruction Set The 8086 instructions treat different types of operands uniformly. Nearly every instruction can operate on either byte or word data. Register, memory and immediate operands can be specified interchangeably in most instructions. Immediate values are exceptions: they must serve as source operands and not destination operands. Memory variables can be manipulated (added to, subtracted from, shifted, compared) without being moved into and out of registers. This saves instructions, registers and execution time in assembly language programs. In high-level languages, where most variables are memory-based, compilers can produce faster and shorter object programs. The 8086 Modular Core family instruction set can be viewed as existing on two levels. One is the assembly level and the other is the machine level. To the assembly language programmer, the 8086 Modular Core family appears to have about 100 instructions. One MOV (data move) instruction, for example, transfers a byte or a word from a register, a memory location or an immediate value to either a register or a memory location. The 8086 Modular Core family CPUs, however, recognize 28 different machine versions of the MOV instruction. The two levels of instruction sets address two requirements: efficiency and simplicity. Approximately 300 forms of machinelevel instructions make very efficient use of storage. For example, the machine

17

instruction that increments a memory operand is three or four bytes long because the address of the operand must be encoded in the instruction. Incrementing a register, however, requires less information, so the instruction can be shorter. The 8086 Core family has eight single-byte machine-level instructions that increment different 16-bit registers. The assembly level instructions simplify the programmers view of the instruction set. The programmer writes one form of an INC (increment) instruction and the assembler examines the operand to determine which machine level instruction to generate. The following paragraphs provide a functional description of the assembly-level instructions. 2.6.1 Data Transfer Instructions The instruction set contains 14 data transfer instructions. These instructions move single bytes and words between memory and registers. They also move single bytes and words between the AL or AX register and I/O ports. Table 2-3 lists the four types of data transfer instructions and their functions. Data transfer instructions are categorized as general purpose, input/output, address object and flag transfer. The stack manipulation instructions, used for transferring flag contents and instructions used for loading segment registers are also included in this group. Figure 2-11 shows the flag storage formats. The address object instructions manipulate the addresses of variables instead of the values of the variables. Data transfer instructions are categorized as general purpose, input/output, address object and flag transfer. The stack manipulation instructions, used for transferring flag contents and instructions used for loading segment registers are also included in this group. The address object instructions manipulate the addresses of variables instead of the values of the variables.

18

Examples MOV DS, AX MOV [BX], DX 2.6.2 Arithmetic Instructions

Move (AX) to DS Move (DX) into location indicated by (BX)

Table 2.1 shows the various arithmetic instructions operate on four types of numbers: Unsigned binary Signed binary (integers) Unsigned packed decimal Unsigned unpacked decimal

Table 2.2 shows the interpretations of various bit patterns according to number type. Binary numbers can be 8 or 16 bits long. Decimal numbers are stored in bytes, two digits per byte for packed decimal and one digit per byte for unpacked decimal. The processor assumes that the operands in arithmetic instructions contain data that represents valid numbers for that instruction. Invalid data may produce unpredictable results. The Execution Unit analyzes the results of arithmetic instructions and adjusts status flags accordingly.

19

Table 2.1 Arithmetic Operations

Table 2.2 various bit patterns according to Number Type

20

Examples Suppose that (AL) = B4, which is -76 (in decimal) as an 8-bit signed integer and 180 (in decimal) as an unsigned integer, and the (BL) = 11, which is 17 (in decimal) both as an 8-bit signed integer and as an unsigned integer. Then IMUL BL would cause (AX) = FAF4 = -1292 (in decimal) and (CF) = (OF) = 1 (which implies that the result can not be put in 8 bits). The instruction MUL BL would cause the (AX) = 0BF4 = 3060 (in decimal) and (CF) = (OF) = 1 (which again indicates that the product is too large for 8 bits). CMP CX,BX subtracts the contents of register BX from the contents of CX and decides whether CX=BX or CX>BX or CX<BX base don the contents of CF, ZF or SF as follows. CF 0 0 1 ZF 1 0 0 SF 0 0 1

CX=BX CX>BX CX<BX

2.6.3 Logical Instructions Various logical instructions supported by 8086 are shown in Table 2.3. Logical instructions include the Boolean operators NOT, AND, OR and exclusive OR (XOR), as well as a TEST instruction. The TEST instruction sets the flags as a result of a Boolean AND operation but does not alter either of its operands. Individual bits in bytes and words can be shifted either arithmetically or logically. Up to 32 shifts can be performed, according to the value of the count operand coded in the instruction. The count can be specified as an immediate value or as a variable in the CL register. This allows the shift count to be a supplied at execution time. Arithmetic shifts can be used to multiply and divide binary numbers by powers of two. Logical shifts can be used to isolate bits in bytes or words. Individual bits in bytes and words can also be rotated. The processor does not discard the bits rotated out of an operand. The bits circle back to the other end of the operand. The number of bits to be rotated is taken from the count operand, which can specify either an immediate value or the CL register. The carry flag can act as an extension of the operand in two of the rotate instructions. This allows a bit to be isolated in the Carry Flag (CF) and then tested by a JC (jump if carry) or JNC (jump if not carry) instruction. Examples Suppose if (DL) = 10001010 and NOT DL is executed then New (DL) = 01110101

21

Suppose if (AL) = 10010110 and (LOG_DATA) = 010111010 then the instruction OR AL, LOG_DATA will produce New (AL) = 11011110

Table 2.3 Logical Instructions

2.6.4 String Instructions Five basic string operations process strings of bytes or words, one element (byte or word) at a time. Strings of up to 64 Kbytes can be manipulated with these instructions. Instructions are available to move, compare or scan for a value, as well as to move string elements to and from the accumulator. Table 2.4 lists the string instructions. These basic operations can be preceded by a one-byte prefix that causes the instruction to be repeated by the hardware, allowing long strings to be processed much faster than is possible with a software loop. The repetitions can be terminated by a variety of conditions. Repeated operations can be interrupted and resumed.

22

Table 2.4 String Instructions

A string instruction can have a source operand, a destination operand, or both. The hardware assumes that a source string resides in the current data segment. A segment prefix can override this assumption. A destination string must be in the current extra segment. The assembler does not use the operand names to address strings. Instead, the contents of the Source Index (SI) register are used as an offset to address the current element of the source string. The contents of the Destination Index (DI) register are taken as the offset of the current destination string element. These registers must be initialized to point to the source and destination strings before executing the string instructions. The LDS, LES and LEA instructions are useful in performing this function. String instructions automatically update the SI register, the DI register, or both, before processing the next string element. The Direction Flag (DF) determines whether the index registers are autoincremented (DF = 0) or auto-decremented (DF = 1). The processor adjusts the DI, SI, or both registers by one for byte strings or by two for word strings. If a repeat prefix is used, the count register (CX) is decremented by one after each repetition of the string instruction. The CX register must be initialized to the number of repetitions before the string instruction is executed. If the CX register is 0, the string instruction is not executed and control goes to the following instruction. Examples

23

CMPSB instruction will compare the byte pointed to by SI with the byte pointed to by DI and set the flags according to the result. It will also increment the pointers SI and DI to point to the next string elements. The REPE prefix in front of this instruction tells the 8086 to decrement the CX register after each compare and repeat the CMPSB instruction if the compared bytes were equal and CX is not yet decremented down to zero. 2.6.5 Program Transfer Instructions The contents of the Code Segment (CS) and Instruction Pointer (IP) registers determine the instruction execution sequence in the 8086 Modular Core family. The CS register contains the base address of the current code segment. The Instruction Pointer register points to the memory location of the next instruction to be fetched. In most operating conditions, the next instruction will already have been fetched and will be waiting in the CPU instruction queue. Program transfer instructions operate on the IP and CS registers. Changing the contents of these registers causes normal sequential operation to be altered. When a program transfer occurs, the queue no longer contains the correct instruction. The Bus Interface Unit obtains the next instruction from memory using the new IP and CS values. It then passes the instruction directly to the Execution Unit and begins refilling the queue from the new location. The 8086 Modular Core family offers four groups of program transfer instructions (shown in table 2.5). These are unconditional transfers, conditional transfers, iteration control instructions and interrupt-related instructions. Unconditional transfer instructions can transfer control either to a target instruction within the current code segment (intrasegment transfer) or to a different code segment (intersegment transfer). The assembler terms an intrasegment transfer SHORT or NEAR and an intersegment transfer FAR. The transfer is made unconditionally when the instruction is executed. CALL, RET and JMP are all unconditional transfers. CALL is used to transfer the program to a procedure. A CALL can be NEAR or FAR. A NEAR CALL stacks only the Instruction Pointer, while a FAR CALL stacks both the Instruction Pointer and the Code Segment register. The RET instruction uses the information pushed onto the stack to determine where to return when the procedure finishes. Note that the RET and CALL instructions must be the same type. This can be a problem when the CALL and RET instructions are in separately assembled programs. The JMP instruction does not push any information onto the stack. A JMP instruction can be NEAR or FAR. Conditional transfer instructions are jumps that may or may not transfer control, depending on the state of the CPU flags when the instruction is executed. Each conditional transfer instruction tests a different combination of flags for a condition (see Table 2-10). If the condition is logically TRUE, control is transferred to the target specified in the instruction. If the condition is FALSE, control passes to the instruction following the conditional jump. All conditional jumps are SHORT. The target must be in the current code segment within 128

24

to +127 bytes of the next instructions first byte. For example, JMP 00H causes a jump to the first byte of the next instruction. Jumps are made by adding the relative displacement of the target to the Instruction Pointer. All conditional jumps are self-relative and are appropriate for position-independent routines. The interrupt instructions allow programs and external hardware devices to activate interrupt service routines. The effect of a software interrupt is similar to that of a hardware-initiated interrupt. The processor cannot execute an interrupt acknowledge bus cycle if the interrupt originates in software or with an NMI (Non-Maskable Interrupt). Examples CMP TOTAL, 100 JGE EXIT would result in a branch to EXIT if the contents of TOTAL are greater than or equal to 100. JMP TABLE[SI] would get the branch address from the memory location whose address is that of TABLE+(SI). This instruction would cause the branch address to be selected from an array of addresses and could be used as part of a multiple-branch decision. Table 2.5 Program Transfer Instructions

25

26

2.6.6 Processor Control Instructions Processor control instructions shown in Table 2.6 allow programs to control various CPU functions. Seven of these instructions update flags, four of them are used to synchronize the microprocessor with external events, and the remaining instruction causes the CPU to do nothing. Except for flag operations, processor control instructions do not affect the flags. Table 2.6 Processor Control Instructions

Have you understood? 1. What is the difference between ADD and ADC instructions? 2. Mention the status of the related flags in deciding equal to, greater than and less than relationships. 3. Differentiate between JBE and JNA instructions. 4. What is the purpose of the process control instructions? 2.7 Assembler Directives Assembler directives give instruction to the assembler where as other instructions discussed in the above section give instruction to the 8086 microprocessor. Assembler directives are specific for a particular assembler. However all the popular assemblers like the Intel 8086 macro assembler, the turbo assembler and the IBM macro assembler use common assembler directives.

The ASSUME directive tell the assembler the name of the logical segment it should use for a specified segment. The DB directive is used to declare a byte-type variable or to set aside one or more storage locations of type byte in memory (Define Byte). 27

The DD directive is used to declare a variable of type doubleword or to reserve memory locations which can be accessed as type doubleword. (Define Doubleword) The DQ directive is used to tell the assembler to declare a variable 4 words in length or to reverse 4 words of storage in memory. (Define Quadword) The DT directive is used to tell the assembler to define a variable which is 01 bytes in length or to reserve 10 bytes of storage in memory. (Define Ten Bytes) The DW directive is used to tell the assembler to define a variable of type word or to reserve storage locations of type word in memory. (Define Word) The END directive is put after the last statement of a program to tell the assembler that this is the end of the program module. The ENDP directive is used along with the name of the procedure to indicate the end of a procedure to the assembler. The ENDS directive is used with the name of a segment to indicate the end of that logical segment. The EQU is used to give a name to some value or symbol. The EVEN directive tells the assembler to increment the location counter to the next even address if it is not already at an even address. This directive is useful since 8086 can read a series of words much more quickly if they are at even addresses. The EXTRN directive is used to tell the assembler that the names or labels following the directive are in some other assembly module. The GLOBAL directive can be used in place of a PUBLIC directive or in place of an EXTERN directive. For a name or symbol defined in the current assembly module, the GLOBAL directive is used to make the symbol available to other modules. The GROUP directive is used to tell the assembler to group the logical segments named after the directive into one logical group segment. This allows the contents of all the segments to be accessed from the same group segment base. The INCLUDE directive is used to tell the assembler to insert a block of source code from the named file into the current source module.

28

The LABEL directive is used to give a name to the current value in the location counter. The LABEL directive must be followed by a term which specifies the type you want associated with that name. The LENGTH is an operator which tells the assembler to determine the number of elements in some named data item, such as a string or an array. The NAME directive is used to give a specific name to each assembly module when programs consisting of several modules are written. The OFFSET is an operator which tells the assembler to determine the offset or displacement of a named data item (variable) or procedure from the start of the segment which contains it. The ORG directive is used to set the location counter to a desired value at any point in the program. The PROC directive is used to identify the start of a procedure. The PROC directive follows a name you give the procedure. After the PROC directive, the term near or far is used to specify the type of the procedure. The PTR operator is used to assign a specific type to a variable or to a label. It is necessary to do this in any instruction where the type of the operand is not clear. In order for the various modules of a large program to link together correctly, any variable name or label referred to in other modules must be declared public in the module in which it is defined. The PUBLIC directive is used to tell the assembler that a specified name or label will be accessed from other modules. The SEGMENT directive is used to indicate the start of a logical statement. Preceding the SEGMENT directive is the name you want to give the segment. The SHORT operator is used to tell the assembler that only 1-byte displacement is needed to code a jump instruction. The TYPE operator tells the assembler to determine the type of a specified variable. The assembler actually determines the number of bytes in the type of the variable. Have you understood? 1. What is the difference between the routine instructions and directives in an assembly language program? 2. Differentiate between the assembler directive and the assembler operator. 3. Give examples for assembler operators.

29

2.8 Writing an Assembly Language Program Writing assembly language programs for 8086 is slightly different from that of writing assembly language programs for 8085. In addition to the instructions that are meant for solving the problem, some additional instructions are required to complete the programs. The purpose of these additional programs is to initialize various parts of the system, such as segment registers, flags and programmable port devices. Some of the instructions are to handle the stack of the 8086 based system. If we use stack in our program, then it is necessary to load the stack segment register and an instruction to load the stack pointer register with the offset of the top of the stack. Another purpose of these additional instructions is to handle the programmable peripheral devices such as ports, timers and controllers. The programmable peripheral interfaces should be assigned suitable control words to make them to function in the way as we expect. The best way to approach the initialization task is to make a checklist of all the registers, programmable devices and flags in the system we are working on. Then we can mark the ones we need for a specific program and determine the instructions needed to initialize each part. An 8086 assembly language program has five columns namely address, data or code, labels, mnemonics, operands and comments. The address column is used for the address or the offset of a code byte or a data byte. The actual code bytes or data bytes are put in the data or code column. A label is a name which represents an address referred to in a jump or call instruction. Labels are put in the labels column. A label is followed by a colon (:) if it is used by a jump or call instruction in the same code segment. The mnemonics column contains the opcode mnemonics for the instructions. The operands column contains the registers, memory locations or data acted upon by the instructions. A comments column gives space to describe the function of the instruction for future reference. An assembly language program to multiply two 16-bit numbers DATA SEGMENT MLND_NUMBER MLPR_NUMBER RESULT

DW 2036H DW 3178H DW 2 DUP (0)

DATA CODE START: SEGMENT ASSUME CS:CODE, DS:DATA MOV AX, DATA MOV DS, AX MOV AX, MLND_NUMBER MUL MLPR_NUMBER

30

CODE

MOV RESULT, AX MOV RESULT+2, DX INT 3 ENDS END START

Various functions performed by the above program are Initialize the segment registers Move the multiplicand in the accumulator Multiply the contents of the accumulator with the multiplier Store the result in adjacent memory locations An assembly language program that compares two strings is shown as follows. DATA SEGMENT STRINGONE STR_LENGTH STRINGTWO ENDS SEGMENT ASSUME DB ANNAUNIV EQU ($ - STRINGONE) DB 8 DUP(0)

DATA CODE

CODE

CS:CODE, DS:DATA, ES:DATA MOVE AX, DATA MOVE DS, AX MOVE ES, AX MOV DX, 0FFFEH MOV AL, 99H OUT DX, AL LEA SI, STRINGONE LEA DI, STRINGTWO MOV CX, STR_LENGTH CLD REPE CMPSB JNE NO_MATCH JMP MATCH NO_MATCH: MOV AL, 01 MOV DX, 0FFFAH OUT DX, AL HLT MATCH: NOP ENDS END

Various functions performed by the above program are Initialize the segment registers Setup an output port

31

Load source pointer Load destination pointer Load counter with string one length Increment source index and destination index registers Compare the two string bytes If equal continue to compare the following bytes If not equal, inform it by making an alarm

Summary 1. The Intel 8086 is a 16-bit microprocessor. 16-bit indicates that the word length of the microprocessor. The 8086 microprocessor is able to process 16 bits of information at a time. 2. The 8086 CPU logic has been partitioned into two functional units namely Bus Interface Unit (BIU) and Execution Unit (EU). 3. The BIU has to interact with memory and input and output devices in fetching the instructions and data required by the EU and in sending the results produced by EU to the memory or the output device. 4. The EU is responsible for executing the instructions of the programs and to carry out the required processing. 5. The Execution Unit (EU) of 8086 microprocessor has control unit, instruction decoder, Arithmetic and Logical Unit (ALU), general registers, flag register, pointers and index registers. 6. The BIU has an instruction stream byte queue, a set of segment registers and instruction pointer. 7. In the Segment:Offset scheme the value in any register considered being a Segment register is multiplied by 16 (or shifted one hexadecimal byte to the left; add an extra 0 to the end of the hex number) and then the value in an Offset register is added to it. 8. The way of specifying the address of an operand by a processor is called addressing mode. 9. The various types of addressing modes supported by 8086 are implied, register, immediate, direct and register indirect modes. 10. The 8086 instruction set includes data transfer instructions, arithmetic instructions, logical instructions, string instructions, program transfer instructions and process control instructions. 11. Assembler directives give instruction to the assembler where as other instructions give instruction to the 8086 microprocessor. 12. An 8086 assembly language program includes some additional instructions besides the instructions that are meant for solving the problem. The purpose of these additional instructions is to initialize various parts of the system, such as segment registers, flags and programmable port devices.

32

In this unit, you have learnt about the architecture, addressing modes and instruction set of 8086 a 16-bit microprocessor. Even though 8086 was designed and implemented with the intention of using it in a general purpose digital computer, it was never used due to the incompatibility problem that existed with the peripherals of that time. Personal computers were designed and implemented using 8088 an 8-bit processor externally and 16-bit processor. Unit III deals with interfacing the peripherals to the microprocessor and designing a microcomputer in terms of 8086 microprocessor.

Exercises 1. Describe the function of the 8086 queue. How does the queue speed up processing? 2. What physical address is represented by 4370:561EH and 7A32:0028H? 3. Describe the difference between the instructions MOV AX,2437H and MOV AX, [2437H]. 4. Write an 8086 assembly language program to convert a 16-digit unpacked BCD number to a packed BCD number. 5. Explain the EVEN directive with an example. Answers 1. To execute an instruction it is necessary for the 8086 microprocessor to decode the instruction into opcode and operands. Usually the Execution Unit performs this job. The EU does not require the use of buses for this job. Hence the Bus Interface Unit (BIU) stores these prefetched bytes in a first in first out register set called a queue. When the EU is ready for its next instruction, it simply reads the instruction byte(s) for the instruction from the queue in the BIU. This is much faster than sending out an address to the system memory and waiting for memory to send back the next instruction byte or bytes. 2. 4370:561EH 43700 +561E --------48D1E --------7A32:0028H 7A320 +0028 --------7A348 3. MOV AX, 2437H moves the 16 bit number 2437H into accumulator.

33

MOV AX, [2437H] moves the 16 bit number present in the memory location whose address is represented by the offset 2437H 4. MOV DX,8 MOV CL,4 MOV SI,0 MOV DI,SI CONV: MOV AX,WORD PTR UNPACKED[SI] SHL AL,CL SHR AX,CL MOV PACKED[DI], AL ADD SI,2 INC DI DEC DX JNZ CONV 5. DATA_HERE SEGMENT ;Location counter will point ;to 0009 after assembler ;reads next statement SLAVES_AVERAGES DB 9 DUP(?) ;declare array of 9 bytes EVEN ;increment location ;counter to 000AH INVENTORY_RECORDS DW 100 DUP(0) ; Array of 100 words starting ; on even address for ; quicker read DATA_HERE ENDS

34