Course Notes 1.2 Fall 2001 94.201 Page 1 of 12 Notes on the Processor For the purposes of a programmer's model, a processor is characterized by the register set, instruction set (including addressing modes) and interrupt mechanism. The interrupt mechanism will not be discussed further in this course (but it is a major topic in 94.203!). The registers are fixed-size, binary-valued variables that can be modified by the execution of instructions. Registers are often used to hold data relevant to the purpose of a program. For example, an application may need to count events, and a register could be used to accumulate the count value as the program executes. In addition to serving general purposes relevant to applications, registers may also be used in very specific ways that support the operation of the processor (as will be seen in the discussions of the IP register in the execution cycle, and the BX register in addressing modes). The registers are the state variables of the processor, and the processor's state at any point in time is determined by the contents of the registers. Instructions are executed by the processor. The only effects of executing an instruction are the modification of the computer system state variables (processor registers, memory cells, I/O ports). Addressing modes are used to provide flexibility in identifying the state variables to be used as operands in instructions. The instruction set and addressing modes that a processor supports are determined when the processor is designed. The pseudo-80x86 Intel Processor (p-86) The processor studied in this course is a simplified version of the Intel 80x86 family of processors. (For those who may already know about this family: the main simplification is the reduction of the address space to 64K bytes – this permits the elimination of all concerns about segments. Segments will be introduced in 94.203.) The processor will be introduced by first describing the register set and then presenting the simple underlying operation (execution) cycle. The instruction set will then be introduced, with addressing modes introduced gradually as needed. Only a representative subset of the instruction set will be discussed now, in order to get to a point where simple programs can be understood. Additional instructions will be discussed in more detail later. See the Instruction Reference handout for a more complete list of instructions. Copyright Trevor W. Pearce, September 21, 2000 For use in the 94.201 course only – not for distribution outside of the Department of Systems and Computer Engineering, Carleton University, Ottawa, Canada Course Notes 1.2 Fall 2001 94.201 Page 2 of 12 p-86 Register Set All registers are 16-bits wide. All registers (except the IR) can be modified under program control (i.e. by executing instructions). There are 4 general purpose registers: AX, BX, CX and DX. Each of the general purpose registers can be accessed as 16-bit values using the above names. In addition, the high byte (most significant 8 bits) and low byte (least significant 8 bits) of the registers can be accessed respectively using the names: AH, AL (for AX), BH, BL (for BX), CH, CL (for CX), DH, DL (for DX). In addition to the general purpose registers, the register set also includes the following addressing registers: IP SP BP SI DI Instruction Pointer Stack Pointer Base Pointer Source Index Destination Index The processor also includes a 16-bit FLAGS register. Unlike other registers, the bits of FLAGS do not collectively define a useful 8- or 16-bit value. Instead, four of the bits have individual meanings (the rest of the bits are meaningless and can be ignored). The exact position of each of the meaningful bits is not important (in this course), and the bits are referred to by their names: CF SF OF IF Carry Flag Sign Flag Overflow Flag Interrupt Flag To understand the operation of the processor, it is necessary to know about additional registers that support the operation of the processor, but cannot be modified directly under software control. The additional registers are the IR (Instruction Register) and temporary registers (used to hold intermediate values during processor operation). These additional registers may be larger than 16-bits. Summary of the 16-bit general purpose and addressing registers available to programmers: General Purpose AX (AH,AL) BX (BH, BL) CX (CH, CL) DX (DH, DL) IP SP BP SI DI Addressing Instruction Pointer Stack Pointer Base Pointer Source Index Destination Index Copyright Trevor W. Pearce, September 21, 2000 For use in the 94.201 course only – not for distribution outside of the Department of Systems and Computer Engineering, Carleton University, Ottawa, Canada Course Notes 1.2 Fall 2001 94.201 Page 3 of 12 Execution Cycle The processor assumes that instructions are stored as binary values in memory. Furthermore, it is assumed that instructions are stored sequentially in memory, such that the last byte of each instruction is followed by the first byte of another. The encoding of an instruction must account for the specific operation to be performed, and any operands involved in the operation. Since some operations involve more operands than others, instruction length can vary from one to six bytes. (The encoding scheme used for instructions is a bit too complex to discuss prior to a more complete discussion of instructions and addressing modes. Instruction encoding will be discussed later.) Before executing an instruction, the processor must first fetch it from memory. The fundamental operation of the processor is based on the assumption that the IP register contains the address of the next instruction to be executed (i.e. the processor always assumes that the 16-bit value in the IP register is the address of the memory location containing the first byte of the next instruction to execute). The execution cycle consists of two steps: (1) Instruction Fetch: IR := mem[IP] loads IR with complete instruction starting at mem[IP] The Processor fetches the next instruction from memory by copying the encoded instruction value into the IR. The IP is used to select which memory location the first byte of the instruction is stored in. By looking at the first byte, the processor can decide whether the instruction has additional bytes to be loaded. In some cases, the processor must also load the second byte into IR before it can decide exactly how bytes are in the instruction. (The important point is that the processor can determine how many bytes there are in an instruction, and can load the complete instruction into the IR.) While fetching the instruction, the processor adjusts IP to point to the next sequential instruction in memory (i.e. to point to the byte after the last byte of the instruction it just loaded). This adjustment of the IP to point to the next instruction results in the processor having an inherently sequential control flow. Sequential control flow requires that instructions are stored sequentially in memory! (2) Instruction Execute: Execute the instruction in IR. The processor now executes the instruction it just loaded into IR. The execution is carried out by dedicated circuitry inside the processor. The details of how the circuitry implements instructions is beyond the scope of this course (97.267 starts to lay the foundations for this sort of hardware knowledge, and 97.350 adds more details!). Execution results in system state changes (i.e. changes to the system's state variables – the registers, cells, and ports). Copyright Trevor W. Pearce, September 21, 2000 For use in the 94.201 course only – not for distribution outside of the Department of Systems and Computer Engineering, Carleton University, Ottawa, Canada Course Notes 1.2 Fall 2001 94.201 Page 4 of 12 The processor continually cycles through the two steps until a HLT (halt) instruction is executed. Note: instructions are executed by the processor by copying individual instructions (one-at-a-time) into the IR – instructions are stored in memory, but not “executed” in memory. Instruction Set The instructions in an instruction set can often be organized into three general categories: Data Transfer, Data Manipulation and Control Flow. Data transfer instructions copy data among system state variables (registers, locations, ports). The limited number of registers in a processor, and the dedicated use of specific registers in certain instructions, results in the need to transfer data in and out of registers frequently. Data Manipulation instructions modify the values of state variables, including the flags. Manipulation instructions are essential to perform calculations where values must be combined to obtain results. Control flow instructions allow programmers to specify an instruction, other than the next sequential instruction, as the next instruction to be executed. If control flow instructions were not available, then practical programs would not be possible. Although these three categories are useful generalizations, particularly during a first exposure to an instruction set, it is common for processors to have hybrid instructions that span more than one category. In the following discussion, a representative subset of the p-86 instructions will be introduced to illustrate the three categories. Additional instructions will be introduced later. When learning about an instruction, there are two important parts to be understood: the operation and the operands. The operation specifies how state variable values are involved (i.e. copied, combined, modified, written, etc.). The operands specify which state variables are involved. Operands may be explicit or implicit. Explicit operands must be stated each time the instruction is written. Implicit operands are not stated when the instruction is written, but are always used by the processor when the instruction is executed. Operands that act as the source of values to be used in operations are referred to as source operands. Operands that have new values written to them are referred to as destination operands. In some instructions, the same state variable acts as both the source and destination. Addressing modes provide various ways for programmers to specify the explicit operands of instructions (i.e. flexibility in stating which of the computer systems state variables are to be used as the operands). The immediate, register, direct and indirect addressing modes for data transfer are introduced below in the discussion of the MOV instruction. These addressing modes are also applicable to data manipulation instructions. More powerful variations of the indirect mode are introduced later. The relative addressing mode is introduced for control flow instructions. Copyright Trevor W. Pearce, September 21, 2000 For use in the 94.201 course only – not for distribution outside of the Department of Systems and Computer Engineering, Carleton University, Ottawa, Canada Course Notes 1.2 Fall 2001 94.201 Page 5 of 12 More terminology: When a register is used as an operand, it is referred to as a register operand. When a memory cell is used as an operand, it is referred to as a memory operand. Data Transfer Data transfer instructions allow state variable values to be copied among state variables. The p-86 supports several data transfer instructions. The MOV (move) instruction is used to copy values among registers, and between the processor and memory. The IN (input) and OUT (output) instructions are used to copy values between registers and I/O ports. Data transfer instructions do not modify the flags. MOV The MOV instruction involves two operands: the source (src) state variable whose value is to be copied, and the destination (dest) state variable where the copied source value is to be written. The general form of the MOV instruction is written: MOV dest, src where: dest specifies the destination state variable src specifies the source state variable Programs often require data to be copied to and from registers. In such cases, the register addressing mode must be used to specify the register(s) involved. For example, executing the instruction: MOV AX, BX would result in the value stored in the BX register (src) being copied to the AX register (dest). In this case, both the src and dest operands are registers and have been specified using the register addressing mode. Programs often require the use of constant values. For example, if a register was being used to implement a counter, then it must first be initialized to 0, and then incremented when appropriate (by adding 1). Processors provide the immediate addressing mode to allow constant values (like 0 and 1) to be specified as operands. An immediate value is specified by stating the value. For example, executing the instruction: MOV CX, 0 would cause the CX register (dest) to be loaded with the (16-bit) value 0 (src). In this case, the dest operand has been specified using the register addressing mode, and the src operand has been specified using the immediate mode. The immediate mode can only be used for source operands. The constant value is encoded as part of the instruction, and is loaded into the IR when the instruction is fetched. During the execution of the instruction, the immediate value is copied from the IR and used as prescribed by the instruction’s operation. Programs often require data variables (for example, counters). When only a few variables are required, it may be possible to dedicate a register to each variable; however, Copyright Trevor W. Pearce, September 21, 2000 For use in the 94.201 course only – not for distribution outside of the Department of Systems and Computer Engineering, Carleton University, Ottawa, Canada Course Notes 1.2 Fall 2001 94.201 Page 6 of 12 this approach becomes impractical once the register set is exhausted. A more general approach is to store variables in memory. Memory operands may be specified using the direct and indirect addressing modes. Memory Operands: Direct Mode The direct addressing mode allows a memory operand to be specified by stating the address of the relevant location. This is similar to, but different from, the immediate mode. Both modes are similar in that they encode a constant value (the immediate value or the address) as part of the instruction. The modes differ in the interpretation of the value (in immediate mode, the value is the operand, in direct mode, the value is the memory address of the operand). A syntactic notation is needed to differentiate the immediate and direct modes. The direct mode is specified by enclosing the supplied memory address in square brackets (i.e. "[" and "]" ). For example, executing the instruction: MOV DX, [24B2H] would cause the DX register to be loaded with the contents of the two memory bytes at memory addresses 24B2H and 24B3H. We can’t tell from the instruction the exact value that would be loaded into DX – this depends on the contents of the addressed memory locations at the time the instruction is executed. Recall that DX is a 16-bit register, and therefore, 2 memory locations must be accessed to obtain a 16-bit value to copy to DX. Since the system uses the little endian scheme to store 16-bit values in pairs of bytes, then the contents of location 24B2H would be loaded into DL, and the contents of 24B3H would be loaded into DH. In contrast to the above, executing the instruction: MOV DX, 24B2H would load the DX register with the immediate value 24B2H. N.B. no “[” and “]” around 24B2H ! The direct mode can also be used for either destination and source operands (see above for example of source operand). As a destination example, executing the instruction: MOV [034H], SI would copy the contents of the SI register to memory locations 0034H and 0035H (16bit, little endian!). The p-86 processor has some limitations in how source and destination addressing modes can be combined in instructions. At most, only one operand can be specified to be a memory operand. This limitation is a result of decisions that were made when the processor was designed. Unfortunately, the only way to be sure of exactly which modes are supported by an instruction requires reading a concise description of the instruction (see the Instruction Reference handout in the course I: drive!). Sanity Check: Be sure you understand the difference between: [28H] MOV AL, 28H and MOV AL, Copyright Trevor W. Pearce, September 21, 2000 For use in the 94.201 course only – not for distribution outside of the Department of Systems and Computer Engineering, Carleton University, Ottawa, Canada Course Notes 1.2 Fall 2001 94.201 Page 7 of 12 Why doesn't the following instruction make any sense? MOV 0, CX Memory Operands: Indirect Mode The direct mode is adequate in some cases when the data structure being accessed is a simple byte or word variable, but the use of the mode requires that the address of the variable be known at the time the program is written. While the direct mode is simple to use, it is not flexible enough to provide a general access method to composite structures such as arrays and records, which often require a dynamic access mechanism (i.e. the exact element to be accessed depends on run-time values – the same statement may access different elements at different times depending on the specific state variable values at the time of execution). An array is a structure consisting of a collection of elements, all of which are of the same type (i.e. each element of the array has the same memory requirements, for example: all are one byte or two bytes wide). A record (called a struct in some languages) is also a collection of elements, although the elements are not necessarily of the same type (i.e. the elements in a record may have different memory requirements). In programs, the elements of a composite structure are stored in contiguous memory locations. Accessing a particular element of a structure often involves two pieces of information: the start address of the structure in memory, and the offset into the structure to reach the element. The direct addressing mode can accommodate only a single address (such as a structure’s start address), and is not flexible enough to deal with a second piece of addressing information (such as an offset into the structure). The indirect addressing mode provides a flexible mechanism for accessing composite structures. (The indirect mode is also useful in accessing parameters passed to subroutines, but this will be discussed in detail later.) In the indirect mode, the address of the operand is constructed from the current values of specified state variables at the time that the instruction is executed. In the simplest form of indirect mode, the contents of a register is used as the operand’s address – thus it is often called the register indirect mode. The p-86 processor allows the following registers to be used in register indirect addressing of memory operands: BX, BP, SI, DI Note that the following p-86 registers can NOT be used in indirect modes for memory operands: AX, AH, AL, BH, BL, CX, CH, CL, DX, DH, DL, FLAGS, IP, SP The p-86 processor allows only the DX register to be used in the indirect addressing of I/O ports (i.e. in the IN and OUT instructions). A syntactic notation is needed to differentiate the register and indirect modes. The indirect mode follows the direct mode by enclosing the addressing information in square brackets. For example, executing the instruction: MOV AL, [BX] Copyright Trevor W. Pearce, September 21, 2000 For use in the 94.201 course only – not for distribution outside of the Department of Systems and Computer Engineering, Carleton University, Ottawa, Canada Course Notes 1.2 Fall 2001 94.201 Page 8 of 12 would cause the low byte of the AX register to be loaded with the contents of the memory cell whose address is contained in the BX register. Obviously, executing the instruction would only make sense if the BX register had been loaded previously with the address of a memory location. (Recall the discussion of composite structures above.) Indirect addressing provides a flexible way to access the elements of composite structures. For example, suppose that a program wishes to use a loop to process all of the elements of an array of bytes. During loop initialization, a legal register for register indirect addressing (e.g. BX) could be loaded with the start address of the array: MOV BX, start_address_of_array In the loop, the current element to process could be accessed: MOV AL, [BX] At the end of each iteration through the loop, the BX register should be adjusted to point to the next element: ADD BX, 1 (ADD instruction will be discussed more later) The above example shows one possible way to use indirect addressing to access the elements of an array – a more powerful mode will be discussed later. The indirect mode allows operands to be specified dynamically – the address of the operand is not specified in the instruction, the address is determined by the values of state variables at run-time (i.e. the state variable values at the time the instruction is executed). This is different from specifying an address statically using the direct addressing mode – in the direct mode, the exact address is known and specified at compile/assemble-time (i.e. before the program is run). Operand Compatibility A potential ambiguity can arise when the destination operand is specified using direct or indirect mode, and the src operand is specified using immediate mode. This combination is very useful for initializing memory variable to specific values. For example: MOV [480H], 1 This combination of modes is allowed; however, it is unclear as to whether the instruction should move the 8-bit value 01H to memory location 0480H, or the 16-bit value 0001H to locations 0480H and 0481H (16-bit, little endian!). This ambiguity must be resolved using "WORD PTR" or "BYTE PTR" to clarify how the destination address should be used. For example, MOV BYTE PTR [480H], 1 specifies that the 8-bit value 01H should be copied to memory. The instruction: MOV WORD PTR [480H], 1 specifies that the 16-bit value 0001H should be copied to memory. Data Manipulation Copyright Trevor W. Pearce, September 21, 2000 For use in the 94.201 course only – not for distribution outside of the Department of Systems and Computer Engineering, Carleton University, Ottawa, Canada Course Notes 1.2 Fall 2001 94.201 Page 9 of 12 Data manipulation instructions allow the values of state variables to be modified in ways other than using data transfer instructions. For example, by performing arithmetic or logic operations with values. In addition to generating a result of the manipulation, these instructions also have the important side effect of modifying the processor flags to reflect the result of the manipulation. The setting (set: force the value to 1) or clearing (clear: force the value to 0) of flags is performed by the processor as part of the instruction's execution. This manipulation of the flags is essential to support the use of the conditional control flow instructions (to be discussed later). The number of operands associated with a manipulation instruction depends on the instruction. For example, the instruction: NEG dest negates the dest operand by performing the operation: dest := 2's complement( dest ) For the NEG instruction, dest can be specified using register, direct or indirect modes. If direct or indirect are used, then WORD PTR or BYTE PTR must also be used to clarify whether it is a byte or word of memory to be negated. The ADD instruction requires two operands. The instruction: ADD dest, src performs the operation: dest := dest + src Following an arithmetic operation, the flags are modified to reflect the result: ZF := 1 iff the resulting value of dest = 0 SF := 1 iff the result value of dest is negative (2's complement signed interpretation) CF := 1 iff a carry (or required a borrow) resulted at the most significant bit this flag is often used to indicate that the result of an unsigned operation overflowed OF := 1 iff the result overflowed the 2's complement capacity for the specified size Example: Prior to executing the instruction: ADD AL, BH suppose that the AL and BH registers contain the binary values: AL 1111 1111 (unsigned = 255, signed = –1) BH 0000 0001 (unsigned = 1, signed = 1) After executing the instruction, the following state variable values would exist (no other state variables would be modified by the execution of the instruction): AL 0000 0000 (dest = result of addition) ZF = 1 since the result is 0 SF = 0 since the result is not negative Copyright Trevor W. Pearce, September 21, 2000 For use in the 94.201 course only – not for distribution outside of the Department of Systems and Computer Engineering, Carleton University, Ottawa, Canada Course Notes 1.2 Fall 2001 94.201 Page 10 of 12 CF = 1 since the addition generated a carry (unsigned overflow occurred!) OF = 0 since the 8-bit 2's complement result correctly represents the result when the operands are interpreted as signed values As with addressing modes, a concise description of the instruction must be consulted to determine the exact way in which the flags are manipulated by the instruction. (See the Instruction Reference on the course I: drive.) Control Flow Control flow instructions allow a program to select the memory location of the next instruction to be executed. Recall the 2 steps of execution cycle: (1) the IP register is used to fetch the instruction to execute, (2) the fetched instruction is executed.. If the fetched instruction is a control flow instruction, then the location of the next instruction to be fetched (next time through the cycle) can be changed by simply changing the IP value during the execution of the fetched control flow instruction. Control flow instructions select the next instruction to be fetched by modifying the IP. In general, control flow instructions do not modify the flags (only data manipulation instructions modify the flags). (Aside: Recall from the discussion of the execution cycle, that the IP is modified to point to the next sequential instruction during the instruction fetch step, not after the instruction execution step. This is to ensure that if the fetched instruction is a control flow instruction that modified the IP value, then the IP will not be modified further before fetching the next instruction.) The JMP (jump) instruction is used to specify an unconditional jump (i.e. a jump that is always taken, regardless of the flag values). This instruction forces the IP to point to a desired memory location (i.e. containing the next instruction to be fetched). The instruction has the general form: JMP target where the target operand is used to specify the desired memory location. The relative mode is often used for target addressing. The relative mode is different than the immediate, register and direct modes used for data transfer and manipulation instructions. In the relative mode, the target operand is encoded as a signed immediate value that specifies the offset from the current IP value (after fetching the JMP instruction) to the address of the next instruction. The execution of the instruction is performed by adding the offset to IP. NB: the flags are not modified as a result of the addition! The offset is given as a signed value to allow control to be transferred to either forward (higher) or backward (lower) memory addresses. Copyright Trevor W. Pearce, September 21, 2000 For use in the 94.201 course only – not for distribution outside of the Department of Systems and Computer Engineering, Carleton University, Ottawa, Canada Course Notes 1.2 Fall 2001 94.201 Page 11 of 12 Example: Suppose the following memory configuration: address(H) contents 0034 JMP 0010H 0037 ADD AX, 2 (other values in memory here) 0047 ADD AX, 8 After fetching the JMP instruction from address 0034H, the IP contains 0037H (the address of the first byte of the next sequential instruction). The execution of the JMP instruction causes the offset 0010H to be added to the IP value. The resulting IP value is 0047H. Therefore, following the execution of the JMP instruction, the next instruction will be fetched from 0047H, not from 0037H. Now consider the following memory configuration: address(H) contents 0034 JMP 0FFFDH 0037 ADD AX, 2 What will happen if the JMP instruction is executed? Can the behaviour of the system be predicted? In addition to the unconditional JMP, most processors are also equipped with conditional jumps. These instructions are called conditional because they check for certain flag values and only jump if the specified flag values are found. For example, the JZ (Jump if Zero) instruction has the form: JZ target When the instruction is executed, the processor checks ZF and only jumps to the target if ZF = 1. If ZF is 0, then the instruction has no effect, and the next sequential instruction is fetched. To understand what flag combinations are relevant to a conditional jump instruction, it is necessary to consult a concise description of the instruction. (See Instruction Reference in course I: drive.) Conditional jumps (but not the JMP instruction) in the p-86 processor are further constrained to use only 8-bit immediate relative addressing values. This means that conditional jumps can jump only to target destinations within the range of -128 to +127 bytes. We have already seen that the processor supports different flags to reflect the results of arithmetic operations, depending on whether the operands involved are interpreted as signed or unsigned values (e.g. following an ADD, OF indicates signed overflow while CF indicates unsigned overflow). There are also different conditional jumps that check the flag combinations relevant to signed vs. unsigned results. More will be said about this later! Copyright Trevor W. Pearce, September 21, 2000 For use in the 94.201 course only – not for distribution outside of the Department of Systems and Computer Engineering, Carleton University, Ottawa, Canada Course Notes 1.2 Fall 2001 94.201 Copyright Trevor W. Pearce, September 21, 2000 For use in the 94.201 course only – not for distribution outside of the Department of Systems and Computer Engineering, Carleton University, Ottawa, Canada Page 12 of 12