SUMMARY OF DATA MOVEMENT INSTRUCTIONS.

SUMMARY

1. Data movement instructions transfer data between registers, a register and memory, a register and the stack, memory and the stack, the accumulator and I/O, and the flags and the stack. Memory-to-memory transfers are allowed only with the MOVS instruction.

2. Data movement instructions include MOV, PUSH, POP, XCHG, XLAT, IN, OUT, LEA, LOS, LES, LSS, LGS, LFS, LAHF, SAHF, and the following string instructions: LODS, STOS, MOVS, INS, and OUTS.

3. The first byte of an instruction contains the opcode. The opcode specifies the operation per- formed by the microprocessor. The opcode may be preceded by one or more override pre- fixes in some forms of instructions.

4. The D-bit, located in many instructions, selects the direction of data flow. If D = 0, the data flow from the REG field to the R/M field of the instruction. If D = 1, the data flow from the R/M field to the REG field.

5. The W-bit, found in most instructions, selects the size of the data transfer. If W = 0, the data are byte-sized; if W = 1, the data are word-sized. In the 80386 and above, W = 1 specifies either a word or doubleword register.

6. MOD selects the addressing mode of operation for a machine language instruction’s R /M field. If MOD = 00, there is no displacement; if MOD = 01, an 8-bit sign-extended dis- placement appears; if MOD = 10, a 16-bit displacement occurs; and if MOD = 11, a regis- ter is used instead of a memory location. In the 80386 and above, the MOD bits also specify a 32-bit displacement.

7. A 3-bit binary register code specifies the REG and R/M fields when the MOD = 11. The 8- bit registers are AH, AL, BH, BL, CH, CL, DH, and DL. The l6-bit registers are AX, BX, CX, DX, SP, BP, DI, and SI. The 32-bit registers are EAX, EBX, ECX, EDX, ESP, EBP, EDI, and ESI. To access the 64-bit registers, a new prefix is added called the REX prefix that contains a fourth bit for accessing registers R8 through R15.

8. When the R/M field depicts a memory mode, a 3-bit code selects one of the following modes: 3BX + DI4, 3BX + SI4, 3BP + DI4, 3BP+ SI4, [BX], [BP], [DI], or [SI] for 16-bit instructions. In the 80386 and above, the R/M field specifies EAX, EBX, ECX, EDX, EBP, EDI, and ESI or one of the scaled-index modes of addressing memory data. If the scaled- index mode is selected 1R>M = 1002, an additional byte (scaled-index byte) is added to the instruction to specify the base register, index register, and the scaling factor.

9. By default, all memory-addressing modes address data in the data segment unless BP or EBP addresses memory. The BP or EBP register addresses data in the stack segment.

10. The segment registers are addressed only by the MOV, PUSH, or POP instructions. The instruction may transfer a segment register to a 16-bit register, or vice versa. MOV CS,reg or POP CS instructions are not allowed because they change only a portion of the address. The 80386 through the Pentium 4 include two additional segment registers, FS and GS.

11. Data are transferred between a register or a memory location and the stack by the PUSH and POP instructions. Variations of these instructions allow immediate data to be pushed onto the stack, the flags to be transferred between the stack, and all 16-bit registers can be transferred between the stack and the registers. When data are transferred to the stack, 2 bytes (8086–80286) always move. The most significant byte is placed at the location addressed by SP – 1, and the least significant byte is placed at the location addressed by SP – 2. After placing the data on the stack, SP is decremented by 2. In the 80386–Core2, 4 bytes of data from a memory location or register may also be transferred to the stack.

12. Opcodes that transfer data between the stack and the flags are PUSHF and POPF. Opcodes that transfer all the 16-bit registers between the stack and the registers are PUSHA and POPA. In the 80386 and above, PUSHFD and POPFD transfer the contents of the EFLAGS between the microprocessor and the stack, and PUSHAD and POPAD transfer all the 32-bit registers. The PUSHA and POPA instructions are invalid in the 64-bit mode.

13. LEA, LDS, and LES instructions load a register or registers with an effective address. The LEA instruction loads any 16-bit register with an effective address; LDS and LES load any 16- bit register and either DS or ES with the effective address. In the 80386 and above, additional instructions include LFS, LGS, and LSS, which load a 16-bit register and FS, GS, or SS.

14. String data transfer instructions use either or both DI and SI to address memory. The DI off- set address is located in the extra segment, and the SI offset address is located in the data segment. If the 80386–Core2 is operated in protected mode, ESI and EDI are used with the string instructions.

15. The direction flag (D) chooses the auto-increment or auto-decrement mode of operation for DI and SI for string instructions. To clear D to 0, use the CLD instruction to select the auto- increment mode; to set D to 1, use the STD instruction to select the auto-decrement mode. Either or both DI and SI increment/decrement by 1 for a byte operation, by 2 for a word operation, and by 4 for a doubleword operation.

16. LODS loads AL, AX, or EAX with data from the memory location addressed by SI; STOS stores AL, AX, or EAX in the memory location addressed by DI; and MOVS transfers a byte, a word, or a doubleword from the memory location addressed by SI into the location addressed by DI.

17. INS inputs data from an I/O device addressed by DX and stores it in the memory location addressed by DI. The OUTS instruction outputs the contents of the memory location addressed by SI and sends it to the I/O device addressed by DX.

18. The REP prefix may be attached to any string instruction to repeat it. The REP prefix repeats the string instruction the number of times found in register CX.

19. Arithmetic and logic operators can be used in assembly language. An example is MOV AX,34*3, which loads AX with 102.

20. Translate (XLAT) converts the data in AL into a number stored at the memory location addressed by BX plus AL.

21. IN and OUT transfer data between AL, AX, or EAX and an external I/O device. The address of the I/O device is either stored with the instruction (fixed-port addressing) or in register DX (variable-port addressing).

22. The Pentium Pro–Core2 contain a new instruction called CMOV, or conditional move. This instruction only performs the move if the condition is true.

23. The segment override prefix selects a different segment register for a memory location than the default segment. For example, the MOV AX,[BX] instruction uses the data segment, but the MOV AX,ES:[BX] instruction uses the extra segment because of the ES: override prefix. Using the segment override prefix is the only way to address the FS and GS segments in the 80386 through the Pentium 4.

24. The MOVZX (move and zero-extend) and MOVSX (move and sign-extend) instructions, found in the 80386 and above, increase the size of a byte to a word or a word to a double- word. The zero-extend version increases the size of the number by inserting leading zeros. The sign-extend version increases the size of the number by copying the sign-bit into the more significant bits of the number.

25. Assembler directives DB (define byte), DW (define word), DD (define doubleword), and DUP (duplicate) store data in the memory system.

26. The EQU (equate) directive allows data or labels to be equated to labels.

27. The SEGMENT directive identifies the start of a memory segment and ENDS identifies the end of a segment when full-segment definitions are in use.

28. The ASSUME directive tells the assembler what segment names you have assigned to CS, DS, ES, and SS when full-segment definitions are in effect. In the 80386 and above, ASSUME also indicates the segment name for FS and GS.

29. The PROC and ENDP directives indicate the start and end of a procedure. The USES direc- tive (MASM version 6.x) automatically saves and restores any number of registers on the stack if they appear with the PROC directive.

30. The assembler assumes that software is being developed for the 8086/8088 microprocessor unless the .286, .386, .486, .586, or .686 directive is used to select one of these other micro- processors. This directive follows the .MODEL statement to use the 16-bit instruction mode and precedes it for the 32-bit instruction mode.

31. Memory models can be used to shorten the program slightly, but they can cause problems for larger programs. Also be aware that memory models are not compatible with all assembler programs.

 

DATA MOVEMENT INSTRUCTIONS:ASSEMBLER DETAIL.

ASSEMBLER DETAIL

The assembler (MASM)1 for the microprocessor can be used in two ways: (1) with models that are unique to a particular assembler, and (2) with full-segment definitions that allow complete control over the assembly process and are universal to all assemblers. This section of the text presents both methods and explains how to organize a program’s memory space by using the assembler. It also explains the purpose and use of some of the more important directives used with this assembler. Appendix A provides additional detail about the assembler.

In most cases, the inline assembler found in Visual C+ + is used for developing assembly code for use in a C+ + program, but there are occasions that require separate assembly modules writing using the assembler. This section of the text contrasts, where possible, the inline assembler and the assembler.

Directives

Before the format of an assembly language program is discussed, some details about the directives (pseudo-operations) that control the assembly process must be learned. Some common assembly language directives appear in Table 4–22. Directives indicate how an operand or sec- tion of a program is to be processed by the assembler. Some directives generate and store information in the memory; others do not. The DB (define byte) directive stores bytes of data in the memory, whereas the BYTE PTR directive never stores data. The BYTE PTR directive indicates the size of the data referenced by a pointer or index register. Note that none of the directives function in the inline assembler program that is a part of Visual C+ + . If you are using the inline assembler exclusively, you can skip this part of the text. Be aware that complex sections of assembly code are still written using MASM.

Note that by default the assembler accepts only 8086/8088 instructions, unless a program is preceded by the .686 or .686P directive or one of the other microprocessor selection switches. The .686 directive tells the assembler to use the Pentium Pro instruction set in the real mode, and the .686P directive tells the assembler to use the Pentium Pro protected mode instruction set. Most modern software is written assuming that the microprocessor is a Pentium Pro or newer, so the .686 switch is often used. Windows 95 was the first major operating system to use a 32-bit architecture that conforms to the 80386. Windows XP requires a Pentium class machine (.586 switch) using at least a 233MHz microprocessor.

Storing Data in a Memory Segment. The DB (define byte), DW (define word), and DD (define doubleword) directives, first presented in Chapter 1, are most often used with MASM to define and store memory data. If a numeric coprocessor executes software in the system, the DQ (define quadword) and DT (define ten bytes) directives are also common. These directives label a memory location with a symbolic name and indicate its size.

Example 4–13 shows a memory segment that contains various forms of data definition directives. It also shows the full-segment definition with the first SEGMENT statement to indicate the start of the segment and its symbolic name. Alternately, as in past examples in this and prior chapters, the SMALL model can be used with the .DATA statement. The last statement in this example contains the ENDS directive, which indicates the end of the segment. The name of the segment (LIST_SEG) can be anything that the programmer desires to call it. This allows a pro- gram to contain as many segments as required.

Data Movement Instructions-0131Data Movement Instructions-0132Data Movement Instructions-0133

Example 4–13 shows various forms of data storage for bytes at DATA1. More than 1 byte can be defined on a line in binary, hexadecimal, decimal, or ASCII code. The DATA2 label shows how to store various forms of word data. Doublewords are stored at DATA3; they include floating-point, single-precision real numbers.

Memory is reserved for use in the future by using a question mark (?) as an operand for a DB, DW, or DD directive. When a ? is used in place of a numeric or ASCII value, the assembler sets aside a location and does not initialize it to any specific value. (Actually, the assembler usu- ally stores a zero into locations specified with a?.) The DUP (duplicate) directive creates an array, as shown in several ways in Example 4–12. A 10 DUP (?) reserves 10 locations of mem- ory, but stores no specific value in any of the 10 locations. If a number appears within the ( ) part of the DUP statement, the assembler initializes the reserved section of memory with the data indicated. For example, the LIST2 DB 10 DUP (2) instruction reserves 10 bytes of memory for array LIST2 and initializes each location with a 02H.

The ALIGN directive, used in this example, makes sure that the memory arrays are stored on word boundaries. An ALIGN 2 places data on word boundaries and an ALIGN 4 places them on doubleword boundaries. In the Pentium–Pentium 4, quadword data for double-precision floating-point numbers should use ALIGN 8. It is important that word-sized data are placed at word boundaries and doubleword-sized data are placed at doubleword boundaries. If not, the microprocessor spends additional time accessing these data types. A word stored at an odd- numbered memory location takes twice as long to access as a word stored at an even-numbered memory location. Note that the ALIGN directive cannot be used with memory models because the size of the model determines the data alignment. If all doubleword data are defined first, fol- lowed by word-sized and then byte-sized data, the ALIGN statement is not necessary to align data correctly.

ASSUME, EQU, and ORG. The equate directive (EQU) equates a numeric, ASCII, or label to another label. Equates make a program clearer and simplify debugging. Example 4–14 shows several equate statements and a few instructions that show how they function in a program.

Data Movement Instructions-0134

The THIS directive always appears as THIS BYTE, THIS WORD, THIS DWORD, or THIS QWORD. In certain cases, data must be referred to as both a byte and a word. The assembler can only assign either a byte, word, or doubleword address to a label. To assign a byte label to a word, use the software listed in Example 4–15.

Data Movement Instructions-0135

This example also illustrates how the ORG (origin) statement changes the starting off- set address of the data in the data segment to location 300H. At times, the origin of data or the code must be assigned to an absolute offset address with the ORG statement. The ASSUME statement tells the assembler what names have been chosen for the code, data, extra, and stack segments. Without the ASSUME statement, the assembler assumes nothing and automatically uses a segment override prefix on all instructions that address memory data. The ASSUME statement is only used with full-segment definitions, as described later in this section of the text.

PROC and ENDP. The PROC and ENDP directives indicate the start and end of a procedure (subroutine). These directives force structure because the procedure is clearly defined. Note that if structure is to be violated for whatever reason, use the CALLF, CALLN, RETF, and RETN instructions. Both the PROC and ENDP directives require a label to indicate the name of the procedure. The PROC directive, which indicates the start of a procedure, must also be followed with a NEAR or FAR. A NEAR procedure is one that resides in the same code segment as the program. A FAR procedure may reside at any location in the memory system. Often the call NEAR procedure is considered to be local, and the call FAR procedure is considered to be global. The term global denotes a procedure that can be used by any program; local defines a procedure that is only used by the current program. Any labels that are defined within the procedure block are also defined as either local (NEAR) or global (FAR).

Example 4–16 shows a procedure that adds BX, CX, and DX and stores the sum in register AX. Although this procedure is short and may not be particularly useful, it does illustrate how to use the PROC and ENDP directives to delineate the procedure. Note that information about the operation of the procedure should appear as a grouping of comments that show the registers changed by the procedure and the result of the procedure.

Data Movement Instructions-0136Data Movement Instructions-0137

If version 6.x of the Microsoft MASM assembler program is available, the PROC directive specifies and automatically saves any registers used within the procedure. The USES statement indicates which registers are used by the procedure, so that the assembler can automatically save them before your procedure begins and restore them before the procedure ends with the RET instruction. For example, the ADDS PROC USES AX BX CX statement automatically pushes AX, BX, and CX on the stack before the procedure begins and pops them from the stack before the RET instruction executes at the end of the procedure. Example 4–17 illustrates a procedure written using MASM version 6.x that shows the USES statement. Note that the registers in the list are not separated by commas, but by spaces, and the PUSH and POP instructions are dis- played in the procedure listing because it was assembled with the .LIST ALL directive. The instructions prefaced with an asterisk (*) are inserted by the assembler and were not typed in the source file. The USES statement appears elsewhere in this text, so if MASM version 5.10 is in use, the code will need to be modified.

Data Movement Instructions-0138

Memory Organization

The assembler uses two basic formats for developing software: One method uses models and the other uses full-segment definitions. Memory models, as presented in this section and briefly in earlier chapters, are unique to the MASM assembler program. The TASM assembler also uses memory models, but they differ somewhat from the MASM models. The full-segment definitions are common to most assemblers, including the Intel assembler, and are often used for soft- ware development. The models are easier to use for simple tasks. The full-segment definitions offer better control over the assembly language task and are recommended for complex pro- grams. The model was used in early chapters because it is easier to understand for the beginning programmer. Models are also used with assembly language procedures that are used by high- level languages such as C>C+ + . Although this text fully develops and uses the memory model definitions for its programming examples, realize that full-segment definitions offer some advantages over memory models, as discussed later in this section.

Models. There are many models available to the MASM assembler, ranging from tiny to huge. Appendix A contains a table that lists all the models available for use with the assembler. To designate a model, use the .MODEL statement followed by the size of the memory system. The TINY model requires that all software and data fit into one 64K-byte memory segment; it is useful for many small programs. The SMALL model requires that only one data segment be used with one code segment for a total of 128K bytes of memory. Other models are available, up to the HUGE model.

Example 4–18 illustrates how the .MODEL statement defines the parameters of a short program that copies the contents of a 100-byte block of memory (LISTA) into a second 100- byte block of memory (LISTB). It also shows how to define the stack, data, and code segments. The .EXIT 0 directive returns to DOS with an error code of 0 (no error). If no parameter is added to .EXIT, it still returns to DOS, but the error code is not defined. Also note that special directives such as @DATA (see Appendix A) are used to identify various segments. If the .STARTUP directive is used (MASM version 6.x), the MOV AX,@DATA fol- lowed by MOV DS,AX statements can be eliminated. The .STARTUP directive also eliminates the need to store the starting address next to the END label. Models are important with both Microsoft Visual C+ + and Borland C+ + development systems if assembly language is included with C+ + programs. Both development systems use inline assembly programming for adding assembly language instructions and require an understanding of programming models.

Data Movement Instructions-0139

Full-Segment Definitions. Example 4–19 illustrates the same program using full segment definitions. Full-segment definitions are also used with the Borland and Microsoft C>C+ + environments for procedures developed in assembly language. The program in Example 4–19 appears longer than the one pictured in Example 4–18, but it is more structured than the model method of setting up a program. The first segment defined is the STACK_SEG, which is clearly delineated with the SEG- MENT and ENDS directives. Within these directives, a DW 100 DUP (?) sets aside 100H words for the stack segment. Because the word STACK appears next to SEGMENT, the assembler and linker automatically load both the stack segment register (SS) and stack pointer (SP).

Data Movement Instructions-0140

Next, the data are defined in the DATA_SEG. Here, two arrays of data appear as LISTA and LISTB. Each array contains 100 bytes of space for the program. The names of the segments in this program can be changed to any name. Always include the group name ‘DATA’, so that the Microsoft program CodeView can be effectively used to symbolically debug this software. CodeView is a part of the MASM package used to debug software. To access CodeView, type CV, followed by the file name at the DOS command line; if operating from Programmer’s Work Bench, select Debug under the Run menu. If the group name is not placed in a program, CodeView can still be used to debug a program, but the program will not be debugged in symbolic form. Other group names such as ‘STACK’, ‘CODE’, and so forth are listed in Appendix A. You must at least place the word ‘CODE’ next to the code segment SEGMENT statement if you want to view the program symbolically in CodeView.

The CODE_SEG is organized as a far procedure because most software is procedure- oriented. Before the program begins, the code segment contains the ASSUME statement. The ASSUME statement tells the assembler and linker that the name used for the code segment (CS) is CODE_SEG; it also tells the assembler and linker that the data segment is DATA_SEG and the stack segment is STACK_SEG. Notice that the group name ‘CODE’ is used for the code segment for use by CodeView. Other group names appear in Appendix A with the models.

After the program loads both the extra segment register and data segment register with the location of the data segment, it transfers 100 bytes from LISTA to LISTB. Following this is a sequence of two instructions that return control back to DOS (the disk operating system). Note that the program loader does not automatically initialize DS and ES. These registers must be loaded with the desired segment addresses in the program.

The last statement in the program is END MAIN. The END statement indicates the end of the program and the location of the first instruction executed. Here, we want the machine to exe- cute the main procedure so the MAIN label follows the END directive.

In the 80386 and above, an additional directive is found attached to the code segment. The USE16 or USE32 directive tells the assembler to use either the 16- or 32-bit instruction modes for the microprocessor. Software developed for the DOS environment must use the USE16 directive for the 80386 through the Core2 program to function correctly because MASM assumes that all segments are 32 bits and all instruction modes are 32 bits by default.

A Sample Program

Example 4–20 provides a sample program, using full-segment definitions, that reads a character from the keyboard and displays it on the CRT screen. Although this program is trivial, it illus- trates a complete workable program that functions on any personal computer using DOS, from the earliest 8088-based system to the latest Core2-based system. This program also illustrates the use of a few DOS function calls. (Appendix A lists the DOS function calls with their parameters.) The BIOS function calls allow the use of the keyboard, printer, disk drives, and everything else that is available in your computer system.

This example program uses only a code segment because there is no data. A stack segment should appear, but it has been left out because DOS automatically allocates a l28-byte stack for all programs. The only time that the stack is used in this example is for the INT 21H instructions that call a procedure in DOS. Note that when this program is linked, the linker signals that no stack segment is present. This warning may be ignored in this example because the stack is fewer than 128 bytes.

Notice that the entire program is placed into a far procedure called MAIN. It is good programming practice to write all software in procedural form, which allows the program to be used as a procedure at some future time if necessary. It is also fairly important to document register use and any parameters required for the program in the program header, which is a section of comments that appear at the start of the program.

The program uses DOS functions 06H and 4CH. The function number is placed in AH before the INT 21H instruction executes. The 06H function reads the keyboard if DL = 0FFH, or displays the ASCII contents of DL if it is not 0FFH. Upon close examination, the first section of the program moves 06H into AH and 0FFH into DL, so that a key is read from the keyboard. The INT 21H tests the keyboard; if no key is typed, it returns equal. The JE instruction tests the equal condition and jumps to MAIN if no key is typed.

When a key is typed, the program continues to the next step, which compares the contents of AL with an @ symbol. Upon return from the INT 21H, the ASCII character of the typed key is found in AL. In this program, if an @ symbol is typed, the program ends. If the @ symbol is not typed, the program continues by displaying the character typed on the keyboard with the next INT 21H instruction.

The second INT 21H instruction moves the ASCII character into DL so it can be displayed on the CRT screen. After displaying the character, a JMP executes. This causes the program to continue at MAIN, where it repeats reading a key.

If the @ symbol is typed, the program continues at MAIN1, where it executes the DOS function code number 4CH. This causes the program to return to the DOS prompt so that the computer can be used for other tasks.

More information about the assembler and its application appears in Appendix A and in the next several chapters. Appendix A provides a complete overview of the assembler, linker, and DOS functions. It also provides a list of the BIOS (basic I/O system) functions. The information provided in the following chapters clarifies how to use the assembler for certain tasks at different levels of the text.

Data Movement Instructions-0141

Example 4–21 shows the program listed in Example 4–20, except models are used instead of full-segment descriptions. Please compare the two programs to determine the differences. Notice how much shorter and cleaner looking the models can make a program.

 

DATA MOVEMENT INSTRUCTIONS:MISCELLANEOUS DATA TRANSFER INSTRUCTIONS.

MISCELLANEOUS DATA TRANSFER INSTRUCTIONS

Don’t be fooled by the term miscellaneous; these instructions are used in programs. The data transfer instructions detailed in this section are XCHG, LAHF, SAHF, XLAT, IN, OUT, BSWAP, MOVSX, MOVZX, and CMOV. Because the miscellaneous instructions are not used as often as a MOV instruction, they have been grouped together and presented in this section.

XCHG

The XCHG (exchange) instruction exchanges the contents of a register with the contents of any other register or memory location. The XCHG instruction cannot exchange segment registers or memory-to-memory data. Exchanges are byte-, word-, or doubleword-sized (80386 and above), and they use any addressing mode discussed in Chapter 3, except immediate addressing. Table 4–17 shows some examples of the XCHG instruction. In the 64-bit mode, data sizes may also be 64 bits for the exchange instruction.

The XCHG instruction, using the 16-bit AX register with another 16-bit register, is the most efficient exchange. This instruction occupies 1 byte of memory. Other XCHG instructions require 2 or more bytes of memory, depending on the addressing mode selected.

When using a memory-addressing mode and the assembler, it doesn’t matter which operand addresses memory. The XCHG AL,[DI] instruction is identical to the XCHG [DI],AL instruction, as far as the assembler is concerned.

If the 80386 through the Core2 microprocessor is available, the XCHG instruction can exchange doubleword data. For example, the XCHG EAX,EBX instruction exchanges the con- tents of the EAX register with the EBX register.

LAHF and SAHF

The LAHF and SAHF instructions are seldom used because they were designed as bridge instructions. These instructions allowed 8085 (an early 8-bit microprocessor) software to be translated into 8086 software by a translation program. Because any software that required translation was completed many years ago, these instructions have little application today. The LAHF instruction transfers the rightmost 8 bits of the flag register into the AH register. The SAHF instruction transfers the AH register into the rightmost 8 bits of the flag register.

At times, the SAHF instruction may find some application with the numeric coprocessor. The numeric coprocessor contains a status register that is copied into the AX register with the FSTSW AX instruction. The SAHF instruction is then used to copy from AH into the flag register. The flags are then tested for some of the conditions of the numeric coprocessor. This is detailed in Chapter 14, which explains the operation and programming of the numeric coprocessor. Because LAHF and LAFH are legacy instructions, they do not function in the 64-bit mode and are invalid instructions.

Data Movement Instructions-0123Data Movement Instructions-0124

XLAT

The XLAT (translate) instruction converts the contents of the AL register into a number stored in a memory table. This instruction performs the direct table lookup technique often used to convert one code to another. An XLAT instruction first adds the contents of AL to BX to form a memory address within the data segment. It then copies the contents of this address into AL. This is the only instruction that adds an 8-bit number to a l6-bit number.

Suppose that a 7-segment LED display lookup table is stored in memory at address TABLE. The XLAT instruction then uses the lookup table to translate the BCD number in AL to a 7-segment code in AL. Example 4–11 provides a sequence of instructions that converts from a BCD code to a 7-segment code. Figure 4–19 shows the operation of this example program if TABLE = 1000H, DS = 1000H, and the initial value of AL = 05H 15 BCD2. After the translation, AL = 6DH.

Data Movement Instructions-0125

IN and OUT

Table 4–18 lists the forms of the IN and OUT instructions, which perform I/O operations. Notice that the contents of AL, AX, or EAX are transferred only between the I/O device and the micro- processor. An IN instruction transfers data from an external I/O device into AL, AX, or EAX; an OUT transfers data from AL, AX, or EAX to an external I/O device. (Note that only the 80386 and above contain EAX.)

Two forms of I/O device (port) addressing exist for IN and OUT: fixed port and variable port. Fixed-port addressing allows data transfer between AL, AX, or EAX using an 8-bit I/O port

Data Movement Instructions-0126

address. It is called fixed-port addressing because the port number follows the instruction’s opcode, just as it did with immediate addressing. Often, instructions are stored in ROM. A fixed- port instruction stored in ROM has its port number permanently fixed because of the nature of read-only memory. A fixed-port address stored in RAM can be modified, but such a modification does not conform to good programming practices.

The port address appears on the address bus during an I/O operation. For the 8-bit fixed-port I/O instructions, the 8-bit port address is zero-extended into a 16-bit address. For example, if the IN AL,6AH instruction executes, data from I/O address 6AH are input to AL. The address appears as a 16-bit 006AH on pins A0–A15 of the address bus. Address bus bits A16–A19 (8086/8088), A16–A23 (80286/80386SX), A16–A24 (80386SL/80386SLC/ 80386EX), or A16–A31 (80386–Core2) are undefined for an IN or OUT instruction. Note that Intel reserves the last 16 I/O ports (FFF0H–FFFFH) for use with some of its peripheral components.

Variable-port addressing allows data transfers between AL, AX, or EAX and a 16-bit port address. It is called variable-port addressing because the I/O port number is stored in register DX, which can be changed (varied) during the execution of a program. The 16-bit I/O port address appears on the address bus pin connections A0–A15. The IBM PC uses a 16-bit port address to access its I/O space. The ISA bus I/O space for a PC is located at I/O port 0000H–03FFH. Note that PCI bus cards may use I/O addresses above 03FFH.

Figure 4–20 illustrates the execution of the OUT 19H,AX instruction, which transfers the contents of AX to I/O port 19H. Notice that the I/O port number appears as a 0019H on the 16-bit address bus and that the data from AX appears on the data bus of the microproces- sor. The system control signal IOWC (I/O write control) is a logic zero to enable the I/O device.

A short program that clicks the speaker in the personal computer appears in Example 4–12. The speaker (in DOS only) is controlled by accessing I/O port 61H. If the rightmost 2 bits of this port are set (11) and then cleared (00), a click is heard on the speaker. Note that this program uses a logical OR instruction to set these 2 bits and a logical AND instruction to clear them. These logic operation instructions are described in Chapter 5. The MOV CX,8000H instruction, followed by the LOOP L1 instruction, is used as a time delay. If the count is increased, the click will become longer; if shortened, the click will become shorter. To obtain a series of clicks that can be heard, the program must be modified to repeat many times.

Data Movement Instructions-0127

MOVSX and MOVZX

The MOVSX (move and sign-extend) and MOVZX (move and zero-extend) instructions are found in the 80386–Pentium 4 instruction sets. These instructions move data, and at the same time either sign- or zero-extend it. Table 4–19 illustrates these instructions with several examples of each.

When a number is zero-extended, the most significant part fills with zeros. For example, if an 8-bit 34H is zero-extended into a 16-bit number, it becomes 0034H. Zero-extension is often used to convert unsigned 8- or 16-bit numbers into unsigned 16- or 32-bit numbers by using the MOVZX instruction.

A number is sign-extended when its sign-bit is copied into the most significant part. For example, if an 8-bit 84H is sign-extended into a 16-bit number, it becomes FF84H. The sign-bit of an 84H is a 1, which is copied into the most significant part of the sign-extended result. Sign- extension is most often used to convert 8- or 16-bit signed numbers into 16- or 32-bit signed numbers by using the MOVSX instruction.

BSWAP

The BSWAP (byte swap) instruction is available only in the 80486–Pentium 4 microprocessors. This instruction takes the contents of any 32-bit register and swaps the first byte with the fourth, and the second with the third. For example, the BSWAP EAX instruction with

Data Movement Instructions-0128

EAX = 00112233H swaps bytes in EAX, resulting in EAX = 33221100H. Notice that the order of all 4 bytes is reversed by this instruction. This instruction is used to convert data between the big and little endian forms. In 64-bit operation for the Pentium 4, all 8 bytes in the selected operand are swapped.

CMOV

The CMOV (conditional move) class of instruction is new to the Pentium Pro–Core2 instruction sets. There are many variations of the CMOV instruction. Table 4–20 lists these variations

Data Movement Instructions-0129Data Movement Instructions-0130

of CMOV. These instructions move the data only if the condition is true. For example, the CMOVZ instruction moves data only if the result from some prior instruction was a zero. The destination is limited to only a 16- or 32-bit register, but the source can be a 16- or 32-bit register or memory location.

Because this is a new instruction, you cannot use it with the assembler unless the .686 switch is added to the program.

 

DATA MOVEMENT INSTRUCTIONS:SEGMENT OVERRIDE PREFIX.

SEGMENT OVERRIDE PREFIX

The segment override prefix, which may be added to almost any instruction in any memory- addressing mode, allows the programmer to deviate from the default segment. The segment over- ride prefix is an additional byte that appends the front of an instruction to select an alternate segment register. About the only instructions that cannot be prefixed are the jump and call instructions that must use the code segment register for address generation. The segment override is also used to select the FS and GS segments in the 80386 through the Core2 microprocessors.

For example, the MOV AX,[DI] instruction accesses data within the data segment by default. If required by a program, this can be changed by prefixing the instruction. Suppose that the data are in the extra segment instead of in the data segment. This instruction addresses the extra segment if changed to MOV AX,ES:[DI].

Table 4–21 shows some altered instructions that address different memory segments that are different from normal. Each time an instruction is prefixed with a segment override prefix, the instruction becomes 1 byte longer. Although this is not a serious change to the length of the instruction, it does add to the instruction’s execution time. It is usually customary to limit the use of the segment override prefix and remain in the default segments so that shorter and more efficient software is written.

 

DATA MOVEMENT INSTRUCTIONS:STRING DATA TRANSFERS

STRING DATA TRANSFERS

There are five string data transfer instructions: LODS, STOS, MOVS, INS, and OUTS. Each string instruction allows data transfers that are either a single byte, word, or doubleword (or if repeated, a block of bytes, words, or doublewords). Before the string instructions are presented, the operation of the D flag-bit (direction), DI, and SI must be understood as they apply to the string instructions. In the 64-bit mode of the Pentium 4 and Core2, quadwords are also used with the string instructions such as LODSQ.

The Direction Flag

The direction flag (D, located in the flag register) selects the auto-increment 1D = 02 or the auto-decrement 1D = 12 operation for the DI and SI registers during string operations. The direction flag is used only with the string instructions. The CLD instruction clears the D flag 1D = 02 and the STD instruction sets it 1D = 12. Therefore, the CLD instruction selects the auto-increment mode 1D = 02 and STD selects the auto-decrement mode 1D = 12.

Whenever a string instruction transfers a byte, the contents of DI and/or SI are incremented or decremented by 1. If a word is transferred, the contents of DI and/or SI are incremented or decremented by 2. Doubleword transfers cause DI and/or SI to increment or decrement by 4. Only the actual registers used by the string instruction are incremented or decremented. For example, the STOSB instruction uses the DI register to address a memory location. When STOSB executes, only the DI register is incremented or decremented without affecting SI. The same is true of the LODSB instruction, which uses the SI register to address memory data. A LODSB instruction will only increment or decrement SI without affecting DI.

DI and SI

During the execution of a string instruction, memory accesses occur through either or both of the DI and SI registers. The DI offset address accesses data in the extra segment for all string instructions that use it. The SI offset address accesses data, by default, in the data segment. The segment assignment of SI may be changed with a segment override prefix, as described later in this chapter. The DI segment assignment is always in the extra segment when a string instruction executes. This assignment cannot be changed. The reason that one pointer addresses data in the extra segment and the other in the data segment is so that the MOVS instruction can move 64K bytes of data from one segment of memory to another.

When operating in the 32-bit mode in the 80386 microprocessor or above, the EDI and ESI registers are used in place of DI and SI. This allows string using any memory location in the entire 4G-byte protected mode address space of the microprocessor.

LODS

The LODS instruction loads AL, AX, or EAX with data stored at the data segment offset address indexed by the SI register. (Note that only the 80386 and above use EAX.) After loading AL with

Data Movement Instructions-0112

a byte, AX with a word, or EAX with a doubleword, the contents of SI increment, if D = 0 or decrement, if D = 1. A 1 is added to or subtracted from SI for a byte-sized LODS, a 2 is added or subtracted for a word-sized LODS, and a 4 is added or subtracted for a doubleword-sized LODS. Table 4–11 lists the permissible forms of the LODS instruction. The LODSB (loads a byte) instruction causes a byte to be loaded into AL, the LODSW (loads a word) instruction causes a word to be loaded into AX, and the LODSD (loads a doubleword) instruction causes a double- word to be loaded into EAX. Although rare, as an alternative to LODSB, LODSW, LODSD, and LODSQ, the LODS instruction may be followed by a byte-, word- or doubleword-sized operand to select a byte, word, or doubleword transfer. Operands are often defined as bytes with DB, as words with DW, and as doublewords with DD. The DB pseudo-operation defines byte(s), the DW pseudo-operation defines word(s), and the DD pseudo-operations define doubleword(s).

Figure 4–18 shows the effect of executing the LODSW instruction if the D flag 0, SI 1000H, and DS 1000H. Here, a 16-bit number stored at memory locations 11000H and 1l001H moves into AX. Because D 0 and this is a word transfer, the contents of SI incre- ment by 2 after AX loads with memory data.

STOS

The STOS instruction stores AL, AX, or EAX at the extra segment memory location addressed by the DI register. (Note that only the 80386–Core2 use EAX and doublewords.) Table 4–12 lists all forms of the STOS instruction. As with LODS, a STOS instruction may be appended with a B, W, or D for byte, word, or doubleword transfers. The STOSB (stores a byte) instruction stores the byte in AL at the extra segment memory location addressed by DI. The STOSW (stores a word) instruction stores AX in the extra segment memory location addressed by DI. A doubleword is stored in the extra segment location addressed by DI with the STOSD (stores a doubleword) instruction. After the byte (AL), word (AX), or doubleword (EAX) is stored, the contents of DI increment or decrement.

STOS with a REP. The repeat prefix (REP) is added to any string data transfer instruction, except the LODS instruction. It doesn’t make any sense to perform a repeated LODS operation. The REP prefix causes CX to decrement by 1 each time the string instruction executes. After CX decrements, the string instruction repeats. If CX reaches a value of 0, the instruction terminates and the program continues with the next sequential instruction. Thus, if CX is loaded with 100 and a REP STOSB instruction executes, the microprocessor automatically repeats the STOSB instruction 100 times. Because the DI register is automatically incremented or decremented after each datum is stored, this instruction stores the contents of AL in a block of memory instead of a single byte of memory. In the Pentium 4 operated in 64-bit mode, the RCX register is used with the REP prefix.

Data Movement Instructions-0113

Suppose that the STOSW instruction is used to clear an area of memory called Buffer using a count called Count and the program is to function call ClearBuffer in the C+ + envi- ronment using the inline assembler. (See Example 4–5.) Note that both the Count and Buffer address are transferred to the function. The REP STOSW instruction clears the memory buffer called Buffer. Notice that Buffer is a pointer to the actual buffer that is cleared by this function.

Data Movement Instructions-0114

Data Movement Instructions-0115

MOVS

One of the more useful string data transfer instructions is MOVS, because it transfers data from one memory location to another. This is the only memory-to-memory transfer allowed in the 8086–Pentium 4 microprocessors. The MOVS instruction transfers a byte, word, or doubleword from the data segment location addressed by SI to the extra segment location addressed by SI. As with the other string instructions, the pointers then are incremented or decremented, as dictated by the direction flag. Table 4–14 lists all the permissible forms of the MOVS instruction. Note that only the source operand (SI), located in the data segment, may be overridden so that another segment may be used. The destination operand (DI) must always be located in the extra segment.

It is often necessary to transfer the contents of one area of memory to another. Suppose that we have two blocks of doubleword memory, blockA and blockB, and we need to copy blockA into blockB. This can be accomplished using the MOVSD instruction as illustrated in Example 4–6, which is a C+ + language function written using the inline assembler. The function receives three pieces of information from the caller: blockSize and the addresses of blockA and blockB. Note that all data are in the data segment in a Visual C+ + program so we need to copy DS into ES, which is done using a PUSH DS followed by a POP ES. We also need to save all registers that we changed except for EAX, EBX, ECX, and EDX.

Example 4–7 shows the same function written in C+ + exclusively, so the two methods can be compared and contrasted. Example 4–8 shows the assembly language version of

Data Movement Instructions-0116Data Movement Instructions-0117

Example 4–7 for comparison to Example 4–6. Notice how much shorter the assembly language version is compared to the C+ + version generated in Example 4–8. Admittedly the C+ + version is a little easier to type, but if execution speed is important, Example 4–6 will run much faster than Example 4–7.

Data Movement Instructions-0118Data Movement Instructions-0119

INS

The INS (input string) instruction (not available on the 8086/8088 microprocessors) transfers a byte, word, or doubleword of data from an I/O device into the extra segment memory location addressed by the DI register. The I/O address is contained in the DX register. This instruction is useful for inputting a block of data from an external I/O device directly into the memory. One application transfers data from a disk drive to memory. Disk drives are often considered and interfaced as I/O devices in a computer system.

As with the prior string instructions, there are three basic forms of the INS. The INSB instruction inputs data from an 8-bit I/O device and stores it in the byte-sized memory location indexed by SI. The INSW instruction inputs 16-bit I/O data and stores it in a word-sized memory location. The INSD instruction inputs a doubleword. These instructions can be repeated using the REP prefix, which allows an entire block of input data to be stored in the memory from an I/O device. Table 4–15 lists the various forms of the INS instruction. Note that in the 64-bit mode there is no 64-bit input, but the memory address is 64 bits and located in RDI for the INS instructions.

Data Movement Instructions-0120

Example 4–9 shows a sequence of instructions that inputs 50 bytes of data from an I/O device whose address is 03ACH and stores the data in extra segment memory array LISTS. This software assumes that data are available from the I/O device at all times. Otherwise, the software must check to see if the I/O device is ready to transfer data precluding the use of a REP prefix.

Data Movement Instructions-0121

OUTS

The OUTS (output string) instruction (not available on the 8086/8088 microprocessors) transfers a byte, word, or doubleword of data from the data segment memory location address by SI to an I/O device. The I/O device is addressed by the DX register as it is with the INS instruction. Table 4–16 shows the variations available for the OUTS instruction. In the 64-bit mode for the Pentium 4 and Core2, there is no 64-bit output, but the address in RSI is 64 bits wide.

Example 4–10 shows a short sequence of instructions that transfer data from a data segment memory array (ARRAY) to an I/O device at I/O address 3ACH. This software assumes that the I/O device is always ready for data.

Data Movement Instructions-0122

 

DATA MOVEMENT INSTRUCTIONS:LOAD-EFFECTIVE ADDRESS.

LOAD-EFFECTIVE ADDRESS

There are several load-effective address instructions in the microprocessor instruction set. The LEA instruction loads any 16-bit register with the offset address, as determined by the addressing mode selected for the instruction. The LDS and LES variations load any 16-bit register with the offset address retrieved from a memory location, and then load either DS or ES with a segment address retrieved from memory. In the 80386 and above, LFS, LGS, and LSS are added to the instruction set, and a 32-bit register can be selected to receive a 32-bit offset from memory. In the 64-bit mode for the Pentium 4, the LDS and LES instructions are invalid and not used because the segments have no function in the flat memory model. Table 4–10 lists the load-effective address instructions.

LEA

The LEA instruction loads a 16- or 32-bit register with the offset address of the data specified by the operand. As the first example in Table 4–9 shows, the operand address NUMB is loaded into register AX, not the contents of address NUMB.

By comparing LEA with MOV, we observe that LEA BX,[DI] loads the offset address specified by [DI] (contents of DI) into the BX register; MOV BX,[DI] loads the data stored at the memory location addressed by [DI] into register BX.

Earlier in the text, several examples were presented by using the OFFSET directive. The OFFSET directive performs the same function as an LEA instruction if the operand is a dis- placement. For example, the MOV BX,OFFSET LIST performs the same function as LEA BX,LIST. Both instructions load the offset address of memory location LIST into the BX register. See Example 4–3 for a short program that loads SI with the address of DATA1 and DI with the address of DATA2. It then exchanges the contents of these memory locations. Note that the LEA and MOV with OFFSET instructions are both the same length (3 bytes).

Data Movement Instructions-0108

But why is the LEA instruction available if the OFFSET directive accomplishes the same task? First, OFFSET only functions with simple operands such as LIST. It may not be used for an operand such as [DI], LIST [SI], and so on. The OFFSET directive is more efficient than the LEA instruction for simple operands. It takes the microprocessor longer to execute the LEA BX,LIST instruction than the MOV BX,OFFSET LIST. The 80486 microprocessor, for example, requires two clocks to execute the LEA BX,LIST instruction and only one clock to execute MOV BX,OFFSET LIST. The reason that the MOV BX,OFFSET LIST instruction executes faster is because the assembler calculates the offset address of LIST, whereas the microprocessor calculates the address for the LEA instruction. The MOV BX,OFFSET LIST instruction is actually assembled as a move immediate instruction and is more efficient.

Suppose that the microprocessor executes an LEA BX,[DI] instruction and DI contains a 1000H. Because DI contains the offset address, the microprocessor transfers a copy of DI into BX. A MOV BX,DI instruction performs this task in less time and is often preferred to the LEA BX,[DI] instruction.

Another example is LEA SI,[BX + DI]. This instruction adds BX to DI and stores the sum in the SI register. The sum generated by this instruction is a modulo-64K sum. (A modulo-64K sum drops any carry out of the 16-bit result.) If BX = 1000H and DI = 2000H, the offset address moved into SI is 3000H. If BX = 1000H and DI = FF00H, the offset address is 0F00H instead of 10F00H. Notice that the second result is a modulo-64K sum of 0F00H.

LDS, LES, LFS, LGS, and LSS

The LDS, LES, LFS, LGS, and LSS instructions load any 16-bit or 32-bit register with an offset address, and the DS, ES, FS, GS, or SS segment register with a segment address. These instructions use any of the memory-addressing modes to access a 32-bit or 48-bit section of memory that contains both the segment and offset address. The 32-bit section of memory contains a 16- bit offset and segment address, while the 48-bit section contains a 32-bit offset and a segment address. These instructions may not use the register addressing mode 1MOD = 112. Note that the LFS, LGS, and LSS instructions are only available on 80386 and above, as are the 32-bit registers.

Figure 4–17 illustrates an example LDS BX,[DI] instruction. This instruction transfers the 32-bit number, addressed by DI in the data segment, into the BX and DS registers. The LDS, LES, LFS, LGS, and LSS instructions obtain a new far address from memory. The offset address appears first, followed by the segment address. This format is used for storing all 32-bit memory addresses.

A far address can be stored in memory by the assembler. For example, the ADDR DD FAR PTR FROG instruction stores the offset and segment address (far address) of FROG in 32 bits of memory at location ADDR. The DD directive tells the assembler to store a doubleword (32-bit number) in memory address ADDR.

In the 80386 and above, an LDS EBX,[DI] instruction loads EBX from the 4-byte section of memory addressed by DI in the data segment. Following this 4-byte offset is a word that is loaded to the DS register. Notice that instead of addressing a 32-bit section of memory, the 80386 and above address a 48-bit section of the memory whenever a 32-bit offset address is loaded to a 32-bit register. The first 4 bytes contain the offset value loaded to the 32-bit register and the last 2 bytes contain the segment address.

The most useful of the load instructions is the LSS instruction. Example 4–4 shows a short program that creates a new stack area after saving the address of the old stack area. After executing some dummy instructions, the old stack area is reactivated by loading both SS and SP with the LSS instruction. Note that the CLI (disable interrupt) and STI (enable interrupt) instructions must be included to disable interrupts. (This topic is discussed near the end of this chapter.) Because the LSS instruction functions in the 80386 or above, the .386 statement appears after

Data Movement Instructions-0109

the .MODEL statement to select the 80386 microprocessor. Notice how the WORD PTR directive is used to override the doubleword (DD) definition for the old stack memory location. If an 80386 or newer microprocessor is in use, it is suggested that the .386 switch be used to develop software for the 80386 microprocessor. This is true even if the microprocessor is a Pentium, Pentium Pro, Pentium II, Pentium III, Pentium 4, or Core2. The reason is that the 80486–Core2 microprocessors add only a few additional instructions to the 80386 instruction set, which are seldom used in software development. If the need arises to use any of the CMPXCHG, CMPX- CHG8 (new to the Pentium), XADD or BSWAP instructions, select either the .486 switch for the 80486 microprocessor of the .586 switch for the Pentium. You can even specify the Pentium II –Core2 using the .686 switch.

Data Movement Instructions-0110Data Movement Instructions-0111

 

DATA MOVEMENT INSTRUCTIONS:PUSH/POP

PUSH/POP

The PUSH and POP instructions are important instructions that store and retrieve data from the LIFO (last-in, first-out) stack memory. The microprocessor has six forms of the PUSH and POP instructions: register, memory, immediate, segment register, flags, and all registers. The PUSH and POP immediate and the PUSHA and POPA (all registers) forms are not avail- able in the earlier 8086/8088 microprocessors, but are available to the 80286 through the Core2.

Register addressing allows the contents of any 16-bit register to be transferred to or from the stack. In the 80386 and above, the 32-bit extended registers and flags (EFLAGS) can also be pushed or popped from the stack. Memory-addressing PUSH and POP instructions store the contents of a 16-bit memory location (or 32 bits in the 80386 and above) on the stack or stack data into a memory location. Immediate addressing allows immediate data to be pushed onto the stack, but not popped off the stack. Segment register addressing allows the contents of any segment register to be pushed onto the stack or removed from the stack (ES may be pushed, but data from the stack may never be popped into ES). The flags may be pushed or popped from that stack, and the contents of all the registers may be pushed or popped.

PUSH

The 8086–80286 PUSH instruction always transfers 2 bytes of data to the stack; the 80386 and above transfer 2 or 4 bytes, depending on the register or size of the memory location. The source of the data may be any internal 16- or 32-bit register, immediate data, any seg- ment register, or any 2 bytes of memory data. There is also a PUSHA instruction that copies the contents of the internal register set, except the segment registers, to the stack. The PUSHA (push all) instruction copies the registers to the stack in the following order: AX, CX, DX, BX, SP, BP, SI, and DI. The value for SP that is pushed onto the stack is whatever it was before the PUSHA instruction executed. The PUSHF (push flags) instruction copies the contents of the flag register to the stack. The PUSHAD and POPAD instructions push and pop the contents of the 32-bit register set found in the 80386 through the Pentium 4. The PUSHA and POPA instructions do not function in the 64-bit mode of operation for the Pentium 4.

Whenever data are pushed onto the stack, the first (most-significant) data byte moves to the stack segment memory location addressed by SP – 1. The second (least-significant) data byte moves into the stack segment memory location addressed by SP – 2. After the data are stored by a PUSH, the contents of the SP register decrement by 2. The same is true for a doubleword push, except that 4 bytes are moved to the stack memory (most-significant byte first), after which the stack pointer decrements by 4. Figure 4–13 shows the operation of the PUSH AX instruction. This instruction copies the contents of AX onto the stack where address

SS:3SP – 14 = AH, SS:3SP – 24 = AL , and afterwards SP = SP – 2. In 64-bit mode, 8 bytes of the stack are used to store the number pushed onto the stack.

The PUSHA instruction pushes all the internal 16-bit registers onto the stack, as illustrated in Figure 4–14. This instruction requires 16 bytes of stack memory space to store all eight 16-bit registers. After all registers are pushed, the contents of the SP register are decremented by 16. The PUSHA instruction is very useful when the entire register set (microprocessor environment) of the 80286 and above must be saved during a task. The PUSHAD instruction places the 32-bit register set on the stack in the 80386 through the Core2. PUSHAD requires 32 bytes of stack storage space.

Data Movement Instructions-0103Data Movement Instructions-0104

stack, assembles as 6A08H. The PUSH 1000H instruction assembles as 680010H. Another example of PUSH immediate is the PUSH ‘A’ instruction, which pushes a 0041H onto the stack. Here, the 41H is the ASCII code for the letter A.

Table 4–8 lists the forms of the PUSH instruction that include PUSHA and PUSHF. Notice how the instruction set is used to specify different data sizes with the assembler.

POP

The POP instruction performs the inverse operation of a PUSH instruction. The POP instruction removes data from the stack and places it into the target 16-bit register, segment register, or a 16- bit memory location. In the 80386 and above, a POP can also remove 32-bit data from the stack and use a 32-bit address. The POP instruction is not available as an immediate POP. The POPF (pop flags) instruction removes a 16-bit number from the stack and places it into the flag register; the POPFD removes a 32-bit number from the stack and places it into the extended flag register. The POPA (pop all) instruction removes 16 bytes of data from the stack and places them into the following registers, in the order shown: DI, SI, BP, SP, BX, DX, CX, and AX. This is the reverse order from the way they were placed on the stack by the PUSHA instruction, causing the same data to return to the same registers. In the 80386 and above, a POPAD instruction reloads the 32-bit registers from the stack.

Suppose that a POP BX instruction executes. The first byte of data removed from the stack (the memory location addressed by SP in the stack segment) moves into register BL. The second byte is removed from stack segment memory location SP + 1 and is placed into register BH. After both bytes are removed from the stack, the SP register is incremented by 2. Figure 4–15 shows how the POP BX instruction removes data from the stack and places them into register BX. The opcodes used for the POP instruction and all of its variations appear in Table 4–9.

Note that a POP CS instruction is not a valid instruction in the instruction set. If a POP CS instruction executes, only a portion of the address (CS) of the next instruction changes. This makes the POP CS instruction unpredictable and therefore not allowed.

Initializing the Stack

When the stack area is initialized, load both the stack segment (SS) register and the stack pointer (SP) register. It is normal to designate an area of memory as the stack segment by loading SS with the bottom location of the stack segment.

Data Movement Instructions-0105

For example, if the stack segment is to reside in memory locations 10000H–1FFFFH, load SS with a 1000H. (Recall that the rightmost end of the stack segment register is appended with a 0H for real mode addressing.) To start the stack at the top of this 64K-byte stack segment, the stack pointer (SP) is loaded with a 0000H. Likewise, to address the top of the stack at location 10FFFH, use a value of 1000H in SP. Figure 4–16 shows how this value causes data to be pushed onto the top of the stack segment with a PUSH CX instruction. Remember that all segments are cyclic in nature—that is, the top location of a segment is contiguous with the bottom location of the segment.

In assembly language, a stack segment is set up as illustrated in Example 4–1. The first statement identifies the start of the stack segment and the last statement identifies the end of the stack segment. The assembler and linker programs place the correct stack segment address in SS and the length of the segment (top of the stack) into SP. There is no need to load these registers in your program unless you wish to change the initial values for some reason.

Data Movement Instructions-0106

An alternative method for defining the stack segment is used with one of the memory models for the MASM assembler only (refer to Appendix A). Other assemblers do not use models; if they do, the models are not exactly the same as with MASM. Here, the .STACK statement, fol- lowed by the number of bytes allocated to the stack, defines the stack area (see Example 4–2). The function is identical to Example 4–1. The .STACK statement also initializes both SS and SP. Note that this text uses memory models that are designed for the Microsoft Macro Assembler program MASM.

Data Movement Instructions-0107

If the stack is not specified by using either method, a warning will appear when the pro- gram is linked. The warning may be ignored if the stack size is 128 bytes or fewer. The system automatically assigns (through DOS) at least 128 bytes of memory to the stack. This memory section is located in the program segment prefix (PSP), which is appended to the beginning of each program file. If you use more memory for the stack, you will erase information in the PSP that is critical to the operation of your program and the computer. This error often causes the computer program to crash. If the TINY memory model is used, the stack is automatically located at the very end of the segment, which allows for a larger stack area.

 

DATA MOVEMENT INSTRUCTIONS:MOV REVISITED

Data Movement Instructions

INTRODUCTION

This chapter concentrates on the data movement instructions. The data movement instructions include MOV, MOVSX, MOVZX, PUSH, POP, BSWAP, XCHG, XLAT, IN, OUT, LEA, LDS,LES, LFS, LGS, LSS, LAHF, SAHF, and the string instructions MOVS, LODS, STOS, INS, and OUTS. The latest data transfer instruction implemented on the Pentium Pro and above is the CMOV (conditional move) instruction. The data movement instructions are presented first because they are more commonly used in programs and are easy to understand.

The microprocessor requires an assembler program, which generates machine language, because machine language instructions are too complex to efficiently generate by hand. This chapter describes the assembly language syntax and some of its directives. [This text assumes that the user is developing software on an IBM personal computer or clone. It is recommended that the Microsoft MACRO assembler (MASM) be used as the development tool, but the Intel Assembler (ASM), Borland Turbo assembler (TASM), or similar software function equally as well. The most recent version of TASM completely emulates the MASM program. This text presents information that functions with the Microsoft MASM assembler, but most programs assemble without modification with other assemblers. Appendix A explains the Microsoft assembler and provides detail on the linker program.] As a more modern alternative, the Visual C++ Express compiler and its inline assembler program may also be used as a development system. Both are explained in detail in the text.

CHAPTER OBJECTIVES

Upon completion of this chapter, you will be able to:

1. Explain the operation of each data movement instruction with applicable addressing modes.

2. Explain the purposes of the assembly language pseudo-operations and key words such as ALIGN, ASSUME, DB, DD, DW, END, ENDS, ENDP, EQU, .MODEL, OFFSET, ORG, PROC, PTR, SEGMENT, USEI6, USE32, and USES.

3. Select the appropriate assembly language instruction to accomplish a specific data move- ment task.

4. Determine the symbolic opcode, source, destination, and addressing mode for a hexadecimal machine language instruction.

5. Use the assembler to set up a data segment, stack segment, and code segment.

6. Show how to set up a procedure using PROC and ENDP.

7. Explain the difference between memory models and full-segment definitions for the MASM assembler.

8. Use the Visual C++ online assembler to perform data movement tasks.

MOV REVISITED

The MOV instruction, introduced in Chapter 3, explains the diversity of 8086–Core2 addressing modes. In this chapter, the MOV instruction introduces the machine language instructions available with various addressing modes and instructions. Machine code is introduced because it may occa- sionally be necessary to interpret machine language programs generated by an assembler or inline assembler of Visual C++ . Interpretation of the machine’s native language (machine language) allows debugging or modification at the machine language level. Occasionally, machine language patches are made by using the DEBUG program available with DOS and also in Visual C++ for Windows, which requires some knowledge of machine language. Conversion between machine and assembly language instructions is illustrated in Appendix B.

Machine Language

Machine language is the native binary code that the microprocessor understands and uses as its instructions to control its operation. Machine language instructions for the 8086 through the Core2 vary in length from 1 to as many as 13 bytes. Although machine language appears complex, there is order to this microprocessor’s machine language. There are well over 100,000 variations of machine language instructions, meaning that there is no complete list of these variations. Because of this, some binary bits in a machine language instruction are given, and the remaining bits are determined for each variation of the instruction.

Instructions for the 8086 through the 80286 are 16-bit mode instructions that take the form found in Figure 4–1(a). The 16-bit mode instructions are compatible with the 80386 and above if they are programmed to operate in the 16-bit instruction mode, but they may be prefixed, as shown in Figure 4–1(b). The 80386 and above assume that all instructions are 16-bit mode instructions when the machine is operated in the real mode (DOS). In the protected mode (Windows), the upper byte of the descriptor contains the D-bit that selects either the 16- or 32-bit instruction mode. At present, only Windows 95 through Windows XP and Linux operate in the 32-bit instruction mode. The 32-bit mode instructions are in the form shown in Figure 4–1(b).

Data Movement Instructions-0087Data Movement Instructions-0088

These instructions occur in the 16-bit instruction mode by the use of prefixes, which are explained later in this chapter.

The first 2 bytes of the 32-bit instruction mode format are called override prefixes because they are not always present. The first modifies the size of the operand address used by the instruction and the second modifies the register size. If the 80386 through the Pentium 4 operate as 16-bit instruction mode machines (real or protected mode) and a 32-bit register is used, the register-size prefix (66H) is appended to the front of the instruction. If operated in the 32-bit instruction mode (protected mode only) and a 32-bit register is used, the register-size prefix is absent. If a 16-bit register appears in an instruction in the 32-bit instruction mode, the register-size 16-bit instruction mode, the register-size prefix is present to select a l6-bit register. The address size-prefix (67H) is used in a similar fashion, as explained later in this chapter. The prefixes toggle the size of the reg- ister and operand address from l6-bit to 32-bit or from 32-bit to l6-bit for the prefixed instruction. Note that the l6-bit instruction mode uses 8- and l6-bit registers and addressing modes, while the 32-bit instruction mode uses 8- and 32-bit registers and addressing modes by default. The prefixes override these defaults so that a 32-bit register can be used in the l6-bit mode or a l6-bit register can be used in the 32-bit mode. The mode of operation (16 or 32 bits) should be selected to func- tion with the current application. If 8- and 32-bit data pervade the application, the 32-bit mode should be selected; likewise, if 8- and l6-bit data pervade, the l6-bit mode should be selected. Normally, mode selection is a function of the operating system. (Remember that DOS can operate only in the l6-bit mode, where Windows can operate in both modes.)

The Opcode. The opcode selects the operation (addition, subtraction, move, and so on) that is performed by the microprocessor. The opcode is either 1 or 2 bytes long for most machine language instructions. Figure 4–2 illustrates the general form of the first opcode byte of many, but not all, machine language instructions. Here, the first 6 bits of the first byte are the binary opcode. The remaining 2 bits indicate the direction (D)—not to be confused with the instruction mode bit (16/32) or direction flag bit (used with string instructions)—of the data flow, and indi- cate whether the data are a byte or a word (W). In the 80386 and above, words and doublewords are both specified when W = 1. The instruction mode and register-size prefix (66H) determine whether W represents a word or a doubleword.

If the direction bit 1D2 = 1, data flow to the register REG field from the R/M field located in the second byte of an instruction. If the D-bit = 0 in the opcode, data flow to the R/M field from the REG field. If the W-bit = 1, the data size is a word or doubleword; if the W-bit = 0, the data size is always a byte. The W-bit appears in most instructions, while the D-bit appears mainly with the MOV and some other instructions. Refer to Figure 4–3 for the binary bit pattern of the second opcode byte (reg-mod-r/m) of many instructions. Figure 4–3 shows the location of the MOD (mode), REG (register), and R/M (register/memory) fields.

Data Movement Instructions-0089Data Movement Instructions-0090

MOD Field. The MOD field specifies the addressing mode (MOD) for the selected instruction. The MOD field selects the type of addressing and whether a displacement is present with the selected type. Table 4–1 lists the operand forms available to the MOD field for l6-bit instruction mode, unless the operand address-size override prefix (67H) appears. If the MOD field contains an 11, it selects the register-addressing mode. Register addressing uses the R/M field to specify a register instead of a memory location. If the MOD field contains a 00, 01, or 10, the R/M field selects one of the data memory-addressing modes. When MOD selects a data memory address- ing mode, it indicates that the addressing mode contains no displacement (00), an 8-bit sign- extended displacement (01), or a l6-bit displacement (10). The MOV AL,[DI] instruction is an example that contains no displacement, a MOV AL,[DI+2] instruction uses an 8-bit displacement ( +2), and a MOV AL,[DI+1000H] instruction uses a 16-bit displacement ( +1000H).

All 8-bit displacements are sign-extended into 16-bit displacements when the micro- processor executes the instruction. If the 8-bit displacement is 00H–7FH (positive), it is sign- extended to 0000H–007FH before adding to the offset address. If the 8-bit displacement is 80H–FFH (negative), it is sign-extended to FF80H–FFFFH. To sign-extend a number, its sign-bit is copied to the next higher-order byte, which generates either a 00H or an FFH in the next higher-order byte. Some assembler programs do not use the 8-bit displacements and in place default to all 16-bit displacements.

In the 80386 through the Core2 microprocessors, the MOD field may be the same as shown in Table 4–1 for 16-bit instruction mode; if the instruction mode is 32 bits, the MOD field is as it appears in Table 4–2. The MOD field is interpreted as selected by the address-size over- ride prefix or the operating mode of the microprocessor. This change in the interpretation of the MOD field and instruction supports many of the numerous additional addressing modes allowed in the 80386 through the Core2. The main difference is that when the MOD field is a 10, this causes the 16-bit displacement to become a 32-bit displacement, to allow any protected mode memory location (4G bytes) to be accessed. The 80386 and above only allow an 8- or 32-bit dis- placement when operated in the 32-bit instruction mode, unless the address-size override prefix appears. Note that if an 8-bit displacement is selected, it is sign-extended into a 32-bit displace- ment by the microprocessor.

Register Assignments. Table 4–3 lists the register assignments for the REG field and the R/M field (MOD = 11). This table contains three lists of register assignments: one is used when the W bit = 0 (bytes), and the other two are used when the W bit = 1 (words or doublewords). Note that doubleword registers are only available to the 80386 through the Core2.

Data Movement Instructions-0091Data Movement Instructions-0092

Suppose that a 2-byte instruction, 8BECH, appears in a machine language program. Because neither a 67H (operand address-size override prefix) nor a 66H (register-size override prefix) appears as the first byte, the first byte is the opcode. If the microprocessor is operated in the 16-bit instruction mode, this instruction is converted to binary and placed in the instruction format of bytes 1 and 2, as illustrated in Figure 4–4. The opcode is 100010. If you refer to Appendix B, which lists the machine language instructions, you will find that this is the opcode for a MOV instruction. Notice that both the D and W bits are a logic 1, which means that a word moves into the destination register specified in the REG field. The REG field contains a 101, indicating regis- ter BP, so the MOV instruction moves data into register BP. Because the MOD field contains a 11, the R/M field also indicates a register. Here, R>M = 100 (SP); therefore, this instruction moves data from SP into BP and is written in symbolic form as a MOV BP,SP instruction.

Suppose that a 668BE8H instruction appears in an 80386 or above, operated in the 16-bit instruction mode. The first byte (66H) is the register-size override prefix that selects 32-bit register operands for the 16-bit instruction mode. The remainder of the instruction indicates that the opcode is a MOV with a source operand of EAX and a destination operand of EBP. This instruction is a MOV EBP,EAX. The same instruction becomes a MOV BP,AX instruction in the 80386 and above if it is operated in the 32-bit instruction mode, because the register-size override prefix selects a 16-bit register. Luckily, the assembler program keeps track of the register- and address-size prefixes and the mode of operation. Recall that if the .386 switch is placed before the .MODEL statement, the 32-bit mode is selected; if it is placed after the .MODEL statement, the 16-bit mode is selected. All programs written using the inline assembler in Visual C++ are always in the 32-bit mode.

R/M Memory Addressing. If the MOD field contains a 00, 01, or 10, the R/M field takes on a new meaning. Table 4–4 lists the memory-addressing modes for the R/M field when MOD is a 00, 01, or 10 for the 16-bit instruction mode.

Data Movement Instructions-0093Data Movement Instructions-0094

All of the 16-bit addressing modes presented in Chapter 3 appear in Table 4–4. The dis- placement, discussed in Chapter 3, is defined by the MOD field. If MOD = 00 and R>M = 101, the addressing mode is [DI]. If MOD = 01 or 10, the addressing mode is [DI + 33H ], or LIST [DI + 22H] for the 16-bit instruction mode. This example uses LIST, 33H, and 22H as arbitrary values for the displacement.

Figure 4–5 illustrates the machine language version of the 16-bit instruction MOV DL,[DI] or instruction (8AI5H). This instruction is 2 bytes long and has an opcode 100010, D = 1 (to REG from R/M), W = 0 (byte), MOD = 00 (no displacement), REG = 010 (DL), and R>M = 101 ([DI]). If the instruction changes to MOV DL,3DI + 14, the MOD field changes to 01 for an 8-bit displacement, but the first 2 bytes of the instruction otherwise remain the same. The instruction now becomes 8A5501H instead of 8A15H. Notice that the 8-bit displacement appends to the first 2 bytes of the instruction to form a 3-byte instruction instead of 2 bytes. If the instruction is again changed to a MOV DL,3DI + 1000H], the machine language form becomes 8A750010H. Here, the 16-bit displacement of 1000H (coded as 0010H) appends the opcode.

Special Addressing Mode. There is a special addressing mode that does not appear in Tables 4–2, 4–3, or 4–4. It occurs whenever memory data are referenced by only the displacement mode of addressing for 16-bit instructions. Examples are the MOV [1000H],DL and MOV NUMB,DL instructions. The first instruction moves the contents of register DL into data segment memory location 1000H. The second instruction moves register DL into symbolic data segment memory location NUMB.

Whenever an instruction has only a displacement, the MOD field is always a 00 and the R/M field is always 110. As shown in the tables, the instruction contains no displacement and uses addressing mode [BP]. You cannot actually use addressing mode [BP] without a displacement in machine language. The assembler takes care of this by using an 8-bit displacement (MOD = 01)

Data Movement Instructions-0095Data Movement Instructions-0096

of 00H whenever the [BP] addressing mode appears in an instruction. This means that the [BP] addressing mode assembles as a [BP + 0], even though a [BP] is used in the instruction. The same special addressing mode is also available for the 32-bit mode.

Figure 4–6 shows the binary bit pattern required to encode the MOV [1000H],DL instruction in machine language. If the individual translating this symbolic instruction into machine language does not know about the special addressing mode, the instruction would incorrectly translate to a MOV [BP],DL instruction. Figure 4–7 shows the actual form of the MOV [BP],DL instruction. Notice that this is a 3-byte instruction with a displacement of 00H.

Data Movement Instructions-0097Data Movement Instructions-0098

32-Bit Addressing Modes. The 32-bit addressing modes found in the 80386 and above are obtained by either running these machines in the 32-bit instruction mode or in the 16-bit instruction mode by using the address-size prefix 67H. Table 4–5 shows the coding for R/M used to specify the 32-bit addressing modes. Notice that when R>M = 100, an additional byte called a scaled-index byte appears in the instruction. The scaled-index byte indicates the additional forms of scaled-index addressing that do not appear in Table 4–5. The scaled-index byte is mainly used when two registers are added to specify the memory address in an instruction. Because the scaled-index byte is added to the instruction, there are 7 bits in the opcode and 8 bits in the scaled-index byte to define. This means that a scaled-index instruction has 215 (32K) possible combinations. There are over 32,000 different variations of the MOV instruction alone in the 80386 through the Core2 microprocessors.

Figure 4–8 shows the format of the scaled-index byte as selected by a value of 100 in the R/M field of an instruction when the 80386 and above use a 32-bit address. The leftmost 2 bits select a scaling factor (multiplier) of 1 × , 2 × , 4 × , or 8 × . Note that a scaling factor of 1 × is implicit if none is used in an instruction that contains two 32-bit indirect address registers. The index and base fields both contain register numbers, as indicated in Table 4–3 for 32-bit registers.

The instruction MOV EAX,3EBX + 4*ECX4 is encoded as 67668B048BH. Notice that both the address size (67H) and register size (66H) override prefixes appear in the instruction. This coding (67668B048BH) is used when the 80386 and above microprocessors are operated in the 16-bit instruction mode for this instruction. If the microprocessor operates in the 32-bit instruction mode, both prefixes disappear and the instruction becomes an 8B048BH instruction. The use of the prefixes depends on the mode of operation of the microprocessor. Scaled-index addressing can also use a single register multiplied by a scaling factor. An example is the MOV AL,[2*ECX] instruction. The contents of the data segment location addressed by two times ECX are copied into AL.

An Immediate Instruction. Suppose that the MOV WORD PTR [BX + 1000H],1234H instruction is chosen as an example of a 16-bit instruction using immediate addressing. This instruction moves a 1234H into the word-sized memory location addressed by the sum of 1000H, BX, and

Data Movement Instructions-0099Data Movement Instructions-0100

FIGURE 4–9 A MOV WORD PTR [BX + 1000H], 1234H instruction converted to binary machine language.

DS × 10H. This 6-byte instruction uses 2 bytes for the opcode, W, MOD, and R/M fields. Two of the 6 bytes are the data of 1234H; 2 of the 6 bytes are the displacement of 1000H. Figure 4–9 shows the binary bit pattern for each byte of this instruction.

This instruction, in symbolic form, includes WORD PTR. The WORD PTR directive indicates to the assembler that the instruction uses a word-sized memory pointer. If the instruction moves a byte of immediate data, BYTE PTR replaces WORD PTR in the instruction. Likewise, if the instruction uses a doubleword of immediate data, the DWORD PTR directive replaces BYTE PTR. Most instructions that refer to memory through a pointer do not need the BYTE PTR, WORD PTR, or DWORD PTR directives. These directives are necessary only when it is not clear whether the operation is a byte, word, or doubleword. The MOV [BX],AL instruction is clearly a byte move; the MOV [BX],9 instruction is not exact, and could therefore be a byte-, word-, or doubleword-sized move. Here, the instruction must be coded as MOV BYTE PTR [BX],9, MOV WORD PTR [BX],9, or MOV DWORD PTR [BX],9. If not, the assembler flags it as an error because it cannot determine the intent of the instruction.

Segment MOV Instructions. If the contents of a segment register are moved by the MOV, PUSH, or POP instructions, a special set of register bits (REG field) selects the segment register (see Table 4–6).

Figure 4–10 shows a MOV BX,CS instruction converted to binary. The opcode for this type of MOV instruction is different for the prior MOV instructions. Segment registers can be moved between any 16-bit register or 16-bit memory location. For example, the MOV [DI],DS instruction stores the contents of DS into the memory location addressed by DI in the data

Data Movement Instructions-0101

segment. An immediate segment register MOV is not available in the instruction set. To load a segment register with immediate data, first load another register with the data and then move it to a segment register.

Although this discussion has not been a complete coverage of machine language coding, it provides enough information for machine language programming. Remember that a program written in symbolic assembly language (assembly language) is rarely assembled by hand into binary machine language. An assembler program converts symbolic assembly language into machine language. With the microprocessor and its over 100,000 instruction variations, let us hope that an assembler is available for the conversion, because the process is very time-consuming, although not impossible.

The 64-Bit Mode for the Pentium 4 and Core2

None of the information presented thus far addresses the issue of 64-bit operation of the Pentium 4 or Core2. In the 64-bit mode, an additional prefix called REX (register extension) is added. The REX prefix, which is encoded as a 40H–4FH, follows other prefixes and is placed immediately before the opcode to modify it for 64-bit operation. The purpose of the REX prefix is to modify the reg and r/m fields in the second byte of the instruction. REX is needed to be able to address registers R8 through R15. Figure 4–11 illustrates the structure of REX and also its application to the second byte of the opcode.

The register and memory address assignments for the rrrr and mmmm fields are shown in Table 4–7 for 64-bit operations. The reg field can only contain register assignments as in other modes of operation and the r/m field contains either a register or memory assignment.

Figure 4–12 shows the scaled-index byte with the REX prefix for more complex address- ing modes and also for using a scaling factor in the 64-bit mode of operation. As with 32-bit instructions, the modes allowed by the scaled-index byte are fairly all conclusive allowing pairs of registers to address memory and also an index factor of 2 × , 4 × , or 8 × . An example is the instruction MOV RAXW,3RDX + RCX – 124, which requires the scaled-index byte with an index of 1, which is understood but never entered into the instruction.

Data Movement Instructions-0102

 

QUESTIONS AND PROBLEMS ON ADDRESSING MODES.

QUESTIONS AND PROBLEMS

1. What do the following MOV instructions accomplish?

(a) MOV AX,BX

(b) MOV BX,AX

(c) MOV BL,CH

(d) MOV ESP,EBP

(e) MOV RAX,RCX

2. List the 8-bit registers that are used for register addressing.

3. List the 16-bit registers that are used for register addressing.

4. List the 32-bit registers that are used for register addressing in the 80386 through the Core2 microprocessors.

5. List the 64-bit registers available to the 64-bit mode of the Pentium 4 and Core2.

6. List the 16-bit segment registers used with register addressing by MOV, PUSH, and POP.

7. What is wrong with the MOV BL,CX instruction?

8. What is wrong with the MOV DS,SS instruction?

9. Select an instruction for each of the following tasks:

(a) copy EBX into EDX

(b) copy BL into CL

(c) copy SI into BX

(d) copy DS into AX

(e) copy AL into AH

(f) copy R8 into R10

10. Select an instruction for each of the following tasks:

(a) move 12H into AL

(b) move 123AH into AX

(c) move 0CDH into CL

(d) move 1000H into RAX

(e) move 1200A2H into EBX

11. What special symbol is sometimes used to denote immediate data?

12. What is the purpose of the .MODEL TINY statement?

13. What assembly language directive indicates the start of the CODE segment?

14. What is a label?

15. The MOV instruction is placed in what field of a statement?

16. A label may begin with what characters?

17. What is the purpose of the .EXIT directive?

18. Does the .MODEL TINY statement cause a program to assemble as an execute (.EXE) program?

19. What tasks does the .STARTUP directive accomplish in the small memory model?

20. What is a displacement? How does it determine the memory address in a MOV DS:[2000H],AL instruction?

21. What do the symbols [ ] indicate?

22. Suppose that DS = 0200H, BX = 0300H, and DI = 400H. Determine the memory address accessed by each of the following instructions, assuming real mode operation:

(a) MOV AL,[1234H]

(b) MOV EAX,[BX]

(c) MOV [DI],AL

23. What is wrong with a MOV [BX],[DI] instruction?

24. Choose an instruction that requires BYTE PTR.

25. Choose an instruction that requires WORD PTR.

26. Choose an instruction that requires DWORD PTR.

27. Select an instruction that requires QWORD PTR.

28. Explain the difference between the MOV BX,DATA instruction and the MOV BX,OFFSET DATA instruction.

29. Suppose that DS = 1000H, SS = 2000H, BP = 1000H, and DI = 0100H. Determine the memory address accessed by each of the following instructions, assuming real mode operation:

(a) MOV AL,[BP + DI]

(b) MOV CX,[DI]

(c) MOV EDX,[BP]

30. What, if anything, is wrong with a MOV AL,[BX][SI] instruction?

31. Suppose that DS = 1200H, BX = 0100H, and SI = 0250H. Determine the address accessed by each of the following instructions, assuming real mode operation:

(a) MOV [100H],DL

(b) MOV [SI + 100H],EAX

(c) MOV DL,[BX + 100H]

32. Suppose that DS = 1100H, BX = 0200H, LIST = 0250H, and SI = 0500H. Determine the address accessed by each of the following instructions, assuming real mode operation:

(a) MOV LIST[SI],EDX

(b) MOV CL,LIST[BX + SI]

(c) MOV CH,[BX + SI]

33. Suppose that DS = 1300H, SS = 1400H, BP = 1500H, and SI = 0100H. Determine the address accessed by each of the following instructions, assuming real mode operation:

(a) MOV EAX,[BP + 200H]

(b) MOV AL,[BP + SI – 200H]

(c) MOV AL,[SI – 0100H]

34. Which base register addresses data in the stack segment?

35. Suppose that EAX = 00001000H, EBX = 00002000H, and DS = 0010H. Determine the addresses accessed by the following instructions, assuming real mode operation:

(a) MOV ECX,[EAX + EBX]

(b) MOV [EAX + 2*EBX],CL

(c) MOV DH,[EBX + 4*EAX + 1000H]

36. Develop a data structure that has five fields of one word each named Fl, F2, F3, F4, and F5 with a structure name of FIELDS.

37. Show how field F3 of the data structure constructed in question 36 is addressed in a program.

38. What are the three program memory-addressing modes?

39. How many bytes of memory store a far direct jump instruction? What is stored in each of the bytes?

40. What is the difference between an intersegment and intrasegment jump?

41. If a near jump uses a signed 16-bit displacement, how can it jump to any memory location within the current code segment?

42. The 80386 and above use a -bit displacement to jump to any location within the 4G-byte code segment.

43. What is a far jump?

44. If a JMP instruction is stored at memory location 100H within the current code segment, it cannot be a jump if it is jumping to memory location 200H within the current code segment.

45. Show which JMP instruction assembles (short, near, or far) if the JMP THERE instruction is stored at memory address 10000H and the address of THERE is:

(a) l0020H

(b) 11000H

(c) 0FFFEH

(d) 30000H

46. Form a JMP instruction that jumps to the address pointed to by the BX register.

47. Select a JMP instruction that jumps to the location stored in memory at the location TABLE. Assume that it is a near JMP.

48. How many bytes are stored on the stack by a PUSH AX?

49. Explain how the PUSH [DI] instruction functions.

50. What registers are placed on the stack by the PUSHA instruction? In what order?

51. What does the PUSHAD instruction accomplish?

52. Which instruction places the EFLAGS on the stack in the Pentium 4 microprocessor?

53. Is a PUSHA available in the 64-bit mode of the Pentium 4 or the Core2?

 

SUMMARY OF ADDRESSING MODES.

SUMMARY

1. The data-addressing modes include register, immediate, direct, register indirect, base- p1us-index, register relative, and base relative-plus-index addressing. The 80386 through the Pentium 4 microprocessors have an additional addressing mode called scaled-index addressing.

2. The program memory-addressing modes include direct, relative, and indirect addressing.

3. Table 3–12 lists all real mode data-addressing modes available to the 8086 through the 80286 microprocessors. Note that the 80386 and above use these modes, plus the many defined through this chapter. In the protected mode, the function of the segment register is to address a descriptor that contains the base address of the memory segment.

4. The 80386 through Core2 microprocessors have additional addressing modes that allow the extended registers EAX, EBX, ECX, EDX, EBP, EDI, and ESI to address memory. Although these addressing modes are too numerous to list in tabular form, in general, any of these registers function in the same way as those listed in Table 3–12. For example, the MOV AL,TABLE[EBX + 2*ECX + 10H] is a valid addressing mode for the 80386–Core2 microprocessors.

5. The 64-bit mode for the Pentium 4 and Core2 microprocessors use the same addressing modes as the Pentium 4 or Core2 in 32-bit mode, except the registers contain a linear address and they are 64 bits in width. An additional addressing mode called RIP relative exists for the 64-bit mode that addresses data relative to the address in the instruction pointer.

6. The MOV instruction copies the contents of the source operand into the destination operand.

The source never changes for any instruction.

7. Register addressing specifies any 8-bit register (AH, AL, BH, BL, CH, CL, DH, or DL) or any 16-bit register (AX, BX, CX, DX, SP, BP, SI, or DI). The segment registers (CS, DS, ES, or SS) are also addressable for moving data between a segment register and a 16-bit register/memory location or for PUSH and POP. In the 80386 through the Core2 microprocessors, the extended registers also are used for register addressing; they consist of EAX, EBX, ECX, EDX, ESP, EBP, EDI, and ESI. Also available to the 80386 and above are the FS and GS segment registers. In the 64-bit mode, the registers are RAX, RBX, RCX, RDX, RSP, RBP, RDI, RSI, and R8 through R15.

8. The MOV immediate instruction transfers the byte or word that immediately follows the opcode into a register or a memory location. Immediate addressing manipulates constant data in a program. In the 80386 and above, doubleword immediate data may also be loaded into a 32-bit register or memory location.

9. The .MODEL statement is used with assembly language to identify the start of a file and the type of memory model used with the file. If the size is TINY, the program exists in one seg- ment, the code segment, and is assembled as a command (.COM) program. If the SMALL

Addressing Modes-0086

model is used, the program uses a code and data segment and assembles as an execute (.EXE) program. Other model sizes and their attributes are listed in Appendix A.

10. Direct addressing occurs in two forms in the microprocessor: (1) direct addressing and (2) displacement addressing. Both forms of addressing are identical except that direct address- ing is used to transfer data between EAX, AX, or AL and memory; displacement addressing is used with any register-memory transfer. Direct addressing requires 3 bytes of memory, whereas displacement addressing requires 4 bytes. Note that some of these instructions in the 80386 and above may require additional bytes in the form of prefixes for register and operand sizes.

11. Register indirect addressing allows data to be addressed at the memory location pointed to by either a base (BP and BX) or index register (DI and SI). In the 80386 and above, extended registers EAX, EBX, ECX, EDX, EBP, EDI, and ESI are used to address memory data.

12. Base-plus-index addressing often addresses data in an array. The memory address for this mode is formed by adding a base register, index register, and the contents of a segment reg- ister times 10H. In the 80386 and above, the base and index registers may be any 32-bit register except EIP and ESP.

13. Register relative addressing uses a base or index register, plus a displacement to access memory data.

14. Base relative-plus-index addressing is useful for addressing a two-dimensional memory array. The address is formed by adding a base register, an index register, displacement, and the contents of a segment register times 10H.

15. Scaled-index addressing is unique to the 80386 through the Core2. The second of two registers (index) is scaled by a factor of 2 * , 4 * , or 8 * to access words, doublewords, or quad- words in memory arrays. The MOV AX,[EBX + 2*ECX] and the MOV [4*ECX],EDX are examples of scaled-index instructions.

16. Data structures are templates for storing arrays of data and are addressed by array name and field. For example, array NUMBER and field TEN of array NUMBER is addressed as NUMBER.TEN.

17. Direct program memory addressing is allowed with the JMP and CALL instructions to any location in the memory system. With this addressing mode, the offset address and segment address are stored with the instruction.

18. Relative program addressing allows a JMP or CALL instruction to branch forward or backward in the current code segment by ; 32K bytes. In the 80386 and above, the 32-bit displacement allows a branch to any location in the current code segment by using a dis- placement value of ; 2G bytes. The 32-bit displacement can be used only in protected mode.

19. Indirect program addressing allows the JMP or CALL instructions to address another portion of the program or subroutine indirectly through a register or memory location.

20. The PUSH and POP instructions transfer a word between the stack and a register or memory location. A PUSH immediate instruction is available to place immediate data on the stack. The PUSHA and POPA instructions transfer AX, CX, DX, BX, BP, SP, SI, and DI between the stack and these registers. In the 80386 and above, the extended register and extended flags can also be transferred between registers and the stack. A PUSHFD stores the EFLAGS, whereas a PUSHF stores the FLAGS. POPA and PUSHA are not available in the 64-bit mode.