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 con-tains 1000H and the MOV AX,[BX] instruction executes, the word contents of data segment offset address 1000H are copied into register AX. If the microprocessor is operated in the real mode and , 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 mem-ory, 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. If a Pentium 4 or Core2 is available that operates in the 64-bit mode, any 64-bit register is used to hold a 64-bit linear address.
In the 64-bit mode, the segment registers serve no purpose in addressing a location in the flat model.
DS = 0100H
TABLE 3–4 Examples of direct data addressing using a displacement.
Assembly Language Size Operation
MOV CH,DOG 8 bits Copies the byte contents of data segment memory location DOG into CH
MOV CH,DS:[1000H]* 8 bits Copies the byte contents of data segment memory offset address 1000H into CH
MOV ES,DATA6 16 bits Copies the word contents of data segment memory location DATA6 into ES
MOV DATA7,BP 16 bits Copies BP into data segment memory location DATA7 MOV NUMBER,SP 16 bits Copies SP into data segment memory location NUMBER MOV DATA1,EAX 32 bits Copies EAX into data segment memory location DATA1 MOV EDI,SUM1 32 bits Copies the doubleword contents of data segment memory
location SUM1 into EDI
*This form of addressing is seldom used with most assemblers because an actual numeric offset address is rarely accessed.
+ 3412
1000 2000
*1000
00001000 00001001 00001002 00002000 00002002 00002001 1 2
3 4 AL1 2
AH3 4
0 0 1 0
0 1 0 0 CS
EAX EBX ECX
DS
*After DS is appended with a 0.
FIGURE 3–6 The operation of the MOV AX,[BX] instruction when BX = 1000H and DS = 0100H.
Note that this instruction is shown after the contents of memory are transferred to AX.
TABLE 3–5 Examples of register indirect addressing.
Assembly Language Size Operation
MOV CX,[BX] 16 bits Copies the word contents of the data segment memory location addressed by BX into CX
MOV [BP],DL* 8 bits Copies DL into the stack segment memory location addressed by BP
MOV [DI],BH 8 bits Copies BH into the data segment memory location addressed by DI
MOV [DI],[BX] — Memory-to-memory transfers are not allowed except with string instructions
MOV AL,[EDX] 8 bits Copies the byte contents of the data segment memory location addressed by EDX into AL
MOV ECX,[EBX] 32 bits Copies the doubleword contents of the data segment memory location addressed by EBX into ECX
MOV RAX,[RDX] 64 bits Copies the quadword contents of the memory location address by the linear address located in RDX into RAX (64-bit mode)
*Note: Data addressed by BP or EBP are by default in the stack segment, while other indirect addressed instructions use the data segment by default.
The data segment is used by default with register indirect addressing or any other address-ing 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;
EAX, EBX, ECX, EDX, EDI, and ESI address memory in the data segment by fault. 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–Pentium 4 instruction is MOV EAX,[EBX]. This instruction loads EAX with the doubleword-sized number stored at the data segment offset address indexed by EBX. In the 64-bit mode, the segment registers are not used in the address calculation because the register contains the actual linear memory address.
In some cases, indirect addressing requires specifying the size of the data. The size is spec-ified by the special assembler directive BYTE PTR, WORD PTR, DWORD PTR, or QWORD PTR. These directives indicate the size of the memory data addressed by the memory pointer (PTR). For example, the MOV AL,[DI] instruction is clearly a byte-sized move instruction, but the MOV [DI],10H instruction is ambiguous. Does the MOV [DI],10H instruction address a byte-, word-, doubleword-, or quadword-sized memory location? The assembler can’t determine the size of the 10H. The instruction MOV BYTE PTR [DI],10H clearly designates the location addressed by DI as a byte-sized memory location. Likewise, the MOV DWORD PTR [DI],10H clearly identifies the memory location as doubleword-sized. The BYTE PTR, WORD PTR, DWORD PTR, and QWORD PTR directives are used only with instructions that address a mem-ory location through a pointer or index register with immediate data, and for a few other instruc-tions that are described in subsequent chapters. Another directive that is occasionally used is the QWORD PTR, where a QWORD is a quadword (64-bits mode). If programs are using the SIMD instructions, the OWORD PTR, an octal word, is also used to represent a 128-bit-wide number.
Indirect addressing often allows a program to refer to tabular data located in the memory system. For example, suppose that you must create a table of information that contains 50 sam-ples taken from memory location 0000:046C. Location 0000:046C contains a counter in DOS 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 sam-ples sequentially.
The sequence shown in Example 3–7 loads register BX with the starting address of the table and it 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 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 in the specified 16-bit register.
Memory
Table + 49
Table + 2 Table + 1 Table 0 0 0 0 T A B L E
EBX FIGURE 3–7 An array
(TABLE) containing 50 bytes that are indirectly addressed through register BX.
EXAMPLE 3–7
.MODEL SMALL ;select small model 0000 .DATA ;start data segment 0000 0032 [ DATAS DW 50 DUP(?) ;setup array of 50 words
0000 ]
0000 .CODE ;start code segment .STARTUP ;start program 0017 B8 0000 MOV AX,0
001A 8E C0 MOV ES,AX ;address segment 0000 with ES 001C B8 0000 R MOV BX,OFFSET DATAS ;address DATAS array with BX 001F B9 0032 MOV CX,50 ;load counter with 50 0022 AGAIN:
0022 26:A1 046C MOV AX,ES:[046CH] ;get clock value
0026 89 07 MOV [BX],AX ;save clock value in DATAS 0028 43 INC BX ;increment BX to next element 0029 43 INC BX
002A E2 F6 LOOP AGAIN ;repeat 50 times .EXIT ;exit to DOS
END ;end program listing
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 (1 is added to BX) twice to address the next word in the table. Finally, the LOOP instruction repeats the LOOP 50 times. The LOOP instruction decrements (subtracts 1 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 only 18.2 times per second. To view the program and its execution, use the CodeView program. To use CodeView, type CV XXXX.EXE, where XXXX.EXE is the name of the program that is being debugged. You can also 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 /S for use of high-resolution video displays in an application. To debug the file TEST.COM with 50 lines, type CV /50 /S TEST.COM at the DOS prompt.