Chapter – 3 Addressing Modes
Introduction
Efficient software development for the microprocessor requires a complete familiarity with the addressing modes employed by each instruction. These are
1. Data addressing modes,
2. Memory addressing modes, and
3. Stack addressing.
The data-addressing modes include ;
1. register,
2. immediate,
3. direct,
4. register indirect,
5. base plus-index,
6. register relative, and
7. base relative-plus-index
in the 8086 through the 80286 microprocessor. The 80386 and above also
8. include scaled-index
mode of addressing memory data.
The program memory-addressing modes include
1. program relative,
2. direct, and
3. indirect.
The operation of the stack memory is explained so that the PUSH and POP instructions are understood.
3. Data-Addressing Modes
Because the MOV instruction is a common and flexible instruction, it provides a basis for the explanation of the data-addressing modes. Figure 3-1 illustrates the MOV instruction and defines the direction of data flow. The source is to the right and the destination is to the left, next to the opcode MOV. An opcode, or operation code, tells the microprocessor which operation to perform.
dIn Figure 3-1, the MOV AX,BX instruction transfers the word contents of the source register (BX) into the destination register (AX). The source never changes, but the destination usually changes.1 It is essential to remember that a MOV instruction always copies the source data and into the destination. The MOV never actually picks up the data and moves it. Also, note that the flag register remains unaffected by most data transfer instructions. The source and destination are often called operands.
The data-addressing modes are as follows:
3.1. Register Addressing
Register addressing is the most common form of data addressing. The microprocessor contains the following 8-bit registers used with register addressing: AH, AL, BH, BL, CH, CL, DH, and DL. Also present are the following 16-bit registers: AX, BX, CX, DX, SP, BP, SI, and DI. In the 80386 and above, the extended 32-bit registers are EAX, EBX, ECX, EDX, ESP, EBP, EDI, and ESI. With register addressing, some MOV instructions, and the PUSH and POP instructions, also use the 16-bit segment registers (CS, ES, DS, SS, FS, and GS).
It is important for instructions to use registers that are the same size. Never mix an 8-bit register with a 16-bit register, an 8-bit register with a 32-bit register, or a 16-bit register with 32-bit register because this is not allowed by the microprocessor and results in an error when assembled. This is even true when a MOV AX,AL or a MOV EAX,AL instruction may seem to make sense. Of course, the MOV AX,AL or MOV EAX,AL instruction is not allowed because these registers are of different sizes. Note that a few instructions, such as SHL DX,CL, are exceptions to this rule. It is also important to note that none of the MOV instructions affect the flag bits.
Table 3-1 shows some variations of register move instructions. It is impossible to show all combinations because there are too many. A segment-to-segment register MOV instruction is not allowed. Note that the code segment register is not normally changed by a MOV instruction because the address of the next instruction is found in both IP/EIP and CS. If only CS were changed, the address of the next instruction would be unpredictable. Therefore, changing the CS register with a MOV instruction is not allowed.
Figure 3-3 shows the operation of the MOV BX,CX instruction. Note that the source register’s contents do not change, but the destination register’s contents do change. The instruction copies a 1234H from register CX into register BX. This erases the old contents (76AFH) of register BX, but the contents of CX remain unchanged. The contents of the destination register or destination memory location change for all instructions except the CMP and TEST instructions. Note that the MOV BX, CX instruction does not affect the leftmost 16 bits of register EBX.
3.2. Immediate Addressing
Another data-addressing mode is immediate addressing. The term immediate implies that the data immediately follow the hexadecimal opcode in the memory. Also note that immediate data are constant data, while the data transferred from a register are variable data. Immediate addressing operates upon a byte or word of data. In the 80386 through the Pentium II microprocessor, immediate addressing also operates on doubleword data. The MOV immediate instruction transfers a copy of the immediate data into a register or a memory location. Figure 3-4 shows the operation of a MOV EAX,13456H instruction. This instruction copies the 13456H from the instruction, located in the memory immediately following the hexadecimal opcode, into register EAX. As with the MOV instruction illustrated in Figure 3-3, the source data overwrites the destination data.
The symbolic assembler portrays immediate data in many ways. The letter H appends hexadecimal data. If hexadecimal data begin with a letter, the assembler requires that the data start with a 0. For example, to represent a hexadecimal F2, a 0F2H is used in assembly language. An ASCII-coded character or characters may be depicted in the immediate form if the ASCII data are enclosed in apostrophes. (An example is the MOV BH,’A’ instruction, which moves an ASCII-coded A (41H) into register BH.) Be careful to use the apostrophe (‘) for ASCII data and not the single quotation mark. Binary data are represented if the binary number is followed by the letter B, or, in some assemblers, the letter Y. Table 3-2 shows many different variations of MOV instructions that apply immediate data.
Direct Data Addressing
Most instructions can use the direct data-addressing mode. In fact, direct data addressing is applied to many instructions in a typical program. There are two basic forms of direct data addressing:
1.Direct addressing, which applies to a MOV between a memory location and AL, AX, or EAX, and
2.Displacement addressing, which applies to almost any instruction in the instruction set. In either case, the address is formed by adding the displacement to the default data segment address or an alternate segment address.
Direct Addressing; Direct addressing with a MOV instruction transfers data between a memory location, located within the data segment, and the AL (8-bit), AX (16-bit), or EAX (32-bit) register. A MOV instruction using this type of addressing is usually a 3-byte long instruction. (In the 80386 and above, a register size prefix may appear before the instruction, causing it to exceed three bytes in length.)
The MOV AL,DATA instruction, as represented by most assemblers, loads AL from data segment memory location DATA (1234H). Memory location DATA is a symbolic memory location, while the 1234H is the actual hexadecimal location. With many assemblers, this instruction is represented as a MOV AL,[1234H17 instruction. The [1234H] is an absolute memory location that is not allowed by all assembler programs. Note that this may need to be formed as MOV AL,DS:[l234Hj with some assemblers, to show that the address is in the data segment. Figure 3—5 shows how this instruction transfers a copy of the byte-sized contents of memory location 11 234H into AL. The effective address is formed by adding I 234H (the offset address) to 1000H (the data segment address of I000H) in a system operating in the real mode.
Table 3—3 lists the three direct addressed instructions. These instructions often appear in programs, so Intel decided to make them special three-byte long instructions to reduce the length
of programs. All other instructions that move data from a memory location to a register, called displacement-addressed instructions, require four or more bytes of memory for storage in a program.
Displacement Addressing. Displacement addressing is almost identical to direct addressing, except that the instruction is four bytes wide instead of three. In the 80386 through the Pentium II, this instruction can be up to seven bytes wide if a 32-bit register and a 32-bit displacement are specified. This type of direct data addressing is much more flexible because most instructions use it.
If the operation of the MOV CL,DS:[l234H] instruction is compared to that of the MOV AL,DS: [I 234Hj instruction of Figure 3—5, both basically perform the same operation except for the destination register (CL versus AL). Another difference only becomes apparent upon examining the assembled versions of these two instructions. The MQV AL,DS:[1234H] instruction is three bytes long and the MOV CL,DS: [12341-I] instruction is four bytes long, as illustrated in Example 3—4. This example shows how the assembler converts these two instructions into hexadecimal machine language. You must include the segment register DS: in this example, before the [offset] part of the instruction. You may use any segment register, but, in most cases, data are stored in the data segment, so this example uses DS:[1234H].
Table 3—4 lists some MOV instructions, using the displacement form of direct addressing. Not all variations are listed because there are many MOV instructions of this type. The segment registers can be stored or loaded from memory.
Example 3—5 shows a short program using models that address information in the data segment. Note that the data segment begins with a DATA statement to inform the assembler where the data segment begins. The model size is adjusted from TINY, as shown in Example 3—3, to SMALL so that a data segment can be included. The SMALL model allows one data segment and one code segment. The SMALL model is often used whenever memory data are required for a program. A SMALL model program assembles as an execute (.EXE) program. Notice how this example allocates memory locations in the data segment by using the DB and DW directives. Here the .STARTUP statement not only indicates the start of the code, but it also loads the data segment register with the segment address of the data segment. If this program is assembled and
executed with CodeView, the instructions can be viewed as they execute and change registers and memory locations.
Register Indirect Addressing
Register indirect addressing allows data to be addressed at any memory location through an offset address held in any of the following registers: BP, BX, DI, and SI. For example, if register BX contains a l000H and the MOV AX,[BX] instruction executes, the word contents of data segment offset address I 000H are copied into register AX. If the microprocessor is operated in the real mode and DS = OIOOH, this instruction addresses a word stored at memory bytes 2000H and 2001H, and transfers it into register AX (see Figure 3—6). Note that the contents of 2000H are moved into AL and the contents of 2001H are moved into AH. The [ ] symbols denote indirect addressing in assembly language. In addition to using the BP, BX, DI, and SI registers to indirectly address memory, the 80386 and above allow register indirect addressing with any extended register except ESP. Some typical instructions using indirect addressing appear in Table 3—5.
The data segment is used by default with register indirect addressing or any other addressing mode that uses BX, DI, or SI to address memory. If the BP register addresses memory, the stack segment is used by default. These settings are considered the default for these four index and base registers. For the 80386 and above, EBP addresses memory in the stack segment by default; FAX, EBX, ECX, EDX, EDT, and ESI address memory in the data segment by default. When using a 32-bit register to address memory in the real mode, the contents of the 32-bit register must never exceed 0000FFFFH. In the protected mode, any value can be used in a 32-bit register that is used to indirectly address memory, as long as it does not access a location outside of the segment, as dictated by the access rights byte. An example 80386/80486/Pentium II instruction is MOV EAX,[EBX]. This instruction loads FAX with the doubleword-sized number stored at the data segment offset address indexed by EBX.
In some cases, indirect addressing requires specifying the size of the data are specified with the special assembler directive BYTE PTR, WORD PTR, or DWORD PTR. These directives indicate the size of the memory data addressed by the memory pointer (PTR). For example, the MOV AL,[DIJ instruction is clearly a byte-sized move instruction, but the MOV [DI], 1OH instruction is ambiguous. Does the MOV [DIJ,10H instruction address a byte-, word-, or double-word-sized memory location? The assembler can’t determine the size of the IOH. The instruction MOV BYTE PTR [DI],IOH clearly designates the location addressed by Dl as a byte-sized memory location. Likewise, the MOV DWORD PTR [DI],IOH clearly identifies t~ie memory location as doubleword-sized. The BYTE PTR, WORD PTR, and DWORD PTR directives are used only with instructions that address a memory location through a pointer or index register with immediate data, and for a few other instructions that are described in subsequent chapters.
Indirect addressing often allows a pi cam to refer to tabular data located in the memory system. For example, suppose that you must create a table of information that contains 50 samples taken from memory location 0000:046C. Location 0000:046C contains a counter that is maintained by the personal computer’s real-time clock. Figure 3—7 shows the table and the BX register used to sequentially address each location in the table. To accomplish this task, load the starting location of the table into the BX register with a MOV immediate instruction. After initializing the starting address of the table, use register indirect addressing to store the 50 samples sequentially.
The sequence shown in Example 3—6 loads register BX with the starting address of the table and initializes the count, located in register CX, to 50. The OFFSET directive tells the assembler to load BX with the offset address of memory location TABLE, not the contents of
TABLE. For example. the MOV BX,DATAS instruction copies the contents of memory location DATAS into BX, while the MOV BX,OFFSET DATAS instruction copies the offset address of DATAS into BX. When the OFFSET directive is used with the MOV instruction, the assembler calculates the offset address and then uses a MOV immediate instruction to load the address into the specified 16-bit register.
Once the counter and pointer are initialized, a repeat-until CX = 0 loop executes. Here, data are read from extra segment memory location 46CH with the MOV AX,ES:[046CH] instruction and stored in memory that is indirectly addressed by the offset address located in register BX. Next, BX is incremented (one is added to BX) to the next table location, and finally the LOOP instruction repeats the LOOP 50 times. The LOOP instruction decrements (subtracts one from) the counter (CX); if CX is not zero, LOOP causes a jump to memory location AGAIN. If CX becomes zero, no jump occurs and this sequence of instructions ends. This example copies the most recent 50 values from the clock into the memory array DATAS. This program will often show the same data in each location because the contents of the clock are changed only4 18.2 times per second. To view the program and its execution, use the CodeView program. To
use CodeView, type CV FILE.EXE or access it as DEBUG from the Programmer’s WorkBench program under the RUN menu. Note that CodeView functions only with .EXE or .COM files. Some useful CodeView switches are /50 for a 50-line display and IS for use of high-resolution video displays in an application. To debug the file TEST.COM with 50 lines, type CV /50 TEST.COM at the DOS prompt.
Base-Plus-Index Addressing
Base-plus-index addressing is similar to indirect addressing because it indirectly addresses memory data. In the 8086 through the 80286, this type of addressing uses one base register (BP or BX), and one index register (DI or SI) to indirectly address memory. The base register often holds the beginning location of a memory array, while the index register holds the relative position of an element in the array. Remember that whenever BP addresses memory data, both the stack segment register and BP generate the effective address.
In the 80386 and above, this type of addressing allows the combination of any two 32-bit extended registers except ESP. For example, the MOV DL,[EAX+EBX] instruction is an example using FAX (as the base) plus EBX (as the index). If the EBP register is used, the data are located in the stack segment instead of in the data segment.
Locating Data with Base-plus-index Addressing. Figure 3—8 shows how data are addressed by the MOV DX,[BX+DI] instruction when the microprocessor operates in the real mode. In this example, BX = 1000H, DI = OO1OH, and DS O100H, which translate into memory address 02010H. This instruction transfers a copy of the word from location 02010H into the DX register. Table 3—6 lists some instructions used for base-plus-index addressing. Note that the Intel assembler requires that this addressing mode appear as [BX] [DI] instead of [BX+DI]. The MOV DX,[BX+DI] instruction is MOV DX,[BX] [DI] for a program written for the Intel ASM assembler. This text uses the first form in all example programs. but the second form can be used in many assemblers, including MASM from Microsoft. Instructions like MOV DI,[BX+DI] will assemble, but will not execute correctly.
Locating Array Data Using Base-p/us-index Addressing. A major use of the base-plus-index addressing mode is to address elements in a memory array. Suppose that the elements in an array, located in the data segment at memory location ARRAY, must be accessed. To accomplish this, load the BX register (base) with the beginning address of the array, and the DI register (index) with the element number to be accessed. Figure 3—9 shows the use of BX and DI to access an element in an array of data.
A short program, listed in Example 3—7, moves array element 1 OH into array element 20H. Notice that the array element number, loaded into the DI register, addresses the array element. Also notice how the contents of the ARRAY have been initialized so that element 1OH contains a 29H.
Register Relative Addressing
Register relative addressing is similar to base-plus-index addressing and displacement addressing. In register relative addressing, the data in a segment of memory are addressed by adding the displacement to the contents of a base or an index register (BP, BX, DI, or SI). Figure 3—10 shows the operation of the MOV AX,[BX+l000I-I] instruction. In this example, BX = OlOOH and DS = 0200H, so the address generated is the sum of DS x 101-I, BX, and the displacement of L000H or 03100H. Remember that BX, DI, or SI addresses the data segment and BP addresses the stack segment. In the 80386 and above, the displacement can be a 32-bit number and the register can be any 32-bit register except the ESP register. Remember that the size of a real mode segment is 64K bytes long. Table 3—7 lists a few instructions that use register relative addressing.
The displacement can be a number added to the register within the [ ], as in the MOV AL,[DI+2] instruction, or it can be a displacement subtracted from the register, as in MOV AL,[SI—lj. A displacement also can be an offset address appended to the front of the [ 1. as in MOV AL,DATA[DI]. Both forms of displacements also can appear simultaneously, as in the MOV AL,DATA[DI+3] instruction. In all cases, both forms of the displacement add to the base, or base and index register within the [I. In the 8086—80286 microprocessors, the value of the displacement is limited to a 16-bit signed number with a value ranging between +32,767 (7FFFH)
and —32,768 (8000I-I)~ in the 80386 and above, a 32-bit displacement is allowed with a value ranging between +2,147,483,647 (7FFFFFFFH) and —2J4L483,648 (80000000H).
Addressing Array Data with Register Relative. It is possible to address array data with register relative addressing, such as one does with base-plus-index addressing. In Figure 3—11, register relative addressing is illustrated with the same example as for base-plus-index addressing. This shows how the displacement ARRAY adds to index register DI to generate a reference to an array element.
Example 3—8 shows how this new addressing mode can transfer the contents of array elernent 101-I into array element 20H. Notice the similarity between this example and Example 3—7. The main difference is that, in Example 3—8, register BX is not used to address memory area ARRAY~ instead, ARRAY is used as a displacement to accomplish the same task.
Base Relative-Plus-Index Addressing
The base relative-plus-index addressing mode is similar to the base-plus-index addressing mode. but it adds a displacement, besides using a base register and an index register, to form the memory address. This type of addressing mode often addresses a two-dimensional array of memory data.
Addressing Data with Base Relative-plus-index. Base relative-plus-index addressing is the least-used addressing mode. Figure 3—12 shows how data are referenced if the instruction executed by the microprocessor is a MOV AX,[BX+S1+LOOHj. The displacement of 10011 adds to BX and SI to form the offset address within the data segment. Registers BX = 002011, SI = 001 OH. and DS = 100011, so the effective address for this instruction is JOJ3OH—the sum of these registers plus a displacement of 100H. This addressing mode is too complex for frequent use in a program. Some typical instructions using base relative-plus-index addressing appear in Table 3—8. Note that with the 80386 and above, the effective address is generated by the sum of two 32-bit registers plus a 32-bit displacement.
Addressing Arrays with Base Relative-plus-index. Suppose that a file of many records exists in memory and each record contains many elements. This displacement addresses the file, the base register addresses a record, and the index register addresses an element of a record. Figure 3—13 illustrates this very complex form of addressing.
Example 3—9 provides a program that copies element 0 of record A into element 2 of record C by using the base relative-plus-index mode of addressing. This example FILE contains four records and each record contains 10 elements. Notice how the THIS BYTE statement is used to define the label FILE and RECA as the same memory location.
Scaled-Index Addressing
Scaled-index addressing is the last type of data-addressing mode discussed. This data-addressing mode is unique to the 80386 through the Pentium II microprocessors. Scaled-index addressing uses two 32-bit registers (a base register and an index register) to access the memory. The second register (index) is multiplied by a scaling factor. The scaling factor can be JX, 2X, 4X, or 8X. A scaling factor of lX is implied and need not be included in the assembly language instruction (MOV AL,[EBX+ECX]). A scaling factor of 2X is used to address word-sized memory arrays, a scaling factor of 4X is used with doubleword-sized memory arrays, and a scaling factor of 8X is used with quadword-sized memory anays.
An example instruction is MOV AX,[EDI+2*ECXj. This instruction uses a scaling factor of 2X, which multiplies the contents of ECX by 2 before adding it to the EDI register to form the memory address. If ECX contains a 00000000H, word-sized memory element 0 is addressed; if ECX contains a 0000000 1H, word-sized memory element 1 is accessed, and so forth. This scales the index (ECX) by a factor of 2 for a word-sized memory anay. Refer to Table 3—9 for some examples of scaled-index addressing. As you can imagine, there are an extremely large number of the scaled-index addressed register combinations. Scaling is also applied to instructions that use a single indirect register to access memory. The MOV EAX,[4*EDI] is a scaled-index instruction that uses one register to indirectly address memory.
Example 3—10 shows a sequence of instructions that uses scaled-index addressing to access a word-sized array of data called LIST. Note that the offset~address of LIST is loaded into register EBX with the MOV EBX,OFFSET LIST instruction. Once EBX addresses array LIST, the elements (located in ECX) of 2, 4, and 7 of this word-wide array are added, using a scaling factor of 2 to access the elements. This program stores the 2 at element 2 into elements 4 and 7. Also notice the .386 directive to select the 80386 microprocessor. This directive must follow the MODEL statement for the assembler to process 80386 instructions for DOS. If the 80486 is in use, the .486 directive appears after the MODEL statement; if the Pentium, Pentium Pro, or Pentium II is in use, the .~86 directive appears after MODEL. If the microprocessor selection directive appears before the .MODEL statement, the microprocessor executes instructions in the 32-bit mode, which is not compatible with DOS.
Data Structures
A data structure is used to specify how information is stored in a memory array and can be quite useful with applications that use arrays. It is best to think of a data structure as a template for data. The start of a structure is identified with the STRUC assembly language directive and the end with the ENDS statement. A typical data structure is defined and used three times in Example 3—11. Notice that the name of the structure appears’with the STRUC and with ENDS statement.
The data structure in Example 3—11 defines five fields of information. The first is 32 bytes long and holds a name; the second is 32 bytes long and holds a street address; the third is 16 bytes long for the city; the fourth is 2 bytes long for the state; the fifth is 5 bytes long for the ZIP Code. Once the structure is defined (INFO), it can be filled, as illustrated, with names and addresses. Three examples of uses for INFO are illustrated. Note that literals are surrounded with apostrophes and the entire field is surrounded with <> symbols when the data structure is used to define data.
When data are addressed in a structure, use the structure name and the field name to select a field from the structure. For example, to address the STREET in NAME2, use the operand NAME2.STREET, where the name of the structure is first followed by a period and then by the name of the field. Likewise, use NAME3.CITY to refer to the city in structure NAME3.
A short sequence of instructions appears in Example 3—12 that clears the name field in structure NAME 1, the address field in structure NAME2, and the ZIP Code field in structure NAME3. The function and operation of the instructions in this program are defined in later chapters in the text. You may wish to refer to this example once these instructions are learned.
PROGRAM MEMORY-ADDRESSING MODES
Program memory-addressing modes, used with the iMP and CALL instructions, consist of three distinct forms: direct, relative, and indirect. This section introduces these three addressing forms, using the JMP instruction to illustrate their operat(on.
Direct Program Memory Addressing
Direct program memory addressing is what many early microprocessors used for all jumps and calls. Direct program memory addressing is also used in high-level languages, such as the BASIC language GOTO and GOSUB instructions. The microprocessor uses this form of addressing, but not as often as relative and indirect program memory addressing are used.
The instructions for direct program memory addressing store the address with the opcode. For example, if a program jumps to memory location 1000011 for the next instruction, the
address (10000H) is stored following the opcode in the memory. Figure 3—14 shows the direct intersegment iMP instruction and the four bytes required to store the address 1000011. This IMP instruction loads CS with 100011 and IP with 000011 to jump to memory location 1000011 for the next instruction. (An intersegment jump is a jump to any memory location within the entire memory system.) The direct jump is often called afar jump because it can jump to any memory location for the next instruction. In the real mode, a farjump accesses any location within the first IM byte of memory by changing both CS and IP. In protected mode operation, the far jump accesses a new code segment descriptor from the descriptor table, allowing it to jump to any memory location in the entire 4G-byte address range in the 80386 through Pentium II microprocessors.
The only other instruction that uses direct program addressing is the intersegment or far CALL instruction. Usually, the name of a memory address, called a label, refers to the location that is called or jumped to instead of the actual numeric address. When using a label with the CALL or JMP instruction, most assemblers select the best form of program addressing.
Relative Program Memory Addressing
Relative program memory addressing is not available in all early microprocessors, but it is available to this family of microprocessors. The term relative means “relative to the instruction pointer (IP).” For example, if a JMP instruction skips the next two bytes of memory, the address in relation to the instruction pointer is a 2 that adds to the instruction pointer. This develops the address of the next program instruction. An example of the relative JMP instruction is shown in Figure 3—15. Notice that the IMP instruction is a one-byte instruction, with a one-byte or a two-byte displacement that adds to the instruction pointer. A one-byte displacement is used in short jumps, and a two-byte displacement is used with near jumps and calls. Both types are considered to be intrasegrnent jumps. (An intrasegment jump is a jump anywhere within the current code segment.) In the 80386 and above, the displacement can also be a 32-bit value, allowing them to use relative addressing to any location within their 4G-byte code segments.
Relative JMP and CALL instructions contain either an 8-bit or a 16-bit signed displacement that allows a forward memory reference or a reverse memory reference. (The 80386 and above can have an 8-bit or 32-bit displacement.) All assemblers automatically calculate the distance for the displacement and select the proper one-, two- or four-byte form. If the distance is too far for a two-byte displacement in an 8086 through 80286 microprocessor, some assemblers use the direct jump. An 8-bit displacement (short) has a jump range of between +127 and —128 bytes from the next instruction, while a 16-bit displacement (near) has a range of ±32K bytes. In the 80386 and above, a 32-bit displacement allows a range of ±2G bytes. The 32-bit displacement can only be used in the protected mode.
lndirect Program Memory Addressing
The microprocessor allows several forms of program indirect memory addressing for the JMP and CALL instructions. Table 3—10 lists some acceptable program indirect jump instructions, which can use any 16-bit register (AX, BX, CX, DX. SP, BP, DI, or SI); any relative register
([BP], [BX], [DI], or [SI]); and any relative register with a displacement. In the 80386 and above, an extended register can also be used to hold the address or indirect address of a relative JMP or CALL. For example, the JMP EAX jumps to the location address by register EAX.
If a 16-bit register holds the address of a JMP instruction, the jump is near. For example, if the BX register contains a I000H and a JMP BX instruction executes, the microprocessor jumps to offset address 100011 in the current code segment.
If a relative register holds the address, the jump is also considered to be an indirect jump. For example, a IMP [BXj refers to the memory location within the data segment at the offset address contained in BX. At this offset address is a 16-bit number that is used as the offset address in the intrasegment jump. This type of jump is sometimes called an indirect-indirect or double-indirect jump.
Figure 3—16 shows a jump table that is stored, beginning at memory location TABLE. This jump table is referenced by the short program of Example 3—13. In this example, the BX register is loaded with a 4 so, when it combines in the IMP TABLE[BXJ instruction with TABLE, the effective address is the contents of the second entry in the jump table.
STACK MEMORY-ADDRESSING MODES
The stack plays an important role in all microprocessors. 11 holds data temporarily and stores return addresses for procedures. The stack memory is a LIFO (last-in, first-out) memory, which describes the way that data are stored and removed from the stack. Data are placed onto the stack
with a PUSH instruction and removed with a POP instruction. The CALL instruction also uses the stack to hold the return address for procedures and a RET (return) instruction to remove the return address from the stack.
The stack memory is maintained by two registers: the stack pointer (SP or ESP) and the stack segment register (SS). Whenever a word of data is pushed onto the stack [see Figure 3—17(a)], the high-order 8 bits are placed in the location addressed by SP — 1. The low-order 8 bits are placed in the location addressed by SP — 2. The SP is then decremented by 2 so that the next word of data is stored in the next available stack memory location. The SP/ESP register always points to an area of memory located within the stack segment. The SPIESP register adds to SS x IOH to form the stack memory address in the real mode. In protected mode operation, the SS register holds a selector that accesses a descriptor for the base address of the stack segment.
Whenever data are popped from the stack [see Figure 3—17(b)], the low-order 8 bits are removed from the location addressed by SP. The high-order 8 bits are removed from the location addressed by SP + 1. The SP register is then incremented by 2. Table 3—Il lists some of the
PUSH and POP instructions available to the microprocessor. Note that PUSH and POP always store or retrieve words of data never bytes in the 8086 through the 80286 microprocessors. The 80386 and above allow words or doublewords to be transferred to and from the stack. Data may be pushed onto the stack from any 16-bit register or segment register; in the 80386 and above, from any 32-bit extended register. Data may be popped off the stack into any 16-hit register or any segment register except CS. The reason that data may not he popped from the stack into CS is that this only changes part of the address of the next instruction.
The PUSHA and POPA instructions either push or pop all of the registers, except the segment registers, on the stack. These instructions are not available on the early 8086/8088 microprocessors. The push immediate instruction is also new to the 80286 through the Pentium microprocessors. Note the examples in Table 3—Il, which show the order of the registers transferred by the PUSHA and POPA instructions. The 80386 and above also allow extended registers to be pushed or popped.
Example 3—14 lists a short program that pushes the contents of AX. BX. and CX onto the stack. The first POP retrieves the value that was pushed onto the stack from CX and places it into AX. The second POP places the original value of BX into CX. The last POP places the original value of AX into BX.
Register addressing
Transfers a copy of a byte or word from the source register or memory location to the destination register or memory location. (Example: the MOV CX,DX instruction copies the word-sized contents of register DX into register CX.) In the 80386 and above, a doubleword can be transferred from the source register or memory location to the destination register or memory location. (Example: the MOV ECX,EDX instruction copies the doubleword-sized contents of register EDX into register ECX.)
Immediate addressing
Transfers the source-immediate byte or word of data into the destination register or memory location. (Example: the MOV AL,22H instruction copies a byte-sized 22H into register AL.) In the 80386 and above, a doubleword of immediate data can be transferred into a register or memory location. (Example: the MOV EBX, 12345678H instmction copies a doubleword-sized 12345678H into the 32-bit wide EBX register.)
Direct
addressing
Moves a byte or word between a memory location and a register. The instruction set does not support a memory-to-memory transfer, except for the MOVS instruction. (Example: the MOV CX,LIST instruction copies the word-sized contents of memory location LIST into register
CX.) In the 80386 and above, a doubleword-sized memory location can also be addressed. (Example: the MOV ESI,LIST instruction copies a 32-bit number, stored in four consecutive bytes of memory, from location LIST into register ESI.)
Register indirect addressing
Transfers a byte or word between a register and a memory location addressed by an index or base register. The index and base registers are BP, BX, DI, and SI. (Example: the MOV AX,IBX] instruction copies the word-sized data from the data segment offset address indexed by BX into register AX.) In the 80386 and above, a byte, word, or double-word is transferred between a register and a memory location addressed by any register: EAX, EBX, ECX, EDX, EBP. ED1, or ESI. (Example:
the MOV AL,[ECX] instruction loads AL from the data segment offset address selected by the contents of ECX.)
Base-plus-index addressing
Transfers a byte or word between a register and the memory location addressed by a base register (BP or BX) plus an index register (DI or SI). (Example: the MOV [BX+DH,CL instruction copies the hytcsized contents of register CL into the data segment memory location addressed by BX plus DI.) In the 80386 and above, any register EAX, EBX, ECX, EDX, EBP, EDI, or ESI may be combined to generate the memory address. (Example: the MOV [EAX+EBX],CL instruction copies the byte-sized contents of register CL into the data segment memory location addressed by EAX plus EBX.)
Register relative addressing
Moves a byte or word between a register and the memory location addressed by an index or base register plus a displacement. (Example:
MOV AX,[BX±4] or MOV AX,ARRAY[BX]. The first instruction loads AX from the data segment address formed by BX plus 4. The second instruction loads AX from the data segment memory location in ARRAY plus the contents of BX.) The 80386 and above use any register to address memory. (Example: MOV AX,[ECX+4] or MOV AX,ARRAY[EBX]. The first instruction loads AX from the data segment address formed by ECX plus 4. The second instruction loads AX from the data segment memory location ARRAY plus thc contents of EBX.)
Base relative-plus-index addressing
Transfers a byte or word between a register and the memory location addressed by a base and an index register plus a displacement. (Example:
MOV AX,ARRAY[BX+DI] or MOV AX,IBX±DI+41. These instructions load AX from a data segment memory location. The first instruction uses an address formed by adding ARRAY. BX, and Dl and the second by adding BX, DI. and 4.) In the 80386 and above, MOV EAX,ARRAY[EBX+ECX] loads EAX from the data segment memory location accessed by the sum of ARRAY, EBX, and ECX.
Scaled-index addressing
Is available only in the 80386 through the Pentium Pro microprocessor. The second register of a pair of registers is modified by the scale factor of 2X, 4X, or 8X to generate the operand memory address. (Example: a MOV EDX,[EAX±4*EBX] instruction loads EDX from the data secmnent memory location addressed by EAX plus 4 times EBX.) Scaling allows access to word (2X), doubleword (4X), or quadword (8X) memory array data. Note that a scaling factor of lX also exists, hut ii is normally implied and does not appear in the instruction. The MOV
AL,[EBX+ECX] is an example in which the scaling factor is a one.
Alternately, the instruction can be rewritten as MOV AL, [EBX+ I *ECX].
Another example is a MOV AL,[2*EBXJ instruction, which uses only
one scaled register to address memory.