INTEL 80286 PROGRAMMER'S REFERENCE MANUAL 1987 Intel Corporation makes no warranty for the use of its products and assumes no responsibility for any errors which may appear in this document nor does it make a commitment to update the information contained herein. Intel retains the right to make changes to these specifications at any time, without notice. Contact your local sales office to obtain the latest specifications before placing your order. The following are trademarks of Intel Corporation and may only be used to identify Intel Products: Above, BITBUS, COMMputer, CREDIT, Data Pipeline, FASTPATH, Genius, i, ξ, ICE, iCEL, iCS, iDBP, iDIS, I²ICE, iLBX, im, iMDDX, iMMX, Inboard, Insite, Intel, intel, intelBOS, Intelevision, inteligent Identifier, inteligent Programming, Intellec, Intellink, iOSP, iPDS, iPSC, iRMX, iSBC, iSBX, iSDM, iSXM, KEPROM, Library Manager, MAP-NET, MCS, Megachassis, MICROMAINFRAME, MULTIBUS, MULTICHANNEL, MULTIMODULE, MultiSERVER, ONCE, OpenNET, OTP, PC-BUBBLE, Plug-A-Bubble, PROMPT, Promware, QUEST, QueX, Quick-Pulse Programming, Ripplemode, RMX/80, RUPI, Seamless, SLD, UPI, and VLSiCEL, and the combination of ICE, iCS, iRMX, iSBC, iSBX, MCS, or UPI and a numerical suffix, 4-SITE. MDS is an ordering code only and is not used as a product name or trademark. MDS(R) is a registered trademark of Mohawk Data Sciences Corporation. *MULTIBUS is a patented Intel bus. Additional copies of this manual or other Intel literature may be obtained from: Intel Corporation Literature Distribution Mail Stop SC6-59 3065 Bowers Avenue Santa Clara, CA 95051 (c)INTEL CORPORATION 1987 CG-10/86 Preface ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ This manual describes the 80286, the most powerful 16-bit microprocessor in the 8086 family, and the 80287 Numeric Processor Extension (NPX). Organization of This Manual 80286 The 80286 contains a table of contents, eleven chapters, four appendices, and an index. For more information on the 80286 book's organization, see its first chapter, Chapter 1, "Introduction to the 80286." Section 1.4 in that chapter explains the organization in detail. Notational Conventions This manual uses special notation to represent sub- and superscript characters. Subscript characters are surrounded by {curly brackets}, for example 10{2} = 10 base 2. Superscript characters are preceeded by a caret and enclosed within (parentheses), for example 10^(3) = 10 to the third power. Table of Contents ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Chapter 1 Introduction to the 80286 1.1 General Attributes 1.2 Modes of Operation 1.3 Advanced Features 1.3.1 Memory Management 1.3.2 Task Management 1.3.3 Protection Mechanisms 1.3.4 Support for Operating Systems 1.4 Organization of This Book 1.5 Related Publications Chapter 2 80286 Base Architecture 2.1 Memory Organization and Segmentation 2.2 Data Types 2.3 Registers 2.3.1 General Registers 2.3.2 Memory Segmentation and Segment Registers 2.3.3 Index, Pointer, and Base Registers 2.3.4 Status and Control Registers 2.4 Addressing Modes 2.4.1 Operands 2.4.2 Register and Immediate Modes 2.4.3 Memory Addressing Modes 2.4.3.1 Segment Selection 2.4.3.2 Offset Computation 2.4.3.3 Memory Mode 2.5 Input/Output 2.5.1 I/O Address Space 2.5.2 Memory-Mapped I\0 2.6 Interrupts and Exceptions 2.7 Hierarchy of Instruction Sets Chapter 3 Basic Instruction Set 3.1 Data Movement Instructions 3.1.1 General-Purpose Data Movement Instructions 3.1.2 Stack Manipulation Instructions 3.2 Flag Operation with the Basic Instruction Set 3.2.1 Status Flags 4 3.2.2 Control Flags 4 3.3 Arithmetic Instructions 3.3.1 Addition Instructions 3.3.2 Subtraction Instructions 3.3.3 Muitiplication Instructions 3.3.4 Division Instructions 3.4 Logical Instructions 3.4.1 Boolean Operation Instructions 3.4.2 Shift and Rotate Instructions 3.4.2.1 Shift Instructions 3.4.2.2 Rotate Instructions 3.4.3 Type Conversion and No-Operation Instructions 3.5 Test and Compare Instructions 3.6 Control Transfer Instructions 3.6.1 Unconditional Transfer Instructions 3.6.1.1 Jump instruction 3.6.1.2 Call Instruction 3.6.1.3 Return and Return from interrupt Instruction 3.6.2 Conditional Transfer Instructions 3.6.2.1 Conditional Jump Instructions 3.6.2.2 Loop Instructions 3.6.2.3 Executing a Loop or Repeat Zero Times 3.6.3 Software-Generated Interrupts 3.6.3.1 Software Interrupt Instruction 3.7 Character Translation and String Instructions 3.7.1 Translate Instruction 3.7.2 String Manipulation Instructions and Repeat Prefixes 3.7.2.1 String Movement Instructions 3.7.2.2 Other String Operations 3.8 Address Manipulation Instructions 3.9 Flag Control instructions 3.9.1 Carry Flag Control Instructions 3.9.2 Direction Flag Control Instructions 3.9.3 Flag Transfer Instructions 3.10 Binary-Coded Decimal Arithmetic Instructions 3.10.1 Packed BCD Adjustment Instructions 3.10.2 Unpacked BCD Adjustment Instructions 3.11 Trusted Instructions 3.11.1 Trusted and Privileged Restrictions on POPF and IRET 3.11.2 Machine State Instructions 3.11.3 Inputand Output Instructions 3.12 Processor Extension Instructions 3.12.1 Processor Extension Synchronization Instructions 3.12.2 Numeric Data Processor Instructions 3.12.2.1 Arithmetic Instructions 3.12.2.2 Comparison Instructions 3.12.2.3 Transcendental Instructions 3.12.2.4 Data Transfer Instructions 3.12.2.5 Constant Instructions Chapter 4 Extended Instruction Set 4.1 Block I\O Instructions 4.2 High-Level Instructions Chapter 5 Real Address Mode 5.1 Addressing and Segmentation 5.2 Interrupt Handling 5.2.1 Interrupt Vector Table 5.2.1.1 Interrupt Procedures 5.2.2 Interrupt Priorities 5.2.3 Reserved and Dedicated Interrupt Vectors 5.3 System Initialization. Chapter 6 Memory Management and Virtual Addressing 6.1 Memory Management Overview 6.2 Virtual Addresses 6.3 Descriptor Tables 6.4 Virtual-to-Physical Address Translation 6.5 Segments and Segment Descriptors 6.6 Memory Management Registers 6.6.1 Segment Address Translation Registers 6.6.2 System Address Registers Chapter 7 Protection 7.1 Introduction 7.1.1 Types of Protection 7.1.2 Protection Implementation 7.2 Memory Management and Protection 7.2.1 Separation of Address Spaces 7.2.2 LDT and GDT Access Checks 7.2.3 Type Validation 7.3 Privilege Levels and Protection 7.3.1 Example of Using Four Privilege Levels 7.3.2 Privilege Usage 7.4 Segment Descriptor 7.4.1 Data Accesses 7.4.2 Code Segment Access 7.4.3 Data Access Restriction by Privilege Level 7.4.4 Pointer Privilege Stamping via ARPL 7.5 Control Transfers 7.5.1 Gates 7.5.1.1 Call Gates 7.5.1.2 Intra-Level Transfers via Call Gate 7.5.1.3 Inter-Level Control Transfer via Call Gates 7.5.1.4 Stack Changes Caused by Call Gates 7.5.2 Inter-Level Returns Chapter 8 Tasks and State Transitions 8.1 Introduction 8.2 Task State Segments and Descriptors 8.2.1 Task State Segment Descriptors 8.3 Task Switching 8.4 Task Linking 8.5 Task Gates Chapter 9 Interrupts and Exceptions 9.1 Interrupt Descriptor Table 9.2 Hardware Initiated Interrupts 9.3 Software Initiated Interrupts 9.4 Interrupt Gates and Trap Gates 9.5 Task Gates and Interrupt Tasks 9.5.1 Scheduling Considerations 9.5.2 Deciding Between Task, Trap, and Interrupt Gates 9.6 Protection Exceptions and Reserved Vectors 9.6.1 Invalid OP-Code (Interrupt 6) 9.6.2 Double Fault (Interrupt 8) 9.6.3 Processor Extension Segment Overrun (Interrupt 9) 9.6.4 Invalid Task State Segment (Interrupt 10) 9.6.5 Not Present (Interrupt 11) 9.6.6 Stack Fault (Interrupt 12) 9.6.7 General Protection Fault (Interrupt 13) 9.7 Additional Exceptions and Interrupts 9.7.1 Single Step Interrupt (Interrupt 1) Chapter 10 System Control and Initialization 10.1 System Flags and Registers 10.1.1 Descriptor Table Registers 10.2 System Control Instructions 10.2.1 Machine Status Word 10.2.2 Other Instructions 10.3 Privileged and Trusted Instructions 10.4 Initialization 10.4.1 Real Address Mode 10.4.2 Protected Mode Chapter 11 Advanced Topics 11.1 Virtual Memory Management 11.2 Special Segment Attributes 11.2.1 Conforming Code Segments 11.2.2 Expand-Down Data Segments 11.3 Pointer Validation 11.3.1 Descriptor Validation 11.3.2 Pointer Integrity: RPL and the"Trojan Horse Problem" 11.4 NPX Context Switching 11.5 Multiprocessor Considerations 11.6 Shutdown Appendix A 80286 System Initialization Appendix B The 80286 Instruction Set Appendix C 8086/8088 Compatibility Considerations Appendix D 80286/80386 Software Compatibility Considerations Index Figures 1-1 Four Privilege Levels 2-1 Segmented Virtual Memory 2-2 Bytes and Words in Memory. 2-3 80286/80287 Supported Data Types 2-4 80286 Base Architecture Register Set 2-5 Real Address Mode Segment Selector Interpretation 2-6 Protected Mode Segment Selector Interpretation 2-7 80286 Stack 2-8 Stack Operation 2-9 BP Usage as a Stack Frame Base Pointer 2-10 Flags Register. 2-11 Two-Component Address 2-12 Use of Memory Segmentation 2-13 Complex Addressing Modes 2-14 Memory-Mapped I/O 2-15 Hierarchy of Instructions 3-1 PUSH 3-2 PUSHA 3-3 POP 3-4 POPA. 3-5 Flag Word Contents 3-6 SAL and SHL 3-7 SHR 3-8 SAR 3-9 ROL 3-10 ROR 3-11 RCL 3-12 RCR 3-13 LAHF and SAHF 3-14 PUSHF and POPF 4-1 Formal Definition of the ENTER Instruction 4-2 Variable Access in Nested Procedures 4-2a Stack Frame for MAIN at Level 1 4-2b Stack Frame for Procedure A 4-2c Stack Frame for Procedure B at Level 3 Called from A 4-2d Stack Frame for Procedure C at Level 3 Called from B 5-1a Forming the Segment Base Address 5-1b Forming the 20-Bit Physical Address in the Real Address Mode 5-2 Overlapping Segments to Save Physical Memory 5-3 Interrupt Vector Table for Real Address Mode 5-4 Stack Structure after Interrupt (Real Address Mode) 6-1 Format of the Segment Selector Component 6-2 Address Spaces and Task Isolation 6-3 Segment Descriptor (S=1) 6-4 Special Purpose Descriptors or System Segment Descriptors (S=O) 6-5 LDT Descriptor 6-6 Virtual-to-Physical Address Translation 6-7 Segment Descriptor Access Bytes 6-8 Memory Management Registers 6-9 Descriptor Loading 7-1 Addressing Segments of a Module within a Task 7-2 Descriptor Cache Registers 7-3 80286 Virtual Address Space 7-4 Local and Global Descriptor Table Definitions 7-5 Error Code Format (on the stack) 7-6 Code and Data Segments Assigned to a Privilege Level. 7-7 Selector Fields 7-8 Access Byte Examples. 7-9 Pointer Privilege Stamping 7-10 Gate Descriptor Format. 7-11 Call Gate 7-12 Stack Contents after an Inter-Level Call 8-1 Task State Segment and TSS Registers 8-2 TSS Descriptor 8-3 Task Gate Descriptor 8-4 Task Switch Through a Task Gate 9-1 Interrupt Descriptor Table Definition 9-2 IDT Selector Error Code. 9-3 Trap/Interrupt Gate Descriptors 9-4 Stack Layout after an Exception with an Error Code 10-1 Local and Global Descriptor Table Definition 10-2 Interrupt Descriptor Table Definition 10-3 Data Type for Global Descriptor Table and Interrupt Descriptor Table 11-1 Expand-Down Segment 11-2 Dynamic Segment Relocation and Expansion of Segment Limit 11-3 Example of NPX Context Switching B-1 /n Instruction Byte Format B-2 /r Instruction Byte Format Tables 2-1 Implied Segment Usage by Index, Pointer, and Base Registers 2-2 Segment Register Selection Rules 2-3 Memory Operand Addressing Modes 2-4 80286 Interrupt Vector Assignments (Real Address Mode) 3-1 Status Flags' Functions 3-2 Control Flags' Functions 3-3 Interpretation of Conditional Transfers 5-1 Interrupt Processing Order 5-2 Dedicated and Reserved Interrupt Vectors in Real Address Mode 5-3 Processor State after RESET 7-1 Segment Access Rights Byte Format 7-2 Allowed Segment Types in Segment Registers 7-3 Call Gate Checks 7-4 Inter-Level Return Checks 8-1 Checks Made during a Task Switch 8-2 Effect of a Task Switch on BUSY and NT Bits and the Link Word 9-1 Trap and Interrupt Gate Checks 9-2 Interrupt and Gate Interactions 9-3 Reserved Exceptions and Interrupts 9-4 Interrupt Processing Order 9-5 Conditions That Invalidate the TSS 10-1 MSW Bit Functions 10-2 Recommended MSW Encodings for Processor Extension Control 11-1 NPX Context Switching B-1 ModRM Values B-2 Protection Exceptions of the 80286 B-3 Hexadecimal Values for the Access Rights Byte C-1 New 80286 Interrupts Chapter 1 Introduction to the 80286 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ The 80286 is the most powerful 16-bit processor in the 8086 series of microprocessors, which includes the 8086, the 8088, the 80186, the 80188, and the 80286. It is designed for applications that require very high performance. It is also an excellent choice for sophisticated "high end" applications that will benefit from its advanced architectural features: memory management, protection mechanisms, task management, and virtual memory support. The 80286 provides, on a single VLSI chip, computational and architectural characteristics normally associated with much larger minicomputers. Sections 1.1, 1.2, and 1.3 of this chapter provide an overview of the 80286 architecture. Because the 80286 represents an extension of the 8086 architecture, some of this overview material may be new and unfamiliar to previous users of the 8086 and similar microprocessors. But the 80286 is also an evolutionary development, with the new architecture superimposed upon the industry standard 8086 in such a way as to affect only the design and programming of operating systems and other such system software. Section 1.4 of this chapter provides a guide to the organization of this manual, suggesting which chapters are relevant to the needs of particular readers. 1.1 General Attributes The 80286 base architecture has many features in common with the architecture of other members of the 8086 family, such as byte addressable memory, I/O interfacing hardware, interrupt vectoring, and support for both multiprocessing and processor extensions. The entire family has a common set of addressing modes and basic instructions. The 80286 base architecture also includes a number of extensions which add to the versatility of the computer. The 80286 processor can function in two modes of operation (see section 1.2 of this chapter, Modes of Operation). In one of these modes only the base architecture is available to programmers, whereas in the other mode a number of very powerful advanced features have been added, including support for virtual memory, multitasking, and a sophisticated protection mechanism. These advanced features are described in section 1.3 of this chapter. The 80286 base architecture was designed to support programming in high-level languages, such as Pascal, C or PL/M. The register set and instructions are well suited to compiler-generated code. The addressing modes (see section 2.4.3 in Chapter 2) allow efficient addressing of complex data structures, such as static and dynamic arrays, records, and arrays within records, which are commonly supported by high-level languages. The data types supported by the architecture include, along with bytes and words, high level language constructs such as strings, BCD, and floating point. The memory architecture of the 80286 was designed to support modular programming techniques. Memory is divided into segments, which may be of arbitrary size, that can be used to contain procedures and data structures. Segmentation has several advantages over more conventional linear memory architectures. It supports structured software, since segments can contain meaningful program units and data, and more compact code, since references within a segment can be shorter (and locality of reference usually insures that the next few references will be within the same segment). Segmentation also lends itself to efficient implementation of sophisticated memory management, virtual memory, and memory protection. In addition, new instructions have been added to the base architecture to give hardware support for procedure invocations, parameter passing, and array bounds checking. 1.2 Modes of Operation The 80286 can be operated in either of two different modes: Real Address Mode or Protected Virtual Address Mode (also referred to as Protected Mode). In either mode of operation, the 80286 represents an upwardly compatible addition to the 8086 family of processors. In Real Address Mode, the 80286 operates essentially as a very high-performance 8086. Programs written for the 8086 or the 80186 can be executed in this mode without any modification (the few exceptions are described in Appendix C, "Compatibility Considerations"). Such upward compatibility extends even to the object code level; for example, an 8086 program stored in read-only memory will execute successfully in 80286 Real Address Mode. An 80286 operating in Real Address Mode provides a number of instructions not found on the 8086. These additional instructions, also present with the 80186, allow for efficient subroutine linkage, parameter validation, index calculations, and block I/O transfers. The advanced architectural features and full capabilities of the 80286 are realized in its native Protected Mode. Among these features are sophisticated mechanisms to support data protection, system integrity, task concurrency, and memory management, including virtual storage. Nevertheless, even in Protected Mode, the 80286 remains upwardly compatible with most 8086 and 80186 application programs. Most 8086 applications programs can be re-compiled or re-assembled and executed on the 80286 in Protected Mode. 1.3 Advanced Features The architectural features described in section 1.1 of this chapter are common to both operating modes of the processor. In addition to these common features, Protected Mode provides a number of advanced features, including a greatly extended physical and logical address space, new instructions, and support for additional hardware-recognized data structures. The Protected Mode 80286 includes a sophisticated memory management and multilevel protection mechanism. Full hardware support is included for multitasking and task switching operations. 1.3.1 Memory Management The memory architecture of the Protected Mode 80286 represents a significant advance over that of the 8086. The physical address space has been increased from 1 megabyte to 16 megabytes (2^(24) bytes), while the virtual address space (i.e., the address space visible to a program) has been increased from 1 megabyte to 1 gigabyte (2^(30) bytes). Moreover, separate virtual address spaces are provided for each task in a multi-tasking system (see the next section, 1.3.2, "Task Management"). The 80286 supports on-chip memory management instead of relying on an external memory management unit. The one-chip solution is preferable because no software is required to manage an external memory management unit, performance is much better, and hardware designs are significantly simpler. Mechanisms have been included in the 80286 architecture to allow the efficient implementation of virtual memory systems. (In virtual memory systems, the user regards the combination of main and external storage as a single large memory. The user can write large programs without worrying about the physical memory limitations of the system. To accomplish this, the operating system places some of the user programs and data in external storage and brings them into main memory only as they are needed.) All instructions that can cause a segment-not-present fault are fully restartable. Thus, a not-present segment can be loaded from external storage, and the task can be restarted at the point where the fault occurred. The 80286, like all members of the 8086 series, supports a segmented memory architecture. The 80286 also fully integrates memory segmentation into a comprehensive protection scheme. This protection scheme includes hardware-enforced length and type checking to protect segments from inadvertent misuse. 1.3.2 Task Management The 80286 is designed to support multi-tasking systems. The architecture provides direct support for the concept of a task. For example, task state segments (see section 8.2 in Chapter 8) are hardware-recognized and hardware-manipulated structures that contain information on the current state of all tasks in the system. Very efficient context-switching (task-switching) can be invoked with a single instruction. Separate logical address spaces are provided for each task in the system. Finally, mechanisms exist to support intertask communication, synchronization, memory sharing, and task scheduling. Task Management is described in Chapter 8. 1.3.3 Protection Mechanisms The 80286 allows the system designer to define a comprehensive protection policy to be applied, uniformly and continuously, to all ongoing operations of the system. Such a policy may be desirable to ensure system reliability, privacy of data, rapid error recovery, and separation of multiple users. The 80286 protection mechanisms are based on the notion of a "hierarchy of trust." Four privilege levels are distinguished, ranging from Level 0 (most trusted) to Level 3 (least trusted). Level 0 is usually reserved for the operating system kernel. The four levels may be visualized as concentric rings, with the most privileged level in the center (see figure 1-1). This four-level scheme offers system reliability, flexibility, and design options not possible with the typical two-level (supervisor/user) separation provided by other processors. A four-level division is capable of separating kernel, executive, system services, and application software, each with different privileges. At any one time, a task executes at one of the four levels. Moreover, all data segments and code segments are also assigned to privilege levels. A task executing at one level cannot access data at a more privileged level, nor can it call a procedure at a less privileged level (i.e., trust a less privileged procedure to do work for it). Thus, both access to data and transfer of control are restricted in appropriate ways. A complete separation can exist between the logical address spaces local to different tasks, providing users with automatic protection against accidental or malicious interference by other users. The hardware also provides immediate detection of a number of fault and error conditions, a feature that can be useful in the development and maintenance of software. Finally, these protection mechanisms require relatively little system overhead because they are integrated into the memory management and protection hardware of the processor itself. Figure 1-1. Four Privilege Levels ‚ƒ € LEVEL 3 ‘‘‘‘‘‘‘‘Ξ‘‘LEAST TRUSTED € ‚ƒ € € € LEVEL 2 € € € € ‚ƒ € € € € € LEVEL 1 € € € € € € ‚ƒ € € € € € € € LEVEL 0 € € € € € € € €  € € € € € € € „Ο… € € € € € €  € € € € € „Ο… € € € €  € € € „Ο… € €  € „Ο…  ”MOST TRUSTED 1.3.4 Support for Operating Systems Most operating systems involve some degree of concurrency, with multiple tasks vying for system resources. The task management mechanisms described above provide the 80286 with inherent support for such multi-tasking systems. Moreover, the advanced memory management features of the 80286 allow the implementation of sophisticated virtual memory systems. Operating system implementors have found that a multi-level approach to system services provides better security and more reliable systems. For example, a very secure kernel might implement critical functions such as task scheduling and resource allocation, while less fundamental functions (such asI/O) are built around the kernel. This layered approach also makes program development and enhancement simpler and facilitates error detection and debugging. The 80286 supports the layered approach through its four-level privilege scheme. 1.4 Organization of This Book To facilitate the use of this book both as an introduction to the 80286 architecture and as a reference guide, the remaining chapters are divided into three major parts. Part I, comprising chapters 2 through 4, should be read by all those who wish to acquire a basic familiarity with the 80286 architecture. These chapters provide detailed information on memory segmentation, registers, addressing modes and the general (application level) 80286 instruction set. In conjunction with the 80286 Assembly Language Reference Manual, these chapters provide sufficient information for an assembly language programmer to design and write application programs. The chapters in Part I are: Chapter 2, "Architectural Features." This chapter discusses those features of the 80286 architecture that are significant for application programmers. The information presented can also function as an introduction to the machine for system programmers. Memory organization and segmentation, processor registers, addressing modes, and instruction formats are all discussed. Chapter 3, "Basic Instruction Set." This chapter presents the core instructions of the 8086 family. Chapter 4, "Extended Instruction Set." This chapter presents the extended instructions shared by the 80186 and 80286 processors. Part II of the book consists of a single chapter: Chapter 5, "Real Address Mode." This chapter presents the system programmer's view of the 80286 when the processor is operated in Real Address Mode. Part III of the book comprises chapters 6 through 11. Aimed primarily at system programmers, these chapters discuss the more advanced architectural features of the 80286, which are available when the processor is in Protected Mode. Details on memory management, protection mechanisms, and task switching are provided. The chapters in Part III are: Chapter 6, "Virtual Memory." This chapter describes the 80286 address translation mechanisms that support virtual memory. Segment descriptors, global and local descriptor tables, and descriptor caches are discussed. Chapter 7, "Protection." This chapter describes the protection features of the 80286. Privilege levels, segment attributes, access restrictions, and call gates are discussed. Chapter 8, "Tasks and State Transitions." This chapter describes the 80286 mechanisms that support concurrent tasks. Context-switching, task state segments, task gates, and interrupt tasks are discussed. Chapter 9, "Interrupts, Traps and Faults." This chapter describes interrupt and trap handling. Special attention is paid to the exception traps, or faults, which may occur in Protected Mode. Interrupt gates, trap gates, and the interrupt descriptor table are discussed. Chapter 10, "System Control and Initialization." This chapter describes the actual instructions used to implement the memory management, protection, and task support features of the 80286. System registers, privileged instructions, and the initial machine state are discussed. Chapter 11, "Advanced Topics." This chapter completes Part III with a description of several advanced topics, including special segment attributes and pointer validation. 1.5 Related Publications The following manuals also contain information of interest to programmers of 80287 systems: Ž Introduction to the 80286, order number 210308 Ž ASM286 Assembly Language Reference Manual, order number 121924 Ž 80286 Operating System Writer's Guide, order number 121960 Ž 80286 Hardware Reference Manual, order number 210760 Ž Microprocessor and Peripheral Handbook, order number 230843 Ž PL/M-286 User's Guide, order number 121945 Ž 80287 Support Library Reference Manual, order number 122129 Ž 8086 Software Toolbox Manual, order number 122203 (includes information about 80287 Emulator Software) Chapter 2 80286 Base Architecture ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ This chapter describes the 80286 application programming environment as seen by assembly language programmers. It is intended to introduce the programmer to those features of the 80286 architecture that directly affect the design and implementation of 80286 application programs. 2.1 Memory Organization and Segmentation The main memory of an 80286 system makes up its physical address space. This address space is organized as a sequence of 8-bit quantities, called bytes. Each byte is assigned a unique address ranging from 0 up to a maximum of 2^(20) (1 megabyte) in Real Address Mode, and up to 2^(24) (16 megabytes) in Protected Mode. A virtual address space is the organization of memory as viewed by a program. Virtual address space is also organized in units of bytes. (Other addressable units such as words, strings, and BCD digits are described below in section 2.2, "Data Types.") In Real Address Mode, as with the 8086 itself, programs view physical memory directly, inasmuch as they manipulate pure physical addresses. Thus, the virtual address space is identical to the physical address space (1 megabyte). In Protected Mode, however, programs have no direct access to physical addresses. Instead, memory is viewed as a much larger virtual address space of 2^(30) bytes (1 gigabyte). This 1 gigabyte virtual address is mapped onto the Protected Mode's 16-megabyte physical address space by the address translation mechanisms described in Chapter 6. The programmer views the virtual address space on the 80286 as a collection of up to sixteen thousand linear subspaces, each with a specified size or length. Each of these linear address spaces is called a segment. A segment is a logical unit of contiguous memory. Segment sizes may range from one byte up to 64K (65,536) bytes. 80286 memory segmentation supports the logical structure of programs and data in memory. Programs are not written as single linear sequences of instructions and data, but rather as modules of code and data. For example, program code may include a main routine and several separate procedures. Data may also be organized into various data structures, some private and some shared with other programs in the system. Run-time stacks constitute yet another data requirement. Each of these several modules of code and data, moreover, may be very different in size or vary dynamically with program execution. Segmentation supports this logical structure (see figure 2-1). Each meaningful module of a program may be separately contained in individual segments. The degree of modularization, of course, depends on the requirements of a particular application. Use of segmentation benefits almost all applications. Programs execute faster and require less space. Segmentation also simplifies the design of structured software. 2.2 Data Types Bytes and words are the fundamental units in which the 80286 manipulates data, i.e., the fundamental data types. A byte is 8 contiguous bits starting on an addressable byte boundary. The bits are numbered 0 through 7, starting from the right. Bit 7 is the most significant bit: 7 0 ’‘‘‘˜‘‘‘˜‘‘‘˜‘‘‘˜‘‘‘˜‘‘‘˜‘‘‘˜‘‘‘“  BYTE  ”‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘• A word is defined as two contiguous bytes starting on an arbitrary byte boundary; a word thus contains 16 bits. The bits are numbered 0 through 15, starting from the right. Bit 15 is the most significant bit. The byte containing bit 0 of the word is called the low byte; the byte containing bit 15 is called the high byte. 15 0 ’‘‘‘˜‘‘‘˜‘‘‘˜‘‘‘˜‘‘‘˜‘‘‘˜‘‘‘˜‘‘‘˜‘‘‘˜‘‘‘˜‘‘‘˜‘‘‘˜‘‘‘˜‘‘‘˜‘‘‘˜‘‘‘“  HIGH BYTE  LOW BYTE  ”‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘• LOCATION N + 1 LOCATION N Each byte within a word has its own particular address, and the smaller of the two addresses is used as the address of the word. The byte at this lower address contains the eight least significant bits of the word, while the byte at the higher address contains the eight most significant bits. The arrangement of bytes within words is illustrated in figure 2-2. Note that a word need not be aligned at an even-numbered byte address. This allows maximum flexibility in data structures (e.g., records containing mixed byte and word entries) and efficiency in memory utilization. Although actual transfers of data between the processor and memory take place at physically aligned word boundaries, the 80286 converts requests for unaligned words into the appropriate sequences of requests acceptable to the memory interface. Such odd aligned word transfers, however, may impact performance by requiring two memory cycles to transfer the word rather than one. Data structures (e.g., stacks) should therefore be designed in such a way that word operands are aligned on word boundaries whenever possible for maximum system performance. Due to instruction prefetching and queueing within the CPU, there is no requirement for instructions to be aligned on word boundaries and no performance loss if they are not. Although bytes and words are the fundamental data types of operands, the processor also supports additional interpretations on these bytes or words. Depending on the instruction referencing the operand, the following additional data types can be recognized: Integer: A signed binary numeric value contained in an 8-bit byte or a 16-bit word. All operations assume a 2's complement representation. (Signed 32- and 64-bit integers are supported using the 80287 Numeric Data Processor.) Ordinal: An unsigned binary numeric value contained in an 8-bit byte or 16-bit word. Pointer: A 32-bit address quantity composed of a segment selector component and an offset component. Each component is a 16-bit word. String: A contiguous sequence of bytes or words. A string may contain from 1 byte to 64K bytes. ASCII: A byte representation of alphanumeric and control characters using the ASCII standard of character representation. BCD: A byte (unpacked) representation of the decimal digits (0-9). Packed BCD: A byte (packed) representation of two decimal digits (0-9). One digit is stored in each nibble of the byte. Floating Point: A signed 32-, 64-, or 80-bit real number representation. (Floating operands are supported using the 80287 Numeric Processor Configuration.) Figure 2-3 graphically represents the data types supported by the 80286. 80286 arithmetic operations may be performed on five types of numbers: unsigned binary, signed binary (integers), unsigned packed decimal, unsigned unpacked decimal, and floating point. Binary numbers may be 8 or 16 bits long. Decimal numbers are stored in bytes; two digits per byte for packed decimal, one digit per byte for unpacked decimal. The processor always assumes that the operands specified in arithmetic instructions contain data that represent valid numbers for the type of instruction being performed. Invalid data may produce unpredictable results. Unsigned binary numbers may be either 8 or 16 bits long; all bits are considered in determining a number's magnitude. The value range of an 8-bit unsigned binary number is 0-255; 16 bits can represent values from 0 through 65,535. Addition, subtraction, multiplication and division operations are available for unsigned binary numbers. Signed binary numbers (integers) may be either 8 or 16 bits long. The high-order (leftmost) bit is interpreted as the number's sign: 0 = positive and 1 = negative. Negative numbers are represented in standard two's complement notation. Since the high-order bit is used for a sign, the range of an 8-bit integer is -128 through +127; 16-bit integers may range from -32,768 through +32,767. The value zero has a positive sign. Separate multiplication and division operations are provided for both signed and unsigned binary numbers. The same addition and subtraction instructions are used with signed or unsigned binary values. Conditional jump instructions, as well as an "interrupt on overflow" instruction, can be used following an unsigned operation on an integer to detect overflow into the sign bit. Unpacked decimal numbers are stored as unsigned byte quantities. One digit is stored in each byte. The magnitude of the number is determined from the low-order half-byte; hexadecimal values 0-9 are valid and are interpreted as decimal numbers. The high-order half-byte must be zero for multiplication and division; it may contain any value for addition and subtraction. Arithmetic on unpacked decimal numbers is performed in two steps. The unsigned binary addition, subtraction and multiplication operations are used to produce an intermediate result. An adjustment instruction then changes the value to a final correct unpacked decimal number. Division is performed similarly, except that the adjustment is carried out on the two digit numerator operand in register AX first, followed by an unsigned binary division instruction that produces a correct result. Unpacked decimal numbers are similar to the ASCII character representations of the digits 0-9. Note, however, that the high-order half-byte of an ASCII numeral is always 3. Unpacked decimal arithmetic may be performed on ASCII numeric characters under the following conditions: Ž the high-order half-byte of an ASCII numeral must be set to 0H prior to multiplication or division. Ž unpacked decimal arithmetic leaves the high-order half-byte set to 0H; it must be set to 3 to produce a valid ASCII numeral. Packed decimal numbers are stored as unsigned byte quantities. The byte is treated as having one decimal digit in each half-byte (nibble); the digit in the high-order half-byte is the most significant. Values 0-9 are valid in each half-byte, and the range of a packed decimal number is 0-99. Additions and subtractions are performed in two steps. First, an addition or subtraction instruction is used to produce an intermediate result. Then, an adjustment operation is performed which changes the intermediate value to a final correct packed decimal result. Multiplication and division adjustments are only available for unpacked decimal numbers. Pointers and addresses are described below in section 2.3.3, "Index, Pointer, and Base Registers," and in section 3.8, "Address Manipulation Instructions." Strings are contiguous bytes or words from 1 to 64K bytes in length. They generally contain ASCII or other character data representations. The 80286 provides string manipulation instructions to move, examine, or modify a string (see section 3.7, "Character Translation and String Instructions"). If the 80287 numeric processor extension (NPX) is present in the system ‘‘ see the 80287 NPX book‘‘the 80286 architecture also supports floating point numbers, 32- and 64-bit integers, and 18-digit BCD data types. The 80287 Numeric Data Processor supports and stores real numbers in a three-field binary format as required by IEEE standard 754 for floating point numerics (see figure 2-3). The number's significant digits are held in the significand field, the exponent field locates the binary point within the significant digits (and therefore determines the number's magnitude), and the sign field indicates whether the number is positive or negative. (The exponent and significand are analogous to the terms "characteristic" and "mantissa," typically used to describe floating point numbers on some computers.) This format is used by the 80287 with various length significands and exponents to support single precision, double precision and extended (80-bit) precision floating point data types. Negative numbers differ from positive numbers only in their sign bits. Figure 2-1. Segmented Virtual Memory ’‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ “ 20000‚ƒ 8000‚ƒ  €CS €  € € 8600‚ƒ € MAIN € € PROCEDURE A € € PROCEDURE €  € PROCEDURE €  € € € B € 0„… 0„… 0„…   ‚ƒ 72535‚ƒ ‚ƒ  €DS €  € € € € € DATA (MAIN) € € DATA (A) € € DATA (B) €  0„…  0„… 0„… 2000‚ƒ  €SS PROCESS €  € STACK €  0„…  ‚ƒ  €ES PROCESS-WIDE €  € DATA €  0„…  ”‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ • CURRENTLY ACCESSIBLE Figure 2-2. Bytes and Words in Memory BYTE ADDRESS All values in hexadecimal. MEMORY VALUES   †‡ E € € †‡ D € € †‡ C € FE €‘“ †‡ –‘ WORD AT ADDRESS B CONTAINS FE06 B € 06 €‘• †‡ A € € †‡‘“ 9 € 1F € –‘BYTE AT ADDRESS 9 CONTAINS 1F †‡‘• 8 € € †‡ 7 € 23 €‘“ †‡ –‘ WORD AT ADDRESS 6 CONTAINS 23OB 6 € OB €‘• †‡ 5 € € †‡ 4 € € †‡ 3 € 74 € ‘“ †‡‘“–‘ WORD AT ADDRESS 2 CONTAINS 74CB 2 € CB € ‘• †‡ –‘ WORD AT ADDRESS 1 CONTAINS CB31 1 € 31 €  †‡‘• 0 € € „… Figure 2-3. 80286/80287 Supported Data Types +1 0 7 0 7 0 15 14 8 7 0 SIGNED ‚ΠΠΠΠΠΠΠƒ UNSIGNED ‚ΠΠΠΠΠΠΠƒ SIGNED ‚ΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠƒ BYTE €  € BYTE €  € WORD €    € „€… „… „€€… SIGN BIT•”‘‘‘‘‘‘• ”MSB  SIGN BIT•”MSB  MAGNITUDE ”‘‘‘‘‘‘‘• ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘• MAGNITUDE MAGNITUDE +3 +2 +1 0 31 16 15 0 SIGNED DOUBLE WORD Supported by 80287 numeric data processor configuration. ‚ΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠƒ €        € „€€€€… SIGN BIT•”MBS  ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘• MAGNITUDE +7 +6 +5 +4 +3 +2 +1 0 63 48 47 32 31 16 15 0 SIGNED QUAD WORD Supported by 80287 numeric data processor configuration. ‚ЁΠΠΠΠΠΠΠƒ €        € „€€€€€€€€… SIGN BIT•”MSB  ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘• MAGNITUDE +1 0 15 0 UNSIGNED WORD ‚ΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠƒ €    € „€€… ”MSB  ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘• MAGNITUDE +N +1 0 7 0 7 0 7 0 BINARY CODED DECIMAL ‚ΠΠΠΠΠΠΠƒ ‚ΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠƒ (BCD) €  €  €    € „… „€… BCD BCD BCD DIGIT N DIGIT 1 DIGIT 0 +N +1 0 7 0 7 0 7 0 ASCII ‚ΠΠΠΠΠΠΠƒ ‚ΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠƒ €  €  €    € „… „€… ASCII ASCII ASCII CHARACTER[N] CHARACTER{1} CHARACTER{0} +N +1 0 7 0 7 0 7 0 PACKED BCD ‚ΠΠΠΠΠΠΠƒ ‚ΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠƒ €  €  €    € „… „€… ”‘‘‘• ”‘‘‘• MOST LEAST SIGNIFICANT SIGNIFICANT DIGIT DIGIT +N +1 0 7/15 0 7/15 0 7/15 0 STRING ‚ΠΠΠΠΠΠΠƒ ‚ΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠƒ €  €  €    € „… „€… BYTE/WORD N BYTE/WORD BYTE/WORD 1 0 +3 +2 +1 0 31 16 15 0 POINTER ‚ΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠƒ €        € „€€€€… ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘• SELECTOR OFFSET +9 +8 +7 +6 +5 +4 +3 +2 +1 0 79 0 FLOATING POINT Supported by 80287 numeric data processor configuration. ‚ЁΠΠΠΠΠΠΠΠΠƒ €          € „€€€€€€€€€€… SIGN BIT•”‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘• EXPONENT MAGNITUDE 2.3 Registers The 80286 contains a total of fourteen registers that are of interest to the application programmer. (Five additional registers used by system programmers are covered in section 10.1.) As shown in figure 2-4, these registers may be grouped into four basic categories: Ž General registers. These eight 16-bit general-purpose registers are used primarily to contain operands for arithmetic and logical operations. Ž Segment registers. These four special-purpose registers determine, at any given time, which segments of memory are currently addressable. Ž Status and Control registers. These three special-purpose registers are used to record and alter certain aspects of the 80286 processor state. 2.3.1 General Registers The general registers of the 80286 are the 16-bit registers AX, BX, CX, DX, SP, BP, SI, and DI. These registers are used interchangeably to contain the operands of logical and arithmetic operations. Some instructions and addressing modes (see section 2.4), however, dedicate certain general registers to specific uses. BX and BP are often used to contain the base address of data structures in memory (for example, the starting address of an array); for this reason, they are often referred to as the base registers. Similarly, SI and DI are often used to contain an index value that will be incremented to step through a data structure; these two registers are called the index registers. Finally, SP and BP are used for stack manipulation. Both SP and BP normally contain offsets into the current stack. SP generally contains the offset of the top of the stack and BP contains the offset or base address of the current stack frame. The use of these general-purpose registers for operand addressing is discussed in section 2.3.3, "Index, Pointer, and Base Registers." Register usage for individual instructions is discussed in chapters 3 and 4. As shown in figure 2-4, eight byte registers overlap four of the 16-bit general registers. These registers are named AH, BH, CH, and DH (high bytes); and AL, BL, CL, and DL (low bytes); they overlap AX, BX, CX, and DX. These registers can be used either in their entirety or as individual 8-bit registers. This dual interpretation simplifies the handling of both 8- and 16-bit data elements. Figure 2-4. 80286 Base Architecture Register Set 16-BIT SPECIAL REGISTER REGISTER NAME FUNCTIONS GENERAL REGISTERS 7 0 7 0 ’‘ ‚Πƒ‘“  AX € AH  AL €  BYTE  Γ‘‘‘‘‘‘š‘‘‘‘‘‘Β –‘MULTIPLY/DIVIDE ADDRESSABLE  DX € DH  DL €  I/O INSTRUCTIONS (8-BIT‘— Γ‘‘‘‘‘‘š‘‘‘‘‘‘Α REGISTER  CX € CH  CL € –‘LOOP/SHIFT/REPEAT COUNT NAMES  Γ‘‘‘‘‘‘š‘‘‘‘‘‘Α SHOWN)  BX € BH  BL €  ”‘ Γ‘‘‘‘‘‘™‘‘‘‘‘‘Β –‘BASE REGISTERS BP € €  Γ‘‘‘‘‘‘‘‘‘‘‘‘‘Α SI € €  Γ‘‘‘‘‘‘‘‘‘‘‘‘‘Β –‘INDEX REGISTERS DI € €  Γ‘‘‘‘‘‘‘‘‘‘‘‘‘Α SP € € –‘STACK POINTER „…‘• 15 0 SEGMENT REGISTERS 15 0 ‚ƒ CS € € CODE SEGMENT SELECTOR Γ‘‘‘‘‘‘‘‘‘‘‘‘‘Β DS € € DATA SEGMENT SELECTOR Γ‘‘‘‘‘‘‘‘‘‘‘‘‘Β SS € € STACK SEGMENT SELECTOR Γ‘‘‘‘‘‘‘‘‘‘‘‘‘Β ES € € EXTRA SEGMENT SELECTOR „… STATUS AND CONTROL 15 0 REGISTERS ‚ƒ F € € FLAGS Γ‘‘‘‘‘‘‘‘‘‘‘‘‘Β IP € € INSTRUCTION POINTER Γ‘‘‘‘‘‘‘‘‘‘‘‘‘Β MSW € € MACHINE STATUS WORD „… 2.3.2 Memory Segmentation and Segment Registers Complete programs generally consist of many different code modules (or segments), and different types of data segments. However, at any given time during program execution, only a small subset of a program's segments are actually in use. Generally, this subset will include code, data, and possibly a stack. The 80286 architecture takes advantage of this by providing mechanisms to support direct access to the working set of a program's execution environment and access to additional segments on demand. At any given instant, four segments of memory are immediately accessible to an executing 80286 program. The segment registers DS, ES, SS, and CS are used to identify these four current segments. Each of these registers specifies a particular kind of segment, as characterized by the associated mnemonics ("code," "stack," "data," or "extra") shown in figure 2-4. An executing program is provided with concurrent access to the four individual segments of memory‘‘a code segment, a stack segment, and two data segments‘‘by means of the four segment registers. Each may be said to select a segment, since it uniquely determines the one particular segment from among the numerous segments in memory, which is to be immediately accessible at highest speed. Thus, the 16-bit contents of a segment register is called a segment selector. Once a segment is selected, a base address is associated with it. To address an element within a segment, a 16-bit offset from the segment's base address must be supplied. The 16-bit segment selector and the 16-bit offset taken together form the high and low order halves, respectively, of a 32-bit virtual address pointer. Once a segment is selected, only the lower 16-bits of the pointer, called the offset, generally need to be specified by an instruction. Simple rules define which segment register is used to form an address when only a 16-bit offset is specified. An executing program requires, first of all, that its instructions reside somewhere in memory. The segment of memory containing the currently executing sequence of instructions is known as the current code segment; it is specified by means of the CS register. All instructions are fetched from this code segment, using as an offset the contents of the instruction pointer (IP). The CS:IP register combination therefore forms the full 32-bit pointer for the next sequential program instruction. The CS register is manipulated indirectly. Transitions from one code segment to another (e.g., a procedure call) are effected implicitly as the result of control-transfer instructions, interrupts, and trap operations. Stacks play a fundamental role in the 80286 architecture; subroutine calls, for example, involve a number of implicit stack operations. Thus, an executing program will generally require a region of memory for its stack. The segment containing this region is known as the current stack segment, and it is specified by means of the SS register. All stack operations are performed within this segment, usually in terms of address offsets contained in the stack pointer (SP) and stack frame base (BP) registers. Unlike CS, the SS register can be loaded explicitly for dynamic stack definition. Beyond their code and stack requirements, most programs must also fetch and store data in memory. The DS and ES registers allow the specification of two data segments, each addressable by the currently executing program. Accessibility to two separate data areas supports differentiation and access requirements like local procedure data and global process data. An operand within a data segment is addressed by specifying its offset either directly in an instruction or indirectly via index and/or base registers (described in the next subsection). Depending on the data structure (e.g., the way data is parceled into one or more segments), a program may require access to multiple data segments. To access additional segments, the DS and ES registers can be loaded under program control during the course of a program's execution. This simply requires loading the appropriate data pointer prior to accessing the data. The interpretation of segment selector values depends on the operating mode of the processor. In Real Address Mode, a segment selector is a physical address (figure 2-5). In Protected Mode, a segment selector selects a segment of the user's virtual address space (figure 2-6). An intervening level of logical-to-physical address translation converts the logical address to a physical memory address. Chapter 6, "Memory Management," provides a detailed discussion of Protected Mode addressing. In general, considerations of selector formats and the details of memory mapping need not concern the application programmer. 2.3.3 Index, Pointer, and Base Registers Five of the general-purpose registers are available for offset address calculations. These five registers, shown in figure 2-4, are SP, BP, BX, SI, and DI. SP is called a pointer register; BP and BX are called base registers; SI and DI are called index registers. As described in the previous section, segment registers define the set of four segments currently addressable by a program. A pointer, base, or index register may contain an offset value relative to the start of one of these segments; it thereby points to a particular operand's location within that segment. To allow for efficient computations of effective address offsets, all base and index registers may participate interchangeably as operands in most arithmetical operations. Stack operations are facilitated by the stack pointer (SP) and stack frame base (BP) registers. By specifying offsets into the current stack segment, each of these registers provides access to data on the stack. The SP register is the customary top-of-stack pointer, addressing the uppermost datum on a push-down stack. It is referenced implicitly by PUSH and POP operations, subroutine calls, and interrupt operations. The BP register provides yet another offset into the stack segment. The existence of this stack relative base register, in conjunction with certain addressing modes described in section 2.4.3, is particularly useful for accessing data structures, variables and dynamically allocated work space within the stack. Stacks in the 80286 are implemented in memory and are located by the stack segment register (SS) and the stack pointer register (SP). A system may have an unlimited number of stacks, and a stack may be up to 64K bytes long, the maximum length of a segment. One stack is directly addressable at a time; this is the current stack, often referred to simply as "the" stack. SP contains the current top of the stack (TOS). In other words, SP contains the offset to the top of the push down stack from the stack segment's base address. Note, however, that the stack's base address (contained in SS) is not the "bottom" of the stack (figure 2-7). 80286 stack entries are 16 bits wide. Instructions operate on the stack by adding and removing stack items one word at a time. An item is pushed onto the stack (see figure 2-8) by decrementing SP by 2 and writing the item at the new TOS. An item is popped off the stack by copying it from TOS and then incrementing SP by 2. In other words, the stack grows down in memory toward its base address. Stack operations never move items on the stack; nor do they erase them. The top of the stack changes only as a result of updating the stack pointer. The stack frame base pointer (BP) is often used to access elements on the stack relative to a fixed point on the stack rather than relative to the current TOS. It typically identifies the base address of the current stack frame established for the current procedure (figure 2-9). If an index register is used relative to BP (e.g., base + index addressing mode using BP as the base), the offset will be calculated automatically in the current stack segment. Accessing data structures in data segments is facilitated by the BX register, which has the same function in addressing operands within data segments that BP does for stack segments. They are called base registers because they may contain an offset to the base of a data structure. The similar usage of these two registers is especially important when discussing addressing modes (see section 2.4, "Addressing Modes"). Operations on data are also facilitated by the SI and DI registers. By specifying an offset relative to the start of the currently addressable data segment, an index register can be used to address an operand in the segment. If an index register is used in conjunction with the BX base register (i.e., base + index addressing) to form an offset address, the data is also assumed to reside in the current data segment. As a rule, data referenced through an index register or BX is presumed to reside in the current data segment. That is, if an instruction invokes addressing for one of its operands using either BX, DI, SI, or BX with SI or DI, the contents of the register(s) (BX, DI, or SI) implicitly specify an offset in the current data segment. As previously mentioned, data referenced via SP, BP or BP with SI or DI implicitly specify an operand in the current stack segment (refer to table 2-1). There are two exceptions to the rules listed above. The first concerns the operation of certain 80286 string instructions. For the most flexibility, these instructions assume that the DI register addresses destination strings not in the data segment, but rather in the extra segment (ES register). This allows movement of strings between different segments. This has led to the descriptive names "source index" and "destination index." In all cases other than string instructions, however, the SI and DI registers may be used interchangeably to reference either source or destination operands. A second more general override capability allows the programmer complete control of which segment is used for a specific operation. Segment-override prefixes, discussed in section 2.4.3, allow the index and base registers to address data in any of the four currently addressable segments. Table 2-1. Implied Segment Usage by Index, Pointer, and Base Registers Register Implied Segment SP SS BP SS BX DS DI DS, ES for String Operations BP + SI, DI SS BX + SI, DI DS ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ NOTE All implied Segment usage, except SP to SS and DI to ES for String Operations, may be explicitly specified with a segment override prefix for any of the four segments. The prefix precedes the instruction for which explicit reference is desired. ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Figure 2-5. Real Address Mode Segment Selector Interpretation ‚ƒ‘“ € €  € €  ’‘†‡  1 MEGABYTE SEGMENT 64K BYTES ‘— € SEG 1 € –‘ PHYSICAL ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘”‘†‡  ADDRESS  BASE ADDRESS € €  SPACE  € €  ‚€Πƒ € €  € SELECTOR  0000 € „…‘• „€… ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ NOTES: 1. The selector inentifies a segment in physical memory. 2. A selector specifies the segments base address, Modulo 16, within the 1 Megabyte address space. 3. The selector is the 16 most significant bits of a segments physical base address. 4. The values of selectors determines the amount they overlap in real memory. 5. Segments may overlap by increments of 16 bytes. Overlap ranges from complete (SEG 1 = SEG 1) to none (SEG 1 Ο SEG 2 ± 64K). ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Figure 2-6. Protected Mode Segment Selector Interpretation ‚ƒ‘“ € SEG 3FFF €  †‡  € SEG 3FFE €  ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘†‡  ‚€ƒ € SEG 3FFD €  € SELECTOR € ’‘†‡  „… 1 TO 64K BYTES‘— € SEG 3FFC €  ”‘†‡  € SEG 3FFB €  †‡  1 GIGABYTE Έ Έ –‘ VIRTUAL †‡  ADDRESS € SEG 4 €  SPACE †‡  € SEG 3 €  †‡  € SEG 2 €  †‡  € SEG 1 €  †‡  € SEG 0 €  „…‘• ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ NOTES: 1. A selector uniquely identifies (names) one of 16K possible segments in the task's virtual address space. 2. The selector value does not specify the segment's location in physical memory. 3. The selector does not imply any overlap with other segments (This depends on the base address of the segment via the memory management and protection information). ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Figure 2-7. 80286 Stack ‚ƒ LOGICAL € €‘‘‘ BOTTOM OF STACK †‡ (initial SP value) € € †‡ € € †‡ € €  POP-UP †‡  ’‘‘‘‘‘‘‘‘‘‘‘€ €‘‘‘ LOGICAL TOP OF STACK  †‡   € €  PUSH-DOWN ‚Π€ƒ € € € SS  SP € € € „Π€… € €  € €  € €  € € ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘„… STACK SEGMENT BASE ADDRESS Figure 2-8. Stack Operation STACK OPERATION FOR CODE SEQUENCE: PUSH AX STACK POP AX SEGMENT POP BX ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘“    EXISTING STACK Γ‘‘‘‘‘‘‘‘‘Β  BOTTOM  BEFORE PUSH  1062 € 0 0 0 0 €  OF ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘• Γ‘‘‘‘‘‘‘‘‘Β  STACK 1060 € 1 1 1 1 € Γ‘‘‘‘‘‘‘‘‘Β 105E € 2 2 2 2 € Γ‘‘‘‘‘‘‘‘‘Β 105C € 3 3 3 3 € Γ‘‘‘‘‘‘‘‘‘Β 105A € 4 4 4 4 € Γ‘‘‘‘‘‘‘‘‘Β ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘ 1058 € 5 5 5 5 € SS  SP Γ‘‘‘‘‘‘‘‘‘Β‘“ ‚Π€ƒ 1056 € 6 6 6 6 €  € SELECTOR  OFFSET € Γ‘‘‘‘‘‘‘‘‘Β  NOT „Π€… 1054 € 7 7 7 7 € –‘ PRESENTLY  Γ‘‘‘‘‘‘‘‘‘Β  USED  1052 € 8 8 8 8 €   Γ‘‘‘‘‘‘‘‘‘Β‘•  1050 € 9 9 9 9 €  Έ Έ ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ 0000 Γ‘‘‘‘‘‘‘‘‘Β   STACK SEGMENT   Γ‘‘‘‘‘‘‘‘‘Β 1062 € 0 0 0 0 € Γ‘‘‘‘‘‘‘‘‘Β 1060 € 1 1 1 1 € Γ‘‘‘‘‘‘‘‘‘Β 105E € 2 2 2 2 € Γ‘‘‘‘‘‘‘‘‘Β 105C € 3 3 3 3 € Γ‘‘‘‘‘‘‘‘‘Β 105A € 4 4 4 4 € PUSH AX Γ‘‘‘‘‘‘‘‘‘Β‚ƒ ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘ 1058 € 5 5 5 5 €€ A A A A € SS  SP Γ‘‘‘‘‘‘‘‘‘Β„Π… ‚Π€ƒ 1056 € A A A A €‘‘• € SELECTOR  OFFSET € Γ‘‘‘‘‘‘‘‘‘Β „Π€… 1054 € 7 7 7 7 €  Γ‘‘‘‘‘‘‘‘‘Β  1052 € 8 8 8 8 €  Γ‘‘‘‘‘‘‘‘‘Β  1050 € 9 9 9 9 €  Έ Έ ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ 0000 Γ‘‘‘‘‘‘‘‘‘Β   STACK SEGMENT   Γ‘‘‘‘‘‘‘‘‘Β 1062 € 0 0 0 0 € Γ‘‘‘‘‘‘‘‘‘Β 1060 € 1 1 1 1 € Γ‘‘‘‘‘‘‘‘‘Β 105E € 2 2 2 2 € Γ‘‘‘‘‘‘‘‘‘Β POP BX 105C € 3 3 3 3 € ‚ƒ Γ‘‘‘‘‘‘‘‘‘Β € 5 5 5 5 € 105A € 4 4 4 4 € „… Γ‘‘‘‘‘‘‘‘‘Β  ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘ 1058 € 5 5 5 5 €‘‘‘‘‘‘• SS  SP Γ‘‘‘‘‘‘‘‘‘Β ‚Π€ƒ 1056 € A A A A €‘‘‘‘‘‘“ € SELECTOR  OFFSET € Γ‘‘‘‘‘‘‘‘‘Β  „Π€… 1054 € 7 7 7 7 € ‚ƒ  Γ‘‘‘‘‘‘‘‘‘Β € A A A A €  1052 € 8 8 8 8 € „…  Γ‘‘‘‘‘‘‘‘‘Β POP AX  1050 € 9 9 9 9 €  Έ Έ ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ 0000 Γ‘‘‘‘‘‘‘‘‘Β   Figure 2-9. BP Usage as a Stack Frame Base Pointer BP is a constant pointer to stack based variables and work space. All references use BP and are independent of SP, which may vary during a routine execution. PROC N PUSH AX PUSH ARRAY_SIZE CALL PROC_N 1 ‘‘‘‘‘‘‘‘‘ PROC_N+1 ‘‘‘‘‘‘‘“ PUSH BP  PUSH CX  MOVE BP, SP  SUB SP, WORK_SPACE  ¨  ¨  ¨  "PROCEDURE BODY"  ¨  ¨  ¨  MOV SP, BP  POP CX  POP BP ”‘‘‘ RET   †‡‘“ € PARAMETERS €  Γ‘‘‘‘‘‘‘‘‘‘‘‘‘Β  € RETURN ADDR €  Γ‘‘‘‘‘‘‘‘‘‘‘‘‘Β –‘PROCEDURE N ‚  ƒ € REGISTERS €  STACK FRAME BP ‘‘‘‘‘‘‘‘‘Γ‘‘‘‘‘‘‘‘‘‘‘‘‘Β  „  … € €  PROCEDURE  € WORK_SPACE €  N+1 STACK BOTTOM  Γ‘‘‘‘‘‘‘‘‘‘‘‘‘Α FRAME OF  € PARAMETERS € –‘‘‘‘‘‘• STACK  Γ‘‘‘‘‘‘‘‘‘‘‘‘‘Β  DYNAMICALLY € RETURN ADDR €  ALLOCATED Γ‘‘‘‘‘‘‘‘‘‘‘‘‘Β  ON DEMAND ‚ƒ € REGISTERS €  RATHER THAN € BP Γ‘‘‘‘‘‘‘‘‘Γ‘‘‘‘‘‘‘‘‘‘‘‘‘Β “STATICALLY „… € € –‘‘‘‘‘• € WORK_SPACE €  ’‘ ‘‘ ‘‘ ‘‘ ‘Γ‘‘‘‘‘‘‘‘‘‘‘‘‘Β‘•• ‘‘‘“ –‘ ‘‘ ‘‘ ‘‘ ‘€ € TOP OF STACK ‚Π€ƒ € € € SS  SP € „… STACK SEGMENT BASE „€… 2.3.4 Status and Control Registers Two status and control registers are of immediate concern to applications programmers: the instruction pointer and the FLAGS registers. The instruction pointer register (IP) contains the offset address, relative to the start of the current code segment, of the next sequential instruction to be executed. Together, the CS:IP registers thus define a 32-bit program-counter. The instruction pointer is not directly visible to the programmer; it is controlled implicitly, by interrupts, traps, and control-transfer operations. The FLAGS register encompasses eleven flag fields, mostly one-bit wide, as shown in figure 2-10. Six of the flags are status flags that record processor status information. The status flags are affected by the execution of arithmetic and logical instructions. The carry flag is also modifiable with instructions that will clear, set or complement this flag bit. See Chapters 3 and 4. The carry flag (CF) generally indicates a carry or borrow out of the most significant bit of an 8- or 16-bit operand after performing an arithmetic operation; this flag is also useful for bit manipulation operations involving the shift and rotate instructions. The effect on the remaining status flags, when defined for a particular instruction, is generally as follows: the zero flag (ZF) indicates a zero result when set; the sign flag (SF) indicates whether the result was negative (SF=1) or positive (SF=0); when set, the overflow flag (OF) indicates whether an operation results in a carry into the high order bit of the result but not a carry out of the high-order bit, or vice versa; the parity flag (PF) indicates whether the modulo 2 sum of the low-order eight bits of the operation is even (PF=0) or odd (PF=1) parity. The auxiliary carry flag (AF) represents a carry out of or borrow into the least significant 4-bit digit when performing binary coded decimal (BCD) arithmetic. The FLAGS register also contains three control flags that are used, under program control, to direct certain processor operations. The interrupt-enable flag (IF), if set, enables external interrupts; otherwise, interrupts are disabled. The trap flag (TF), if set, puts the processor into a single-step mode for debugging purposes where the target program is automatically interrupted to a user supplied debug routine after the execution of each target program instruction. The direction flag (DF) controls the forward or backward direction of string operations: 0 = forward or auto increment the address register(s) (SI, DI or SI and DI), 1 = backward or auto-decrement the address register(s) (SI, DI or SI and DI). In general, the interrupt enable flag may be set or reset with special instructions (STI = set, CLI = clear) or by placing the flags on the stack, modifying the stack, and returning the flag image from the stack to the flag register. If operating in Protected Mode, the ability to alter the IF bit is subject to protection checks to prevent non-privileged programs from effecting the interrupt state of the CPU. This applies to both instruction and stack options for modifying the IF bit. The TF flag may only be modified by copying the flag register to the stack, setting the TF bit in the stack image, and returning the modified stack image to the flag register. The trap interrupt occurs on completion of the next instruction. Entry to the single step routine saves the flag register on the stack with the TF bit set, and resets the TF bit in the register. After completion of the single step routine, the TF bit is automatically set on return to the program being single stepped to interrupt the program again after completion of the next instruction. Use of TF is not inhibited by the protection mechanism in Protected Mode. The DF flag, like the IF flag, is controlled by instructions (CLD = clear, STD = set) or flag register modification through the stack. Typically, routines that use string instructions will save the flags on the stack, modify DF as necessary via the instructions provided, and restore DF to its original state by restoring the Flag register from the stack before returning. Access or control of the DF flag is not inhibited by the protection mechanism in Protected Mode. The Special Fields bits are only relevant in Protected Mode. Real Address Mode programs should treat these bits as don't-care's, making no assumption about their status. Attempts to modify the IOPL and NT fields are subject to protection checking in Protected Mode. In general, the application's programmer will not be able to and should not attempt to modify these bits. (See section 10.3, "Privileged and Trusted Instructions" for more details.) Figure 2-10. Flags Register STATUS FLAGS: CARRY‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“ PARITY‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“  AUXILLIARY CARRY‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“   ZERO‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“    SIGN‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“     OVERFLOW‘‘‘‘‘‘‘‘‘‘‘‘“            15 14 13 1211 10 9 8 7 6 5 4 3 2 1 0 ‚ΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠƒ FLAGS:€œœNTIOPL OFDFIFTFSFZFœœAFœœPFœœCF€ „€€€€€€€€€€€€€€€…           CONTROL FLAGS:     ”‘‘‘‘‘‘‘‘‘‘‘TRAP FLAG    ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘INTERRUPT ENABLE   ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘DIRECTION FLAG   SPECIAL FIELDS:  ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘I/O PRIVILEGE LEVEL ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘NESTED TASK FLAG 2.4 Addressing Modes The information encoded in an 80286 instruction includes a specification of the operation to be performed, the type of the operands to be manipulated, and the location of these operands. If an operand is located in memory, the instruction must also select, explicitly or implicitly, which of the currently addressable segments contains the operand. This section covers the operand addressing mechanisms; 80286 operators are discussed in Chapter 3. The five elements of a general instruction are briefly described below. The exact format of 80286 instructions is specified in Appendix B. Ž The opcode is present in all instructions; in fact, it is the only required element. Its principal function is the specification of the operation performed by the instruction. Ž A register specifier. Ž The addressing mode specifier, when present, is used to specify the addressing mode of an operand for referencing data or performing indirect calls or jumps. Ž The displacement, when present, is used to compute the effective address of an operand in memory. Ž The immediate operand, when present, directly specifies one operand of the instruction. Of the four elements, only one, the opcode, is always present. The other elements may or may not be present, depending on the particular operation involved and on the location and type of the operands. 2.4.1 Operands Generally speaking, an instruction is an operation performed on zero, one, or two operands, which are the data manipulated by the instruction. An operand can be located either in a register (AX, BX, CX, DX, SI, DI, SP, or BP in the case of 16-bit operands; AH, AL, BH, BL, CH, CL, DH, or DL in the case of 8-bit operands; the FLAG register for flag operations in the instruction itself (as an immediate operand)), or in memory or an I/O port. Immediate operands and operands in registers can be accessed more rapidly than operands in memory since memory operands must be fetched from memory while immediate and register operands are available in the processor. An 80286 instruction can reference zero, one, or two operands. The three forms are as follows: Ž Zero-operand instructions, such as RET, NOP, and HLT. Consult Appendix B. Ž One-operand instructions, such as INC or DEC. The location of the single operand can be specified implicitly, as in AAM (where the register AX contains the operand), or explicitly, as in INC (where the operand can be in any register or memory location). Explicitly specified operands are accessed via one of the addressing modes described in section 2.4.2. Ž Two operand instructions such as MOV, ADD, XOR, etc., generally overwrite one of the two participating operands with the result. A distinction can thus be made between the source operand (the one left unaffected by the operation) and the destination operand (the one overwritten by the result). Like one-operand instructions, two-operand instructions can specify the location of operands either explicitly or implicitly. If an instruction contains two explicitly specified operands, only one of them‘‘either the source or the destination‘‘can be in a register or memory location. The other operand must be in a register or be an immediate source operand. Special cases of two-operand instructions are the string instructions and stack manipulation. Both operands of some string instructions are in memory and are explicitly specified. Push and pop stack operations allow transfer between memory operands and the memory based stack. Thus, the two-operand instructions of the 80286 permit operations of the following sort: Ž Register-to-register Ž Register-to-memory Ž Memory-to-register Ž Immediate-to-register Ž Immediate-to-memory Ž Memory-to-memory Instructions can specify the location of their operands by means of eight addressing modes, which are described in sections 2.4.2 and 2.4.3. 2.4.2 Register and Immediate Modes Two addressing modes are used to reference operands contained in registers and instructions: Ž Register Operand Mode. The operand is located in one of the 16-bit registers (AX, BX, CX, DX, SI, DI, SP, or BP) or in one of the 8-bit general registers (AH, BH, CH, DH, AL, BL, CL, or DL). Special instructions are also included for referencing the CS, DS, ES, SS, and Flag registers as operands also. Ž Immediate Operand Mode. The operand is part of the instruction itself (the immediate operand element). 2.4.3 Memory Addressing Modes Six modes are used to access operands in memory. Memory operands are accessed by means of a pointer consisting of a segment selector (see section 2.3.2) and an offset, which specifies the operand's displacement in bytes from the beginning of the segment in which it resides. Both the segment selector component and the offset component are 16-bit values. (See section 2.1 for a discussion of segmentation.) Only some instructions use a full 32-bit address. Most memory references do not require the instruction to specify a full 32-bit pointer address. Operands that are located within one of the currently addressable segments, as determined by the four segment registers (see section 2.3.2, "Segment Registers"), can be referenced very efficiently simply by means of the 16-bit offset. This form of address is called by short address. The choice of segment (CS, DS, ES, or SS) is either implicit within the instruction itself or explicitly specified by means of a segment override prefix (see below). See figure 2-11 for a diagram of the addressing process. 2.4.3.1 Segment Selection All instructions that address operands in memory must specify the segment and the offset. For speed and compact instruction encoding, segment selectors are usually stored in the high speed segment registers. An instruction need specify only the desired segment register and an offset in order to address a memory operand. Most instructions need not explicitly specify which segment register is used. The correct segment register is automatically chosen according to the rules of table 2-1 and table 2-2. These rules follow the way programs are written (see figure 2-12) as independent modules that require areas for code and data, a stack, and access to external data areas. There is a close connection between the type of memory reference and the segment in which that operand resides (see the next section for a discussion of how memory addressing mode calculations are performed). As a rule, a memory reference implies the current data segment (i.e., the implicit segment selector is in DS) unless the BP register is involved in the address specification, in which case the current stack segment is implied (i.e, SS contains the selector). The 80286 instruction set defines special instruction prefix elements (see Appendix B). One of these is SEG, the segment-override prefix. Segment-override prefixes allow an explicit segment selection. Only in two special cases‘‘namely, the use of DI to reference destination strings in the ES segment, and the use of SP to reference stack locations in the SS segment‘‘is there an implied segment selection which cannot be overridden. The format of segment override prefixes is shown in Appendix B. Table 2-2 Segment Register Selection Rules Memory Reference Segment Register Implicit Segment Needed Used Selection Rule Instructions Code (CS) Automatic with instruction prefetch. Stack Stack (SS) All stack pushes and pops. Any memory reference which uses BP as a base register. Local Data Data (DS) All data references except when relative to stack or string destination. External (Global) Extra (ES) Alternate data segment Data and destination of string operation. Figure 2-11. Two-Component Address   POINTER € € ’‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘“ †‡‘“ ‚Πƒ € €  € SEGMENT  OFFSET € € €  „€… € €  31 16 15 0 Γ‘‘‘‘‘‘‘‘‘‘‘‘‘Β  ”‘‘‘‘˜‘‘‘‘• ”‘‘‘‘˜‘‘‘‘• € OPERAND €  SELECTED   € SELECTED € –‘ SEGMENT  ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Γ‘‘‘‘‘‘‘‘‘‘‘‘‘Β   € €   € €   € €   € €  ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘†‡‘• € €  MEMORY  2.4.3.2 Offset Computation The offset within the desired segment is calculated in accordance with the desired addressing mode. The offset is calculated by taking the sum of up to three components: Ž the displacement element in the instruction Ž the base (contents of BX or BP‘‘a base register) Ž the index (contents of SI or DI‘‘an index register) Each of the three components of an offset may be either a positive or negative value. Offsets are calculated modulo 2^(16). The six memory addressing modes are generated using various combinations of these three components. The six modes are used for accessing different types of data stored in memory: addressing mode offset calculation direct address displacement alone register indirect base or index alone based base + displacement indexed index + displacement based indexed base + index based indexed with displacement base + index + disp In all six modes, the operand is located at the specified offset within the selected segment. All displacements, except direct address mode, are optionally 8- or 16-bit values. 8-bit displacements are automatically sign-extended to 16 bits. The six addressing modes are described and demonstrated in the following section on memory addressing modes. Figure 2-12. Use of Memory Segmentation ’‘ ‘‘ ‘“ ‚ƒ € CODE € Γ‘‘‘‘‘‘Β MODULE A € DATA € „… CPU   ’‘‘‘‘‘‘‘‘‘‘‘“ ‚ƒ  ‚ƒ  € CODE €  € CODE Γ‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Γ‘‘‘‘‘‘Β MODULE B  Γ‘‘‘‘‘‘‘Β  € DATA €  € DATA Γ‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘„…  Γ‘‘‘‘‘‘‘Β     € STACK Γ‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“ ‚ƒ  Γ‘‘‘‘‘‘‘Β   € € PROCESS STACK  € EXTRA Γ‘š‘‘‘‘‘‘‘‘‘‘‘“ ”‘‘‘‘‘‘‘‘‘„…  „…      SEGMENT   ‚ƒ PROCESS  REGISTERS   € € DATA ”‘‘‘‘‘‘‘‘‘‘‘• ”‘‘‘‘‘‘‘‘‘‘‘‘‘„… BLOCK 1   ‚ƒ PROCESS € € DATA „… BLOCK 2 ”‘ ‘‘ ‘• MEMORY 2.4.3.3 Memory Mode Two modes are used for simple scalar operands located in memory: Ž Direct Address Mode. The offset of the operand is contained in the instruction as the displacement element. The offset is a 16-bit quantity. Ž Register Indirect Mode. The offset of the operand is in one of the registers SI, DI, or BX. (BP is excluded; if BP is used as a stack frame base, it requires an index or displacement component to reference either parameters passed on the stack or temporary variables allocated on the stack. The instruction level bit encoding for the BP only address mode is used to specify Direct Address mode.) The following four modes are used for accessing complex data structures in memory (see figure 2-13): Ž Based Mode. The operand is located within the selected segment at an offset computed as the sum of the displacement and the contents of a base register (BX or BP). Based mode is often used to access the same field in different copies of a structure (often called a record). The base register points to the base of the structure (hence the term "base" register), and the displacement selects a particular field. Corresponding fields within a collection of structures can be accessed simply by changing the base register. (See figure 2-13, example 1.) Ž Indexed Mode. The operand is located within the selected segment at an offset computed as the sum of the displacement and the contents of an index register (SI or DI). Indexed mode is often used to access elements in a static array (e.g., an array whose starting location is fixed at translation time). The displacement locates the beginning of the array, and the value of the index register selects one element. Since all array elements are the same length, simple arithmetic on the index register will select any element. (See figure 2-13, example 2.) Ž Based Indexed Mode. The operand is located within the selected segment at an offset computed as the sum of the base register's contents and an index register's contents. Based Indexed mode is often used to access elements of a dynamic array (i.e., an array whose base address can change during execution). The base register points to the base of the array, and the value of the index register is used to select one element. (See figure 2-13, example 3.) Ž Based Indexed Mode with Displacement. The operand is located with the selected segment at an offset computed as the sum of a base register's contents, an index register's contents, and the displacement. This mode is often used to access elements of an array within a structure. For example, the structure could be an activation record (i.e., a region of the stack containing the register contents, parameters, and variables associated with one instance of a procedure); and one variable could be an array. The base register points to the start of the activation record, the displacement expresses the distance from the start of the record to the beginning of the array variable, and the index register selects a particular element of the array. (See figure 2-13, example 4.) Table 2-3 gives a summary of all memory operand addressing options. Table 2-3. Memory Operand Addressing Modes Addressing Mode Offset Calculation Direct 16-bit Displacement in the instruction Register Indirect BX, SI, DI Based (BX or BP) + Displacement The displacement can be a 0, 8 or 16-bit value. Indexed (SI or DI) + Displacement The displacement can be a 0, 8 or 16-bit value. Based Indexed (BX or BP) + (SI or DI) Based Indexed + Displacement (BX or BP) + (SI or DI) + Displacement The displacement can be a 0, 8 or 16-bit value. Figure 2-13. Complex Addressing Modes 1. BASED MODE 2. INDEXED MODE MOV AX, [BP + DATE_CODE] MOV ID[SI], DX ADD[BX + BALANCE], CX SUB BX, DATA_TBL[SI]     F †‡‘“ †‡‘“ I € €  € €  X ‚ƒ Γ‘‘‘‘‘‘‘‘‘‘‘Β  ‚ƒ Γ‘‘‘‘‘‘‘‘‘‘‘Β  E € DISPL Γ‘‘‘‘€ OPERAND € –‘ € INDEX Γ‘‘‘‘€ OPERAND € –‘D „… Γ‘‘‘‘‘‘‘‘‘‘‘Β  „… Γ‘‘‘‘‘‘‘‘‘‘‘Β  + € €  + € €  A ‚ƒ ’‘‘Γ‘‘‘‘‘‘‘‘‘‘‘Β‘• ‚ƒ ’‘‘Γ‘‘‘‘‘‘‘‘‘‘‘Β‘• R € BASE Γ‘• € € € DISPL Γ‘• € € R „… € € „… € € A + € € + € € Y ‚ƒ € € ‚ƒ € € € SEGMENT Γ‘‘‘‘„… € SEGMENT Γ‘‘‘‘„… „… „… 3. BASED INDEXED 4. BASED INDEXED MODE WITH DISPLACEMENT BASED MOV DX, [BP][DI] STRUCTURE AND [BX + SI], 3FFH MOV CX, [BP][SI + CNT] CONTAINING SHR[BX + DI + MASK] ARRAY   B   ”‘“ †‡‘“ A †‡ ‘‘“ € €  S € €  ‚ƒ Γ‘‘‘‘‘‘‘‘‘‘‘Β  E ‚ƒ Γ‘‘‘‘‘‘‘‘‘‘‘Β‘“  € INDEX Γ‘‘‘‘€ OPERAND € –‘D € INDEX Γ‘‘‘“ €œœœœœœœœœœœ€  A  „… Γ‘‘‘‘‘‘‘‘‘‘‘Β  „…  Γ‘‘‘‘‘‘‘‘‘‘‘Β  R  + € €  A + ”€ OPERAND € –‘R –• ‚ƒ ’‘‘Γ‘‘‘‘‘‘‘‘‘‘‘Β‘• R ‚ƒ ’‘‘Γ‘‘‘‘‘‘‘‘‘‘‘Β  A  € BASE Γ‘• € € R € DISPL Γ‘• €œœœœœœœœœœœ€  Y  „… € € A „… ’Γ‘‘‘‘‘‘‘‘‘‘‘Β‘•  + € € Y +  € €  ‚ƒ € € ‚ƒ  Γ‘‘‘‘‘‘‘‘‘‘‘Β ‘‘• € SEGMENT Γ‘‘‘‘„… € BASE Γ‘‘‘• € € „… „… € € + € € ‚ƒ € € € SEGMENT Γ‘‘‘‘„… „… 2.5 Input/Output The 80286 allows input/output to be performed in either of two ways: by means of a separate I/O address space (using specific I/O instructions) or by means of memory-mapped I/O (using general-purpose operand manipulation instructions). 2.5.1 I/O Address Space The 80286 provides a separate I/O address space, distinct from physical memory, to address the input/output ports that are used for external devices. The I/O address space consists of 2^(16) (64K) individually addressable 8-bit ports. Any two consecutive 8-bit ports can be treated as a 16-bit port. Thus, the I/O address space can accommodate up to 64K 8-bit ports or up to 32K 16-bit ports. I/O port addresses 00F8H to 00FFH are reserved by Intel. The 80286 can transfer either 8 or 16 bits at a time to a device located in the I/O space. Like words in memory, 16-bit ports should be aligned at even-numbered addresses so that the 16 bits will be transferred in a single access. An 8-bit port may be located at either an even or odd address. The internal registers in a given peripheral controller device should be assigned addresses as shown below. Port Register Port Addresses Example 16-bit even word addresses OUT FE,AX 8-bit; device on lower half of 16-bit data bus even byte addresses IN AL,FE 8-bit; device on upper half of 16-bit data bus odd byte addresses OUT FF,AL The I/O instructions IN and OUT (described in section 3.11.3) are provided to move data between I/O ports and the AX (16-bit I/O) or AL (8-bit I/O) general registers. The block I/O instructions INS and OUTS (described in section 4.1) move blocks of data between I/O ports and memory space (as shown below). In Protected Mode, an operating system may prevent a program from executing these I/O instructions. Otherwise, the function of the I/O instructions and the structure of the I/O space are identical for both modes of operation. INS es:byte ptr [di], DX OUTS DX, byte ptr [si] IN and OUT instructions address I/O with either a direct address to one of up to 256 port addresses, or indirectly via the DX register to one of up to 64K port addresses. Block I/O uses the DX register to specify the I/O address and either SI or DI to designate the source or destination memory address. For each transfer, SI or DI are either incremented or decremented as specified by the direction bit in the flag word while DX is constant to select the I/O device. 2.5.2 Memory-Mapped I/O I/O devices also may be placed in the 80286 memory address space. So long as the devices respond like memory components, they are indistinguishable to the processor. Memory-mapped I/O provides additional programming flexibility. Any instruction that references memory may be used to access an I/O port located in the memory space. For example, the MOV instruction can transfer data between any register and a port; and the AND, OR, and TEST instructions may be used to manipulate bits in the internal registers of a device (see figure 2-14). Memory-mapped I/O performed via the full instruction set maintains the full complement of addressing modes for selecting the desired I/O device. Memory-mapped I/O, like any other memory reference, is subject to access protection and control when executing in protected mode. Figure 2-14. Memory-Mapped I/O MEMORY ADDRESS SPACE ‚ƒ I/O DEVICE 1 € € ‚ƒ € € € INTERNAL REGISTER € Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β‘ ‘‘ ‘ ‘‘ ‘ ‘‘ ‘€‘‚ƒ € € € € € € € Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β‘ ‘‘ ‘ ‘‘ ‘ ‘‘ ‘€‘„… € € € „… € € € € I/O DEVICE 2 € € ‚ƒ € € € INTERNAL REGISTER € €‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘€‘ ‘‘ ‘ ‘‘ ‘ ‘‘ ‘€‘‚ƒ € € € € € € € €‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘€‘ ‘‘ ‘ ‘‘ ‘ ‘‘ ‘€‘„… € € € „… € € „… 2.6 Interrupts and Exceptions The 80286 architecture supports several mechanisms for interrupting program execution. Internal interrupts are synchronous events that are the responses of the CPU to certain events detected during the execution of an instruction. External interrupts are asynchronous events typically triggered by external devices needing attention. The 80286 supports both maskable (controlled by the IF flag) and non-maskable interrupts. They cause the processor to temporarily suspend its present program execution in order to service the requesting device. The major distinction between these two kinds of interrupts is their origin: an internal interrupt is always reproducible by re-executing with the program and data that caused the interrupt, whereas an external interrupt is generally independent of the currently executing task. Interrupts 0-31 are reserved by Intel. Application programmers will normally not be concerned with servicing external interrupts. More information on external interrupts for system programmers may be found in Chapter 5, section 5.2, "Interrupt Handling for Real Address Mode," and in Chapter 9, "Interrupts, Traps and Faults for Protected Virtual Address Mode." In Real Address Mode, the application programmer is affected by two kinds of internal interrupts. (Internal interrupts are the result of executing an instruction which causes the interrupt.) One type of interrupt is called an exception because the interrupt only occurs if a particular fault condition exists. The other type of interrupt generates the interrupt every time the instruction is executed. The exceptions are: divide error, INTO detected overflow, bounds check, segment overrun, invalid operation code, and processor extension error (see table 2-4). A divide error exception results when the instructions DIV or IDIV are executed with a zero denominator; otherwise, the quotient will be too large for the destination operand (see section 3.3.4 for a discussion of DIV and IDIV). An overflow exception results when the INTO instruction is executed and the OF flag is set (after an arithmetic operation that set the overflow (OF) flag). (See section 3.6.3, "Software Generated Interrupts," for a discussion of INTO.) A bounds check exception results when the BOUND instruction is executed and the array index it checks falls outside the bounds of the array. (See section 4.2 for a discussion of the BOUND instruction.) The segment overrun exception occurs when a word memory reference is attempted which extends beyond the end of a segment. An invalid operation code exception occurs if an attempt is made to execute an undefined instruction operation code. A processor extension error is generated when a processor extension detects an illegal operation. Refer to Chapter 5 for a more complete description of these exception conditions. The instruction INT generates an internal interrupt whenever it is executed. The effects of this interrupt (and the effects of all interrupts) is determined by the interrupt handler routines provided by the application program or as part of the system software (provided by system programmers). See Chapter 5 for more on this topic. The INT instruction itself is discussed in section 3.6.3. In Protected Mode, many more fault conditions are detected and result in internal interrupts. Protected Mode interrupts and faults are discussed in Chapter 9. 2.7 Hierarchy of Instruction Sets For descriptive purposes, the 80286 instruction set is partitioned into three distinct subsets: the Basic Instruction Set, the Extended Instruction Set, and the System Control Instruction Set. The "hierarchy" of instruction sets defined by this partitioning helps to clarify the relationships between the various processors in the 8086 family (see figure 2-15). The Basic Instruction Set, presented in Chapter 3, comprises the common subset of instructions found on all processors of the 8086 family. Included are instructions for logical and arithmetic operations, data movement, input/output, string manipulation, and transfer of control. The Extended Instruction Set, presented in Chapter 4, consists of those instructions found only on the 80186, 80188, and 80286 processors. Included are instructions for block structured procedure entry and exit, parameter validation, and block I/O transfers. The System Control Instruction Set, presented in Chapter 10, consists of those instructions unique to the 80286. These instructions control the memory management and protection mechanisms of the 80286. Table 2-4. 80286 Interrupt Vector Assignments (Real Address Mode) Function Interupt Related Return Address Number Instructions Before Instruction Causing Exception? Divide error exception 0 DIV, IDIV Yes Single step interrupt 1 All NMI interrupt 2 All Breakpoint interrupt 3 INT INTO detected overflow exception 4 INTO No BOUND range exceeded exception 5 BOUND Yes Invalid opcode exception 6 Any undefined Yes opcode Processor extension 7 ESC or WAIT Yes not available exception Interrupt table limit 8 INT vector Yes too small exception is not within table limit Processor extension segment 9 ESC with memory No overrun interrupt operand extending beyond offset FFFF(H) Reserved 10-12 Segment overrun exception 13 Word memory Yes reference with offset = FFFF(H) or an attempt to execute past the end of a segment Reserved 14, 15 Processor extension 16 ESC or WAIT error interrupt Reserved 17-31 User defined 32-255 Figure 2-15. Hierarchy of Instructions ‚ƒ € € € € € ‚ƒ € € € € € € € ‚ƒ € € € € € 8086 Ξ‘‘Ξ‘‘Ξ‘‘BASIC INSTRUCTION SET € € € 8088 € € € € € „… € € € € 80186 ‘‘‘Ξ‘‘Ξ‘‘EXTENDED INSTRUCTION SET € € 80188 € € € „… € € 80286 ‘‘‘‘‘‘Ξ‘‘SYSTEM CONTROL INSTRUCTION SET € € „… Chapter 3 Basic Instruction Set ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ The base architecture of the 80286 is identical to the complete instruction set of the 8086, 8088, 80188, and 80186 processors. The 80286 instruction set includes new forms of some instructions. These new forms reduce program size and improve the performance and ease of implementation of source code. This chapter describes the instructions which programmers can use to write application software for the 80286. The following chapters describe the operation of more complicated I/O and system control instructions. All instructions described in this chapter are available for both Real Address Mode and Protected Virtual Address Mode operation. The instruction descriptions note any differences that exist between the operation of an instruction in these two modes. This chapter also describes the operation of each application program-relative instruction and includes an example of using the instruction. The Instruction Dictionary in Appendix B contains formal descriptions of all instructions. Any opcode pattern that is not described in the Instruction Dictionary is undefined and results in an opcode violation trap (interrupt 6). 3.1 Data Movement Instructions These instructions provide convenient methods for moving bytes or words of data between memory and the registers of the base architecture. 3.1.1 General-Purpose Data Movement Instructions MOV (Move) transfers a byte or a word from the source operand to the destination operand. The MOV instruction is useful for transferring data to a register from memory, to memory from a register, between registers, immediate-to-register, or immediate-to-memory. Memory-to-memory or segment register-to-segment register moves are not allowed. Example: MOV DS,AX. Replaces the contents of register DS with the contents of register AX. XCHG (Exchange) swaps the contents of two operands. This instruction takes the place of three MOV instructions. It does not require a temporary memory location to save the contents of one operand while you load the other. The XCHG instruction can swap two byte operands or two word operands, but not a byte for a word or a word for a byte. The operands for the XCHG instruction may be two register operands, or a register operand with a memory operand. When used with a memory operand, XCHG automatically activates the LOCK signal. Example: XCHG BX,WORDOPRND. Swaps the contents of register BX with the contents of the memory word identified by the label WORDOPRND after asserting bus lock. 3.1.2 Stack Manipulation Instructions PUSH (Push) decrements the stack pointer (SP) by two and then transfers a word from the source operand to the top of stack indicated by SP. See figure 3-1. PUSH is often used to place parameters on the stack before calling a procedure; it is also the basic means of storing temporary variables on the stack. The PUSH instruction operates on memory operands, immediate operands (new with the 80286), and register operands (including segment registers). Example: PUSH WORDOPRND. Transfers a 16-bit value from the memory word identified by the label WORDOPRND to the memory location which represents the current top of stack (byte transfers are not allowed). PUSHA (Push All Registers) saves the contents of the eight general registers on the stack. See figure 3-2. This instruction simplifies procedure calls by reducing the number of instructions required to retain the contents of the general registers for use in a procedure. PUSHA is complemented by POPA (see below). The processor pushes the general registers on the stack in the following order: AX, CX, DX, BX, the initial value of SP before AX was pushed, BP, SI, and DI. Example: PUSHA. Pushes onto the stack the contents of the eight general registers. POP (Pop) transfers the word at the current top of stack (indicated by SP) to the destination operand, and then increments SP by two to point to the new top of stack. See figure 3-3. POP moves information from the stack to either a register or memory. The only restriction on POP is that it cannot place a value in register CS. Example: POP BX. Replaces the contents of register BX with the contents of the memory location at the top of stack. POPA (Pop All Registers) restores the registers saved on the stack by PUSHA, except that it ignores the value of SP. See figure 3-4. Example: POPA. Pops from the stack the saved contents of the general registers, and restores the registers (except SP) to their original state. Figure 3-1. PUSH     HIGH ADDRESS € € € € †‡ †‡ SS LIMIT OPERANDS FROM €œœœœœœœœœœœœœœœ€ €œœœœœœœœœœœœœœœ€ PREVIOUS PUSH †‡ †‡ INSTRUCTIONS SP‘€œœœœœœœœœœœœœœœ€ €œœœœœœœœœœœœœœœ€ †‡ †‡ SP ALWAYS POINTS € € € OPERAND €‘TO THE LAST WORD †‡ †‡ PUSHED ONTO THE € € € € STACK (TOS) †‡ †‡ Έ Έ Έ Έ †‡ †‡ € € € € SS ALWAYS POINTS LOW ADDRESS †‡ †‡ TO LOWEST ADDRESS € € € € USED BY THE STACK  BEFORE   AFTER  PUSH OPERAND PUSH OPERAND PUSH decrements SP by 2 bytes and places the operand in the stack at the location to which SP points. Figure 3-2. PUSHA     HIGH ADDRESS € € € € †‡ †‡ SS LIMIT OPERANDS FROM €œœœœœœœœœœœœœœœ€ €œœœœœœœœœœœœœœœ€ PREVIOUS PUSH †‡ †‡ INSTRUCTIONS ’‘‘€œœœœœœœœœœœœœœœ€ €œœœœœœœœœœœœœœœ€  †‡ †‡ SP‘‘• € € € AX € †‡ †‡ € € € CX € †‡ †‡ € € € DX € †‡ †‡ € € € BX € †‡ †‡ € € € OLD SP € †‡ †‡ € € € BP € †‡ †‡ € € € SI € †‡ †‡ € € € DI €‘‘‘SP †‡ †‡ € € € € †‡ †‡ Έ Έ Έ Έ †‡ †‡ € € € € †‡ †‡ € € € € †‡ †‡ € € € € LOW ADDRESS †‡ †‡ SS € € € €     BEFORE AFTER PUSHA PUSHA PUSHA copies the contents of the eight general registers to the stack in the above order. The instruction decrements SP by 16 bytes (8 words) to point to the last word pushed on the stack. Figure 3-3. POP     HIGH ADDRESS € € € € †‡ †‡ SS LIMIT OPERANDS FROM €œœœœœœœœœœœœœœœ€ €œœœœœœœœœœœœœœœ€ PREVIOUS PUSH †‡ †‡ INSTRUCTIONS €œœœœœœœœœœœœœœœ€ €œœœœœœœœœœœœœœœ€‘‘‘SP †‡ †‡ SP‘‘‘€ OPERAND € € € †‡ †‡ € € € € †‡ †‡ Έ Έ Έ Έ †‡ †‡ € € € € LOW ADDRESS †‡ †‡ SS € € € €  BEFORE   AFTER  POP OPERAND POP OPERAND POP copies the contents of the stack location before SP to the operand in the instruction. POP then increments SP by 2 bytes (1 word). Figure 3-4. POPA     HIGH ADDRESS € € € € †‡ †‡ SS LIMIT OPERANDS FROM €œœœœœœœœœœœœœœœ€ €œœœœœœœœœœœœœœœ€ PREVIOUS PUSH †‡ †‡ INSTRUCTIONS €œœœœœœœœœœœœœœœ€ €œœœœœœœœœœœœœœœ€‘‘‘SP †‡ †‡ € AX € € € †‡ †‡ € CX € € € †‡ †‡ € DX € € € †‡ †‡ € BX € € € †‡ †‡ € SP € € € †‡ †‡ € BP € € € †‡ †‡ € SI € € € †‡ †‡ SP‘‘‘€ DI € € € †‡ †‡ € € € € †‡ †‡ Έ Έ Έ Έ †‡ †‡ € € € € †‡ †‡ € € € € †‡ †‡ € € € € LOW ADDRESS †‡ †‡ SS  BEFORE   AFTER  POPA POPA POPA copies the contents of seven stack locations to the corresponding general registers. POPA discards the stored value of SP. 3.2 Flag Operation With the Basic Instruction Set 3.2.1 Status Flags The status flags of the FLAGS register reflect conditions that result from a previous instruction or instructions. The arithmetic instructions use OF, SF, ZF, AF, PF, and CF. The SCAS (Scan String), CMPS (Compare String), and LOOP instructions use ZF to signal that their operations are complete. The base architecture includes instructions to set, clear, and complement CF before execution of an arithmetic instruction. See figure 3-5 and tables 3-1 and 3-2. 3.2.2 Control Flags The control flags of the FLAGS register determine processor operations for string instructions, maskable interrupts, and debugging. Setting DF (direction flag) causes string instructions to auto-decrement; that is, to process strings from high addresses to low addresses, or from "right-to-left." Clearing DF causes string instructions to auto-increment, or to process strings from "left-to-right." Setting IF (interrupt flag) allows the CPU to recognize external (maskable) interrupt requests. Clearing IF disables these interrupts. IF has no effect on either internally generated interrupts, nonmaskable external interrupts, or processor extension segment overrun interrupts. Setting TF (trap flag) puts the processor into single-step mode for debugging. In this mode, the CPU automatically generates an internal interrupt after each instruction, allowing a program to be inspected as it executes each instruction, instruction by instruction. Table 3-1. Status Flags' Functions Bit Position Name Function 0 CF Carry Flag--Set on high-order bit carry or borrow; cleared otherwise 2 PF Parity Flag--Set if low-order eight bits of result contain an even number of 1 bits; cleared otherwise 4 AF Set on carry from or borrow to the low order four bits of AL; cleared otherwise 6 ZF Zero Flag--Set if result is zero; cleared otherwise 7 SF Sign Flag--Set equal to high-order bit of result (0 if positive, 1 if negative) 11 OF Overflow Flag--Set if result is too-large a positive number or too-small a negative number (excluding sign-bit) to fit in destination operand; cleared otherwise Table 3-2. Control Flags' Functions Bit Position Name Function 8 TF Trap (Single Step) Flag--Once set, a single step interrupt occurs after the next instruction executes. TF is cleared by the single step interrupt. 9 IF Interrupt-enable Flag--When set, maskable interrupts will cause the CPU to transfer control to an interrupt vector-specified location. 10 DF Direction Flag--Causes string instructions to auto decrement the appropriate index registers when set. Clearing DF causes auto increment. Figure 3-5. Flag Word Contents STATUS FLAGS: CARRY‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“ PARITY‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“  AUXILLIARY CARRY‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“   ZERO‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“    SIGN‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“     OVERFLOW‘‘‘‘‘‘‘‘‘‘‘‘“            15 14 13 1211 10 9 8 7 6 5 4 3 2 1 0 ‚ΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠƒ FLAGS:€œœNTIOPL OFDFIFTFSFZFœœAFœœPFœœCF€ „€€€€€€€€€€€€€€€…           CONTROL FLAGS:     ”‘‘‘‘‘‘‘‘‘‘‘TRAP FLAG    ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘INTERRUPT ENABLE   ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘DIRECTION FLAG   SPECIAL FIELDS:  ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘I/O PRIVILEGE LEVEL ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘NESTED TASK FLAG 3.3 Arithmetic Instructions The arithmetic instructions of the 8086-family processors simplify the manipulation of numerical data. Multiplication and division instructions ease the handling of signed and unsigned binary integers as well as unpacked decimal integers. An arithmetic operation may consist of two register operands, a general register source operand with a memory destination operand, a memory source operand with a register destination operand, or an immediate field with either a register or memory destination operand, but not two memory operands. Arithmetic instructions can operate on either byte or word operands. 3.3.1 Addition Instructions ADD (Add Integers) replaces the destination operand with the sum of the source and destination operands. ADD affects OF, SF, AF, PF, CF, and ZF. Example: ADD BL, BYTEOPRND. Adds the contents of the memory byte labeled BYTEOPRND to the contents of BL, and replaces BL with the resulting sum. ADC (Add Integers with Carry) sums the operands, adds one if CF is set, and replaces the destination operand with the result. ADC can be used to add numbers longer than 16 bits. ADC affects OF, SF, AF, PF, CF, and ZF. Example: ADC BX, CX. Replaces the contents of the destination operand BX with the sum of BX, CS, and 1 (if CF is set). If CF is cleared, ADC performs the same operation as the ADD instruction. INC (Increment) adds one to the destination operand. The processor treats the operand as an unsigned binary number. INC updates AF, OF, PF, SF, and ZF, but it does not affect CF. Use ADD with an immediate value of 1 if an increment that updates carry (CF) is needed. Example: INC BL. Adds 1 to the contents of BL. 3.3.2 Subtraction Instructions SUB (Subtract Integers) subtracts the source operand from the destination operand and replaces the destination operand with the result. If a borrow is required, carry flag is set. The operands may be signed or unsigned bytes or words. SUB affects OF, SF, ZF, AF, PF, and CF. Example: SUB WORDOPRND, AX. Replaces the contents of the destination operand WORDOPRND with the result obtained by subtracting the contents of AX from the contents of the memory word labeled WORDOPRND. SBB (Subtract Integers with Borrow) subtracts the source operand from the destination operand, subtracts 1 if CF is set, and returns the result to the destination operand. The operands may be signed or unsigned bytes or words. SBB may be used to subtract numbers longer than 16 bits. This instruction affects OF, SF, ZF, AF, PF, and CF. The carry flag is set if a borrow is required. Example: SBB BL, 32. Subtracts 32 from the contents of BL and then decrements the result of this subtraction by one if CF is set. If CF is cleared, SBB performs the same operation as SUB. DEC (Decrement) subtracts 1 from the destination operand. DEC updates AF, OF, PF, SF, and ZF, but it does not affect CF. Use SUB with an immediate value of 1 to perform a decrement that affects carry. Example: DEC BX. Subtracts 1 from the contents of BX and places the result back in BX. 3.3.3 Multiplication Instructions MUL (Unsigned Integer Multiply) performs an unsigned multiplication of the source operand and the accumulator. If the source is a byte, the processor multiplies it by the contents of AL and returns the double-length result to AH and AL. If the source operand is a word, the processor multiplies it by the contents of AX and returns the double-length result to DX and AX. MUL sets CF and OF to indicate that the upper half of the result is nonzero; otherwise, they are cleared. This instruction leaves SF, ZF, AF, and PF undefined. Example: MUL BX. Replaces the contents of DX and AX with the product of BX and AX. The low-order 16 bits of the result replace the contents of AX; the high-order word goes to DX. The processor sets CF and OF if the unsigned result is greater than 16 bits. IMUL (Signed Integer Multiply) performs a signed multiplication operation. IMUL uses AX and DX in the same way as the MUL instruction, except when used in the immediate form. The immediate form of IMUL allows the specification of a destination register other than the combination of DX and AX. In this case, the result cannot exceed 16 bits without causing an overflow. If the immediate operand is a byte, the processor automatically extends it to 16 bits before performing the multiplication. The immediate form of IMUL may also be used with unsigned operands because the low 16 bits of a signed or unsigned multiplication of two 16-bit values will always be the same. IMUL clears CF and OF to indicate that the upper half of the result is the sign of the lower half. This instruction leaves SF, ZF, AF, and PF undefined. Example: IMUL BL. Replaces the contents of AX with the product of BL and AL. The processor sets CF and OF if the result is more than 8 bits long. Example: IMUL BX, SI, 5. Replaces the contents of BX with the product of the contents of SI and an immediate value of 5. The processor sets CF and OF if the signed result is longer than 16 bits. 3.3.4 Division Instructions DIV (Unsigned Integer Divide) performs an unsigned division of the accumulator by the source operand. If the source operand is a byte, it is divided into the double-length dividend assumed to be in registers AL and AH (AH = most significant byte; AL = least significant byte). The single-length quotient is returned in AL, and the single-length remainder is returned in AH. If the source operand is a word, it is divided into the double-length dividend in registers AX and DX. The single-length quotient is returned in AX, and the single-length remainder is returned in DX. Non-integral quotients are truncated to integers toward 0. The remainder is always less than the quotient. For unsigned byte division, the largest quotient is 255. For unsigned word division, the largest quotient is 65,535. DIV leaves OF, SF, ZF, AF, PF, and CF undefined. Interrupt (INT 0) occurs if the divisor is zero or if the quotient is too large for AL or AX. Example: DIV BX. Replaces the contents of AX with the unsigned quotient of the doubleword value contained in DX and AX, divided by BX. The unsigned modulo replaces the contents of DX. Example: DIV BL. Replaces the contents of AL with the unsigned quotient of the word value in AX, divided by BL. The unsigned modulo replaces the contents of AH. IDIV (Signed Integer Divide) performs a signed division of the accumulator by the source operand. IDIV uses the same registers as the DIV instruction. For signed byte division, the maximum positive quotient is +127 and the minimum negative quotient is -128. For signed word division, the maximum positive quotient is +32,767 and the minimum negative quotient is -32,768. Non-integral results are truncated towards 0. The remainder will always have the same sign as the dividend and will be less than the divisor in magnitude. IDIV leaves OF, SF, ZF, AF, PF, and CF undefined. A division by zero causes an interrupt (INT 0) to occur if the divisor is 0 or if the quotient is too large for AL or AX. Example: IDIV WORDOPRND. Replaces the contents of AX with the signed quotient of the double-word value contained in DX and AX, divided by the value contained in the memory word labeled WORDOPRND. The signed modulo replaces the contents of DX. 3.4 Logical Instructions The group of logical instructions includes the Boolean operation instructions, rotate and shift instructions, type conversion instructions, and the no-operation (NOP)instruction. 3.4.1 Boolean Operation Instructions Except for the NOT and NEG instructions, the Boolean operation instructions can use two register operands, a general purpose register operand with a memory operand, an immediate operand with a general purpose register operand, or a memory operand. The NOT and NEG instructions are unary operations that use a single operand in a register or memory. AND (And) performs the logical "and" of the operands (byte or word) and returns the result to the destination operand. AND clears OF and DF, leaves AF undefined, and updates SF, ZF, and PF. Example: AND WORDOPRND, BX. Replaces the contents of WORDOPRND with the logical "and" of the contents of the memory word labeled WORDOPRND and the contents of BX. NOT (Not) inverts the bits in the specified operand to form a one's complement of the operand. NOT has no effect on the flags. Example: NOT BYTEOPRND. Replaces the original contents of BYTEOPRND with the one's complement of the contents of the memory word labeled BYTEOPRND. OR (Or) performs the logical "inclusive or" of the two operands and returns the result to the destination operand. OR clears OF and DF, leaves AF undefined, and updates SF, ZF, and PF. Example: OR AL,5. Replaces the original contents of AL with the logical "inclusive or" of the contents of AL and the immediate value 5. XOR (Exclusive OR) performs the logical "exclusive or" of the two operands and returns the result to the destination operand. XOR clears OF and DF, leaves AF undefined, and updates SF, ZF, and PF. Example: XOR DX, WORDOPRND. Replaces the original contents of DX with the logical "exclusive or" or the contents of DX and the contents of the memory word labeled WORDOPRND. NEG (Negate) forms a two's complement of a signed byte or word operand. The effect of NEG is to reverse the sign of the operand from positive to negative or from negative to positive. NEG updates OF, SF, ZF, AF, PF, and CF. Example: NEG AX. Replaces the original contents of AX with the two's complement of the contents of AX. 3.4.2 Shift and Rotate Instructions The shift and rotate instructions reposition the bits within the specified operand. The shift instructions provide a convenient way to accomplish division or multiplication by binary power. The rotate instructions are useful for bit testing. 3.4.2.1 Shift Instructions The bits in bytes and words may be shifted arithmetically or logically. Depending on the value of a specified count, up to 31 shifts may be performed. A shift instruction can specify the count in one of three ways. One form of shift instruction implicitly specifies the count as a single shift. The second form specifies the count as an immediate value. The third form specifies the count as the value contained in CL. This last form allows the shift count to be a variable that the program supplies during execution. Only the low order 5 bits of CL are used. Shift instructions affect the flags as follows. AF is always undefined following a shift operation. PF, SF, and ZF are updated normally as in the logical instructions. CF always contains the value of the last bit shifted out of the destination operand. In a single-bit shift, OF is set if the value of the high-order (sign) bit was changed by the operation. Otherwise, OF is cleared. Following a multibit shift, however, the content of OF is always undefined. SAL (Shift Arithmetic Left) shifts the destination byte or word operand left by one or by the number of bits specified in the count operand (an immediate value or the value contained in CL). The processor shifts zeros in from the right side of the operand as bits exit from the left side. See figure 3-6. Example: SAL BL,2. Shifts the contents of BL left by 2 bits and replaces the two low-order bits with zeros. Example: SAL BL,1. Shifts the contents of BL left by 1 bit and replaces the low-order bit with a zero. Because the processor does not have to decode the immediate count operand to obtain the shift count, this from of the instruction takes 2 clock cycles rather than the 6 clock cycles (5 + 1 cycle for each bit shifted) required by the previous example. SHL (Shift Logical Left) is physically the same instruction as SAL (see SAL above). SHR (Shift Logical Right) shifts the destination byte or word operand right by one or by the number of bits specified in the count operand (an immediate value or the value contained in CL). The processor shifts zeros in from the left side of the operand as bits exit from the right side. See figure 3-7. Example: SHR BYTEOPRND, CL. Shifts the contents of the memory byte labeled BYTEOPRND right by the number of bits specified in CL, and pads the left side of BYTEOPRND with an equal number of zeros. SAR (Shift Arithmetic Right) shifts the destination byte or word operand to the right by one or by the number of bits specified in the count operand (an immediate value or the value contained in CL). The processor preserves the sign of the operand by shifting in zeros on the left side if the value is positive or by shifting by ones if the value is negative. See figure 3-8. Example: SAR WORDPRND,1. Shifts the contents of the memory byte labeled WORDPRND right by one, and replaces the high-order sign bit with a value equal to the original sign of WORDPRND. SHR shifts the bits in the register or memory operand to the right by the specified number of bit positions. CF receives the last bit shifted out of the right of the operand. SHR shifts in zeros to fill the vacated bit locations. This instruction operates on byte operands as well as word operands. Figure 3-6. SAL and SHL BEFORE SAL OR SHL ‚ƒ ‚ƒ ‚ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆƒ €X€ €X€ € 1 € 1 € 1 € 1 € 1 € 0 € 0 € 0 € 1 € 1 € 1 € 1 € 0 € 0 € 1 € 1 € „… „… „‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰… AFTER SAL OR SHL BY 1 BIT ‚ƒ ‚ƒ ‚ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆƒ €0€ €1€‘Β 1 € 1 € 1 € 1 € 0 € 0 € 0 € 1 € 1 € 1 € 1 € 0 € 0 € 1 € 1 € 0 € „… „… „‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰… AFTER SAL OR SHL BY 8 BITS ‚ƒ ‚ƒ ‚ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆƒ €X€ € €‘Β 1 € 1 € 1 € 1 € 0 € 0 € 1 € 1 € 0 € 0 € 0 € 0 € 0 € 0 € 0 € 0 € „… „… „‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰… OF CF Both SAL and SHL shift the bits in the register or memory operand to the left by the specified number of bit positions. CF receives the last bit shifted out of the left of the operand. SAL and SHL shift in zeros to fill the vacated bit locations. These instructions operate on byte operands as well as word operands. Figure 3-7. SHR BEFORE SHR ‚ƒ ‚ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆƒ ‚ƒ €X€ € 1 € 1 € 0 € 0 € 1 € 1 € 1 € 1 € 0 € 1 € 1 € 1 € 0 € 0 € 0 € 1 € €X€ „… „‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰… „… AFTER SHR BY 1 BIT ‚ƒ ‚ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆƒ ‚ƒ €1€ € 0 € 1 € 1 € 0 € 0 € 1 € 1 € 1 € 1 € 0 € 1 € 1 € 1 € 0 € 0 € 0 Γ‘€1€ „… „‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰… „… AFTER SHR BY 10 BITS ‚ƒ ‚ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆƒ ‚ƒ €X€ € 0 € 0 € 0 € 0 € 0 € 0 € 0 € 0 € 0 € 0 € 0 € 1 € 1 € 0 € 0 € 1 Γ‘€1€ „… „‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰… „… OF OPERAND CF SHR shifts the bits in the register or memory operand to the right by the specified number of bit positions. CF receives the last bit shifted out of the right of the operand. SHR shifts in zeros to fill the vacated bit locations. This instruction operates on byte operands as well as word operands. Figure 3-8. SAR BEFORE SAR WITH A POSITIVE OPERAND ‚ƒ ‚ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆƒ ‚ƒ €X€ € 0 € 0 € 0 € 0 € 0 € 0 € 0 € 0 € 0 € 0 € 0 € 0 € 0 € 0 € 0 € 1 € €X€ „… „‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰… „… AFTER SAR WITH A POSITIVE OPERAND SHIFTED 1 BIT ‚ƒ ‚ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆƒ ‚ƒ €X€ € 0 € 0 € 0 € 0 € 0 € 0 € 0 € 0 € 0 € 0 € 0 € 0 € 0 € 0 € 0 € 0 Γ‘€1€ „… „‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰… „… BEFORE SAR WITH A NEGATIVE OPERAND ‚ƒ ‚ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆƒ ‚ƒ €X€ € 1 € 0 € 0 € 0 € 1 € 1 € 1 € 1 € 0 € 0 € 0 € 1 € 1 € 0 € 1 € 0 Γ‘€X€ „… „‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰… „… AFTER SAR WITH A NEGATIVE OPERAND SHIFTED 6 BITS ‚ƒ ‚ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆƒ ‚ƒ €X€ € 1 € 1 € 1 € 1 € 1 € 1 € 1 € 0 € 0 € 0 € 1 € 1 € 1 € 1 € 0 € 0 Γ‘€0€ „… „‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰… „… OF OPERAND CF SAR preserves the sign of the register or memory operand as it shifts the operand to the right the specified number of bit positions. CF receives the last bit shifted out of the right of the operand. This instruction also operates on byte operands. 3.4.2.2 Rotate Instructions Rotate instructions allow bits in bytes and words to be rotated. Bits rotated out of an operand are not lost as in a shift, but are "circled" back into the other "end" of the operand. Rotates affect only the carry and overflow flags. CF may act as an extension of the operand in two of the rotate instructions, allowing a bit to be isolated and then tested by a conditional jump instruction (JC or JNC). CF always contains the value of the last bit rotated out, even if the instruction does not use this bit as an extension of the rotated operand. In single-bit rotates, OF is set if the operation changes the high-order (sign) bit of the destination operand. If the sign bit retains its original value, OF is cleared. On multibit rotates, the value of OF is always undefined. ROL (Rotate Left) rotates the byte or word destination operand left by one or by the number of bits specified in the count operand (an immediate value or the value contained in CL). For each rotation specified, the high-order bit that exists from the left of the operand returns at the right to become the new low-order bit of the operand. See figure 3-9. Example: ROL AL, 8. Rotates the contents of AL left by 8 bits. This rotate instruction returns AL to its original state but isolates the low-order bit in CF for testing by a JC or JNC instruction. ROR (Rotate Right) rotates the byte or word destination operand right by one or by the number of bits specified in the count operand (an immediate value or the value contained in CL). For each rotation specified, the low-order bit that exits from the right of the operand returns at the left to become the new high-order bit of the operand. See figure 3-10. Example: ROR WORDOPRND, CL. Rotates the contents of the memory word labeled WORDOPRND by the number of bits specified by the value contained in CL. CF reflects the value of the last bit rotated from the right to the left side of the operand. RCL (Rotate Through Carry Left) rotates bits in the byte or word destination operand left by one or by the number of bits specified in the count operand (an immediate value or the value contained in CL). This instruction differs from ROL in that it treats CF as a high-order 1-bit extension of the destination operand. Each high-order bit that exits from the left side of the operand moves to CF before it returns to the operand as the low-order bit on the next rotation cycle. See figure 3-11. Example: RCL BX,1. Rotates the contents of BX left by one bit. The high-order bit of the operand moves to CF, the remaining 15 bits move left one position, and the original value of CF becomes the new low-order bit. RCR (Rotate Through Carry Right) rotates bits in the byte or word destination operand right by one or by the number of bits specified in the count operand (an immediate value or the value contained in CL). This instruction differs from ROR in that it treats CF as a low-order 1-bit extension of the destination operand. Each low-order bit that exits from the right side of the operand moves to CF before it returns to the operand as the high-order bit on the next rotation cycle. See figure 3-12. Example: RCR BYTEOPRND,3. Rotates the contents of the memory byte labeled BYTEOPRND to the right by 3 bits. Following the execution of this instruction, CF reflects the original value of bit number 5 of BYTEOPRND, and the original value of CF becomes bit 2. RCL rotates the bits in the memory or register operand to the left in the same way as ROL except that RCL treats CF as a 1-bit extension of the operand. Note that a 16-bit RCL produces the same result as a 1-bit RCR (though it takes much longer to execute). This instruction also operates on byte operands. RCR rotates the bits in the memory or register operand to the right in the same way as ROR except that RCR treats CF as a 1-bit extension of the operand. This instruction also operates on byte operands. Figure 3-9. ROL BEFORE ROL ‚ƒ‚ƒ ‚ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆƒ €X€€X€ € 1 € 0 € 0 € 0 € 1 € 1 € 1 € 0 € 1 € 0 € 0 € 1 € 1 € 0 € 0 € 0 € „…„… „‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰… AFTER ROL BY 1 BIT ‚ƒ‚ƒ ‚ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆƒ €1€€1€˜Β 0 € 0 € 0 € 1 € 1 € 1 € 0 € 1 € 0 € 0 € 1 € 1 € 0 € 0 € 0 € 1 “ „…„… „‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰… ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘• AFTER ROL BY 12 BITS ‚ƒ‚ƒ ‚ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆƒ €X€€1€˜Β 1 € 0 € 0 € 0 € 1 € 0 € 0 € 0 € 1 € 1 € 1 € 0 € 1 € 0 € 0 € 1 “ „…„… „‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰… OF CF  OPERAND  ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘• ROL shifts the bits in the memory or register operand to the left by the specified number of bit positions. It copies the bit shifted out of the left of the operand into the right of the operand. The last bit shifted into the least significant bit of the operand also appears in CF. This instruction also operates on byte operands. Figure 3-10. ROR BEFORE ROR ‚ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆƒ ‚ƒ € 1 € 1 € 0 € 1 € 1 € 1 € 0 € 0 € 1 € 0 € 1 € 1 € 1 € 0 € 0 € 0 € € X € „‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰… „… AFTER ROR BY 1 BIT ‚ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆƒ ‚ƒ ’ 0 € 1 € 1 € 0 € 1 € 1 € 1 € 0 € 0 € 1 € 0 € 1 € 1 € 1 € 0 € 0 Ø€ 0 € „‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰… „… ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘• AFTER ROR BY 8 BITS ‚ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆƒ ‚ƒ ’ 1 € 0 € 1 € 1 € 1 € 0 € 0 € 0 € 1 € 1 € 0 € 1 € 1 € 1 € 0 € 0 Ø€ 1 € „‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰… „…  OPERAND  CF ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘• ROR shifts the bits in the memory or register operand to the right by the specified number of bit positions. It copies each bit shifted out of the right of the operand into the left of the operand. The last bit shifted into the most significant bit of the operand also appears in CF. This instruction also operates on byte operands. Figure 3-11. RCL BEFORE RCL ‚ƒ ‚ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆƒ € 1 € € 1 € 1 € 1 € 0 € 0 € 0 € 1 € 1 € 0 € 0 € 1 € 1 € 0 € 0 € 0 € 0 € „… „‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰… AFTER RCL BY 1 BIT ‚ƒ ‚ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆƒ ’‘Β 1 €‘Β 1 € 1 € 0 € 0 € 0 € 1 € 1 € 0 € 0 € 1 € 1 € 0 € 0 € 0 € 0 € 1 “  „… „‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰… ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘• AFTER RCL BY 16 BITS ‚ƒ ‚ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆƒ ’‘Β 0 €‘Β 1 € 1 € 1 € 1 € 0 € 0 € 0 € 1 € 1 € 0 € 0 € 1 € 1 € 0 € 0 € 0 “  „… „‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰…  CF OPERAND  ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘• RCL rotates the bits in the memory or register operand to the left in the same way as ROL except that RCL treats CF as a 1-bit extension of the operand. Note that a 16-bit RCL produces the same result as a 1-bit RCR (though it takes much longer to execute). This instruction also operates on byte operands. Figure 3-12. RCR BEFORE RCR ‚ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆƒ ‚ƒ € 1 € 1 € 1 € 0 € 0 € 0 € 1 € 1 € 0 € 0 € 1 € 1 € 0 € 0 € 0 € 0 € € 1 € „‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰… „… AFTER RCR BY 1 BIT ‚ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆƒ ‚ƒ ’ 1 € 1 € 1 € 1 € 0 € 0 € 0 € 1 € 1 € 0 € 0 € 1 € 1 € 0 € 0 € 0 Γ‘€ 0 Γ‘“ „‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰… „…  ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘• AFTER RCR BY 8 BITS ‚ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆƒ ‚ƒ ’ 0 € 0 € 1 € 1 € 1 € 1 € 0 € 0 € 0 € 1 € 1 € 0 € 0 € 1 € 1 € 0 Γ‘€ 0 Γ‘“ „‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰… „…   OPERAND CF  ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘• RCR rotates the bits in the memory or register operand to the right in the same way as ROR except that RCR treats CF as a 1-bit extension of the operand. This instruction also operates on byte operands. 3.4.3 Type Conversion and No-Operation Instructions The type conversion instructions prepare operands for division. The NOP instruction is a 1-byte filler instruction with no effect on registers or flags. CWD (Convert Word to Double-Word) extends the sign of the word in register AX throughout register DX. CWD does not affect any flags. CWD can be used to produce a double-length (double-word) dividend from a word before a word division. CBW (Convert Byte to Word) extends the sign of the byte in register AL throughout AX. CBW does not affect any flags. Example: CWD. Sign-extends the 16-bit value in AX to a 32-bit value in DX and AX with the high-order 16-bits occupying DX. NOP (No Operation) occupies a byte of storage but affects nothing but the instruction pointer, IP. The amount of time that a NOP instruction requires for execution varies in proportion to the CPU clocking rate. This variation makes it inadvisable to use NOP instructions in the construction of timing loops because the operation of such a program will not be independent of the system hardware configuration. Example: NOP. The processor performs no operation for 2 clock cycles. 3.5 Test and Compare Instructions The test and compare instructions are similar in that they do not alter their operands. Instead, these instructions perform operations that only set the appropriate flags to indicate the relationship between the two operands. TEST (Test) performs the logical "and" of the two operands, clears OF and DF, leaves AF undefined, and updates SF, ZF, and PF. The difference between TEST and AND is that TEST does not alter the destination operand. Example: TEST BL,32. Performs a logical "and" and sets SF, ZF, and PF according to the results of this operation. The contents of BL remain unchanged. CMP (Compare) subtracts the source operand from the destination operand. It updates OF, SF, ZF, AF, PF, and CF but does not alter the source and destination operands. A subsequent signed or unsigned conditional transfer instruction can test the result using the appropriate flag result. CMP can compare two register operands, a register operand and a memory operand, a register operand and an immediate operand, or an immediate operand and a memory operand. The operands may be words or bytes, but CMP cannot compare a byte with a word. Example: CMP BX,32. Subtracts the immediate operand, 32, from the contents of BX and sets OF, SF, ZF, AF, PF, and CF to reflect the result. The contents of BX remain unchanged. 3.6 Control Transfer Instructions The 80286 provides both conditional and unconditional program transfer instructions to direct the flow of execution. Conditional program transfers depend on the results of operations that affect the flag register. Unconditional program transfers are always executed. 3.6.1 Unconditional Transfer Instructions JMP, CALL, RET, INT and IRET instructions transfer control from one code segment location to another. These locations can be within the same code segment or in different code segments. 3.6.1.1 Jump Instruction JMP (Jump) unconditionally transfers control to the target location. JMP is a one-way transfer of execution; it does not save a return address on the stack. The JMP instruction always performs the same basic function of transferring control from the current location to a new location. Its implementation varies depending on the following factors: Ž Is the address specified directly within the instruction or indirectly through a register or memory? Ž Is the target location inside or outside the current code segment selected in CS? A direct JMP instruction includes the destination address as part of the instruction. An indirect JMP instruction obtains the destination address indirectly through a register or a pointer variable. Control transfers through a gate or to a task state segment are available only in Protected Mode operation of the 80286. The formats of the instructions that transfer control through a call gate, a task gate, or to a task state segment are the same. The label included in the instruction selects one of these three paths to a new code segment. Direct JMP within the current code segment. A direct JMP that transfers control to a target location within the current code segment uses a relative displacement value contained in the instruction. This can be either a 16-bit value or an 8-bit value sign extended to 16 bits. The processor forms an effective address by adding this relative displacement to the address contained in IP. IP refers to the next instruction when the additions are performed. Example: JMP NEAR_NEWCODE. Transfers control to the target location labeled NEAR_NEWCODE, which is within the code segment currently selected in CS. Indirect JMP within the current code segment. Indirect JMP instructions that transfer control to a location within the current code segment specify an absolute address in one of several ways. First, the program can JMP to a location specified by a 16-bit register (any of AX, DX, CX, BX, BP, SI, or DI). The processor moves this 16-bit value into IP and resumes execution. Example: JMP SI. Transfers control to the target address formed by adding the 16-bit value contained in SI to the base address contained in CS. The processor can also obtain the destination address within a current segment from a memory word operand specified in the instruction. Example: JMP PTR_X. Transfers control to the target address formed by adding the 16-bit value contained in the memory word labeled PTR X to the base address contained in CS. A register can modify the address of the memory word pointer to select a destination address. Example: JMP CASE_TABLE [BX]. CASE_TABLE is the first word in an array of word pointers. The value of BX determines which pointer the program selects from the array. The JMP instruction then transfers control to the location specified by the selected pointer. Direct JMP outside of the current code segment. Direct JMP instructions that specify a target location outside the current code segment contain a full 32-bit pointer. This pointer consists of a selector for the new code segment and an offset within the new segment. Example: JMP FAR_NEWCODE_FOO. Places the selector contained in the instruction into CS and the offset into IP. The program resumes execution at this location in the new code segment. Indirect JMP outside of the current code segment. Indirect JMP instructions that specify a target location outside the current code segment use a double-word variable to specify the pointer. Example: JMP NEWCODE. NEWCODE the first word of two consecutive words in memory which represent the new pointer. NEWCODE contains the new offset for IP and the word following NEWCODE contains the selector for CS. The program resumes execution at this location in the new code segment. (Protected mode programs treat this differently. See Chapters 6 and 7). Direct JMP outside of the current code segment to a call gate. If the selector included with the instruction refers to a call gate, then the processor ignores the offset in the instruction and takes the pointer of the routine being entered from the call gate. JMP outside of current code segment may only go to the same level. Example: JMP CALL_GATE_FOO. The selector in the instruction refers to the call gate CALL_GATE_FOO, and the call gate actually provides the new contents of CS and IP to specify the address of the next instructions. Indirect JMP outside the current code segment to a call gate. If the selector specified by the instruction refers to a call gate, the processor ignores the offset in the double-word and takes the address of the routine being entered from the call gate. The JMP instruction uses the same format to indirectly specify a task gate or a task state segment. Example: JMP CASE_TABLE [BX]. The instruction refers to the double-word in the array of pointers called CASE_TABLE. The specific double-word chosen depends on the value in BX when the instruction executes. The selector portion of this double-word selects a call gate, and the processor takes the address of the routine being entered from the call gate. ROL shifts the bits in the memory or register operand to the left by the specified number of bit positions. It copies the bit shifted out of the left of the operand into the right of the operand. The last bit shifted into the least significant bit of the operand also appears in CF. This instruction also operates on byte operands. ROR shifts the bits in the memory or register operand to the right by the specified number of bit positions. It copies each bit shifted out of the right of the operand into the left of the operand. The last bit shifted into the most significant bit of the operand also appears in CF. This instruction also operates on byte operands. 3.6.1.2 Call Instruction CALL (Call Procedure) activates an out-of-line procedure, saving on the stack the address of the instruction following the CALL for later use by a RET (Return) instruction. An intrasegment CALL places the current value of IP on the stack. An intersegment CALL places both the value of IP and CS on the stack. The RET instruction in the called procedure uses this address to transfer control back to the calling program. A long CALL instruction that invokes a task-switch stores the outgoing task's task state segment selector in the incoming task state segment's link field and sets the nested task flag in the new task. In this case, the IRET instruction takes the place of the RET instruction to return control to the nested task. Examples: CALL NEAR_NEWCODE CALL SI CALL PTR_X CALL CASE_TABLE [BP] CALL FAR_NEWCODE_FOO CALL NEWCODE CALL CALL_GATE_FOO CALL CASE_TABLE [BX] See the previous treatment of JMP for a discussion of the operations of these instructions. 3.6.1.3 Return And Return From Interrupt Instruction RET (Return From Procedure) terminates the execution of a procedure and transfers control through a back-link on the stack to the program that originally invoked the procedure. An intrasegment RET restores the value of IP that was saved on the stack by the previous intrasegment CALL instruction. An intersegment RET restores the values of both CS and IP which were saved on the stack by the previous intersegment CALL instruction. RET instructions may optionally specify a constant to the stack pointer. This constant specifies the new top of stack to effectively remove any arguments that the calling program pushed on the stack before the execution of the CALL instruction. Example: RET. If the previous CALL instruction did not transfer control to a new code segment, RET restores the value of IP pushed by the CALL instruction. If the previous CALL instruction transferred control to a new segment, RET restores the values of both IP and CS which were pushed on the stack by the CALL instruction. Example: RET n. This form of the RET instruction performs identically to the above example except that it adds n (which must be an even value) to the value of SP to eliminate n bytes of parameter information previously pushed by the calling program. IRET (Return From Interrupt or Nested Task) returns control to an interrupted routine or, optionally, reverses the action of a CALL or INT instruction that caused a task switch. See Chapter 8 for further information on task switching. Example: IRET. Returns from an interrupt with or without a task switch based on the value of the NT bit. 3.6.2 Conditional Transfer Instructions The conditional transfer instructions are jumps that may or may not transfer control, depending on the state of the CPU flags when the instruction executes. Instruction encoding is most efficient when the target for the conditional jumps is in the current code segment and within -128 to +127 bytes of the first byte of the next instruction. Alternatively, the opposite sense of the conditional jump can skip around an unconditional jump to the destination. 3.6.2.1 Conditional Jump Instructions Table 3-3 shows the conditional transfer mnemonics and their interpretations. The conditional jumps that are listed as pairs are actually the same instruction. The assembler provides the alternate mnemonics for greater clarity within a program listing. Table 3-3. Interpretation of Conditional Transfers Unsigned Conditional Transfers Mnemonic Condition Tested "Jump If. . ." JA/JNBE (CF or ZF) = 0 above/not below nor equal JAE/JNB CF = 0 above or equal/not below JB/JNAE CF = 1 below/not above nor equal JBE/JNA (CF or ZF) = 1 below or equal/not above JC CF = 1 carry JE/JZ ZF = 1 equal/zero JNC CF = 0 not carry JNE/JNZ ZF = 0 not equal/not zero JNP/JPO PF = 0 not parity/parity odd JP/JPE PF = 1 parity/parity even Signed Conditional Transfers Mnemonic Condition Tested "Jump If. . ." JG/JNLE ((SF xor OF) or ZF) = 0 greater/not less nor equal JGE/JNL (SF xor OF) = 0 greater or equal/not less JL/JNGE (SF xor OF) = 0 less/not greater nor equal JLE/JNG ((SF xor OF) or ZF) = 1 less or equal/not greater JNO OF = 0 not overflow JNS SF = 0 not sign (positive, including 0) JO OF = 1 overflow JS SF = 1 sign (negative) 3.6.2.2 Loop Instructions The loop instructions are conditional jumps that use a value placed in CX to specify the number of repetitions of a software loop. All loop instructions automatically decrement CX and terminate the loop when CX=0. Four of the five loop instructions specify a condition of ZF that terminates the loop before CX decrements to zero. LOOP (Loop While CX Not Zero) is a conditional transfer that auto-decrements the CX register before testing CX for the branch condition. If CX is non-zero, the program branches to the target label specified in the instruction. The LOOP instruction causes the repetition of a code section until the operation of the LOOP instruction decrements CX to a value of zero. If LOOP finds CX=0, control transfers to the instruction immediately following the LOOP instruction. If the value of CX is initially zero, then the LOOP executes 65,536 times. Example: LOOP START_LOOP. Each time the program encounters this instruction, it decrements CX and then tests it. If the value of CX is non-zero, then the program branches to the instruction labeled START_LOOP. If the value in CX is zero, then the program continues with the instruction that follows the LOOP instruction. LOOPE (Loop While Equal) and LOOPZ (Loop While Zero) are physically the same instruction. These instructions auto-decrement the CX register before testing CX and ZF for the branch conditions. If CX is non-zero and ZF=1, the program branches to the target label specified in the instruction. If LOOPE or LOOPZ finds that CX=0 or ZF=0, control transfers to the instruction immediately succeeding the LOOPE or LOOPZ instruction. Example: LOOPE START_LOOP (or LOOPZ START_LOOP). Each time the program encounters this instruction, it decrements CX and tests CX and ZF. If the value in CX is non-zero and the value of ZF is 1, the program branches to the instruction labeled START_LOOP. If CX=0 or ZF=0, the program continues with the instruction that follows the LOOPE (or LOOPZ) instruction. LOOPNE (Loop While Not Equal) and LOOPNZ (Loop While Not Zero) are physically the same instruction. These instructions auto-decrement the CX register before testing CX and ZF for the branch conditions. If CX is non-zero and ZF=0, the program branches to the target label specified in the instruction. If LOOPNE or LOOPNZ finds that CX=0 or ZF=1, control transfers to the instruction immediately succeeding the LOOPNE or LOOPNZ instruction. Example: LOOPNE START_LOOP (or LOOPNZ START_LOOP). Each time the program encounters this instruction, it decrements CX and tests CX and ZF. If the value of CX is non-zero and the value of ZF is 0, the program branches to the instruction labeled START_LOOP. If CX=0 or ZF=1, the program continues with the instruction that follows the LOOPNE (or LOOPNZ) instruction. 3.6.2.3 Executing a Loop or Repeat Zero Times JCXZ (Jump if CX Zero) branches to the label specified in the instruction if it finds a value of zero in CX. Sometimes, it is desirable to design a loop that executes zero times if the count variable in CX is initialized to zero. Because the LOOP instructions (and repeat prefixes) decrement CX before they test it, a loop will execute 65,536 times if the program enters the loop with a zero value in CX. A programmer may conveniently overcome this problem with JCXZ, which enables the program to branch around the code within the loop if CX is zero when JCXZ executes. Example: JCXZ TARGETLABEL. Causes the program to branch to the instruction labeled TARGETLABEL if CX=0 when the instruction executes. 3.6.3 Software-Generated Interrupts The INT n and INTO instructions allow the programmer to specify a transfer to an interrupt service routine from within a program. Interrupts 0-31 are reserved by Intel. 3.6.3.1 Software Interrupt Instruction INT n (Software Interrupt) activates the interrupt service routine that corresponds to the number coded within the instruction. Interrupt type 3 is reserved for internal software-generated interrupts. However, the INT instruction may specify any interrupt type to allow multiple types of internal interrupts or to test the operation of a service routine. The interrupt service routine terminates with an IRET instruction that returns control to the instruction that follows INT. Example: INT 3. Transfers control to the interrupt service routine specified by a type 3 interrupt. Example: INT 0. Transfers control to the interrupt service routine specified by a type 0 interrupt, which is reserved for a divide error. INTO (Interrupt on Overflow) invokes a type 4 interrupt if OF is set when the INTO instruction executes. The type 4 interrupt is reserved for this purpose. Example: INTO. If the result of a previous operation has set OF and no intervening operation has reset OF, then INTO invokes a type 4 interrupt. The interrupt service routine terminates with an IRET instruction, which returns control to the instruction following INTO. 3.7 Character Translation and String Instructions The instructions in this category operate on characters or string elements rather than on logical or numeric values. 3.7.1 Translate Instruction XLAT (Translate) replaces a byte in the AL register with a byte from a user-coded translation table. When XLAT is executed, AL should have the unsigned index to the table addressed by BX. XLAT changes the contents of AL from table index to table entry. BX is unchanged. The XLAT instruction is useful for translating from one coding system to another, such as from ASCII to EBCDIC. The translate table may be up to 256 bytes long. The value placed in the AL register serves as an index to the location of the corresponding translation value. Used with a LOOP instruction, the XLAT instruction can translate a block of codes up to 64K bytes long. Example: XLAT. Replaces the byte in AL with the byte from the translate table that is selected by the value in AL. 3.7.2 String Manipulation Instructions and Repeat Prefixes The string instructions (also called primitives) operate on string elements to move, compare, and scan byte or word strings. One-byte repeat prefixes can cause the operation of a string primitive to be repeated to process strings as long as 64K bytes. The repeated string primitives use the direction flag, DF, to specify left-to-right or right-to-left string processing, and use a count in CX to limit the processing operation. These instructions use the register pair DS:SI to point to the source string element and the register pair ES:DI to point to the destination. One of two possible opcodes represent each string primitive, depending on whether it is operating on byte strings or word strings. The string primitives are generic and require one or more operands along with the primitive to determine the size of the string elements being processed. These operands do not determine the addresses of the strings; the addresses must already be present in the appropriate registers. Each repetition of a string operation using the Repeat prefixes includes the following steps: 1. Acknowledge pending interrupts. 2. Check CX for zero and stop repeating if CX is zero. 3. Perform the string operation once. 4. Adjust the memory pointers in DS:SI and ES:DI by incrementing SI and DI if DF is 0 or by decrementing SI and DI if DF is 1. 5. Decrement CX (this step does not affect the flags). 6. For SCAS (Scan String) and CMPS (Compare String), check ZF for a match with the repeat condition and stop repeating if the ZF fails to match. The Load String and Store String instructions allow a program to perform arithmetic or logical operations on string characters (using AX for word strings and AL for byte strings). Repeated operations that include instructions other than string primitives must use the loop instructions rather than a repeat prefix. 3.7.2.1 String Movement Instructions REP (Repeat While CX Not Zero) specifies a repeated operation of a string primitive. The REP prefix causes the hardware to automatically repeat the associated string primitive until CX=0. This form of iteration allows the CPU to process strings much faster than would be possible with a regular software loop. When the REP prefix accompanies a MOVS instruction, it operates as a memory-to-memory block transfer. To set up for this operation, the program must initialize CX and the register pairs DS:SI and ES:DI. CX specifies the number of bytes or words in the block. If DF=0, the program must point DS:SI to the first element of the source string and point ES:DI to the destination address for the first element. If DF=1, the program must point these two register pairs to the last element of the source string and to the destination address for the last element, respectively. Example: REP MOVSW. The processor checks the value in CX for zero. If this value is not zero, the processor moves a word from the location pointed to by DS:SI to the location pointed to by ES:DI and increments SI and DI by two (if DF=0). Next, the processor decrements CX by one and returns to the beginning of the repeat cycle to check CX again. After CX decrements to zero, the processor executes the instruction that follows. MOVS (Move String) moves the string character pointed to by the combination of DS and SI to the location pointed to by the combination of ES and DI. This is the only memory-to-memory transfer supported by the instruction set of the base architecture. MOVSB operates on byte elements. The destination segment register cannot be overridden by a segment override prefix while the source segment register can be overridden. Example: MOVSW. Moves the contents of the memory byte pointed to by DS:SI to the location pointed to by ES:DI. 3.7.2.2 Other String Operations CMPS (Compare Strings) subtracts the destination string element (ES:DI) from the source string element (DS:SI) and updates the flags AF, SF, PF, CF and OF. If the string elements are equal, ZF=1; otherwise, ZF=0. If DF=0, the processor increments the memory pointers (SI and DI) for the two strings. The segment register used for the source address can be changed with a segment override prefix, while the destination segment register cannot be overridden. Example: CMPSB. Compares the source and destination string elements with each other and returns the result of the comparison to ZF. SCAS (Scan String) subtracts the destination string element at ES:DI from AX or AL and updates the flags AF, SF, ZF, PF, CF and OF. If the values are equal, ZF=1; otherwise, ZF=0. If DF=0, the processor increments the memory pointer (DI) for the string. The segment register used for the source address can be changed with a segment override prefix while the destination segment register cannot be overridden. Example: SCASW. Compares the value in AX with the destination string element. REPE/REPZ (Repeat While CX Equal/Zero) and REPNE/REPNZ (Repeat While CX Not Equal/Not Zero) are the prefixes that are used exclusively with the SCAS (ScanString) and CMPS (Compare String) primitives. The difference between these two types of prefix bytes is that REPE/REPZ terminates when ZF=0 and REPNE/REPNZ terminates when ZF=1. ZF does not require initialization before execution of a repeated string instruction. When these prefixes modify either the SCAS or CMPS primitives, the processor compares the value of the current string element with the value in AX for word elements or with the value in AL for byte elements. The resulting state of ZF can then limit the operation of the repeated operation as well as a zero value in CX. Example: REPE SCASB. Causes the processor to scan the string pointed to by ES:DI until it encounters a match with the byte value in AL or until CX decrements to zero. LODS (Load String) places the source string element at DS:SI into AX for word strings or into AL for byte strings. Example: LODSW. Loads AX with the value pointed to by DS:SI. 3.8 Address Manipulation Instructions The set of address manipulation instructions provide a way to perform address calculations or to move to a new data segment or extra segment. LEA (Load Effective Address) transfers the offset of the source operand (rather than its value) to the destination operand. The source operand must be a memory operand, and the destination operand must be a 16-bit general register (AX, DX, BX, CX, BP, SP, SI, or DI). LEA does not affect any flags. This instruction is useful for initializing the registers before the execution of the string primitives or the XLAT instruction. Example: LEA BX EBCDIC_TABLE. Causes the processor to place the address of the starting location of the table labeled EBCDIC_TABLE into BX. LDS (Load Pointer Using DS) transfers a 32-bit pointer variable from the source operand to DS and the destination register. The source operand must be a memory operand, and the destination operand must be a 16-bit general register (AX, DX, BX, CX, BP, SP, SI or DI). DS receives the high-order segment word of the pointer. The destination register receives the low-order word, which points to a specific location within the segment. Example: LDS SI, STRING_X. Loads DS with the word identifying the segment pointed to by STRING_X, and loads the offset of STRING_X into SI. Specifying SI as the destination operand is a convenient way to prepare for a string operation on a source string that is not in the current data segment. LES (Load Pointer Using ES) operates identically to LDS except that ES receives the offset word rather than DS. Example: LES DI, DESTINATION_X. Loads ES with the word identifying the segment pointed to by DESTINATION_X, and loads the offset of DESTINATION_X into DI. This instruction provides a convenient way to select a destination for a string operation if the desired location is not in the current extra segment. 3.9 Flag Control Instructions The flag control instructions provide a method of changing the state of bits in the flag register. 3.9.1 Carry Flag Control Instructions The carry flag instructions are useful in conjunction with rotate-with-carry instructions RCL and RCR. They can initialize the carry flag, CF, to a known state before execution of a rotate that moves the carry bit into one end of the rotated operand. STC (Set Carry Flag) sets the carry flag (CF) to 1. Example: STC CLC (Clear Carry Flag) zeros the carry flag (CF). Example: CLC CMC (Complement Carry Flag) reverses the current status of the carry flag (CF). Example: CMC 3.9.2 Direction Flag Control Instructions The direction flag control instructions are specifically included to set or clear the direction flag, DF, which controls the left-to-right or right-to-left direction of string processing. IF DF=0, the processor automatically increments the string memory pointers, SI and DI, after each execution of a string primitive. If DF=1, the processor decrements these pointer values. The initial state of DF is 0. CLD (Clear Direction Flag) zeros DF, causing the string instructions to auto-increment SI and/or DI. CLD does not affect any other flags. Example: CLD STD (Set Direction Flag) sets DF to 1, causing the string instructions to auto-decrement SI and/or DI. STD does not affect any other flags. Example: STD 3.9.3 Flag Transfer Instructions Though specific instructions exist to alter CF and DF, there is no direct method of altering the other flags. The flag transfer instructions allow a program to alter the other flag bits with the bit manipulation instructions after transferring these flags to the stack or the AH register. The PUSHF and POPF instructions are also useful for preserving the state of the flag register before executing a procedure. LAHF (Load AH from Flags) copies SF, ZF, AF, PF, and CF to AH bits 7, 6, 4, 2, and 0, respectively (see figure 3-13). The contents of the remaining bits (5, 3, and 1) are undefined. The flags remain unaffected. This instruction can assist in converting 8080/8085 assembly language programs to run on the base architecture of the 8086, 8088, 80186, 80188, and 80286. Example: LAHF SAHF (Store AH into Flags) transfers bits 7, 6, 4, 2, and 0 from AH into SF, ZF, AF, PF, and CF, respectively (see figure 3-13). This instruction also provides 8080/8085 compatibility with the 8086, 8088, 80186, 80188, and 80286. Example: SAHF PUSHF (Push Flags) decrements SP by two and then transfers all flags to the word at the top of stack pointed to by SP (see figure 3-14). The flags remain unaffected. This instruction enables a procedure to save the state of the flag register for later use. Example: PUSHF POPF (Pop Flags) transfers specific bits from the word at the top of stack into the low-order byte of the flag register (see figure 3-14). The processor then increments SP by two. Note that an application program in the protected virtual address mode may not alter IOPL (the I/O privilege level flag) unless the program is executing at privilege level 0. A program may alter IF (the interrupt flag) only when executing at a level that is at least as privileged as IOPL. Procedures may use this instruction to restore the flag status from a previous value. Example: POPF Figure 3-13. LAHF and SAHF 7 6 5 4 3 2 1 0 ‚ΠΠΠΠΠΠΠƒ € SF  ZF œœœœ AF œœœœ PF œœœœ CF € „€€€€€€€… REGISTER AH LAHF loads five flags from the flag register into register AH. SAHF stores these same five flgs from AH into the flag register. The bit position of each flag is the same in AH as it is in the flag register. The remaining bits are indeterminate. Figure 3-14. PUSHF and POPF 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 ‚ΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠƒ €œœœNT  IOPL OF DF IF TF SF ZF œœœAF œœœPF œœœCF € „€€€€€€€€€€€€€€€… STACK WORD PUSHF decrements SP by 2 bytes (1 word) and copies the contents of the flag register to the top of the stack. POPF loads the flag register with the contents of the last word pushed onto the stack. The bit position of each flag is the same in the stack word as it is in the flag register. Only programs executing at the highest privilege level (level 0) may alter the 2-bit IOPL flag. Only programs executing at a level at least as privileged as that indicated by IOPL may alter IF. 3.10 Binary-Coded Decimal Arithmetic Instructions These instructions adjust the results of a previous arithmetic operation to produce a valid packed or unpacked decimal result. These instructions operate only on AL or AH registers. 3.10.1 Packed BCD Adjustment Instructions DAA (Decimal Adjust) corrects the result of adding two valid packed decimal operands in AL. DAA must always follow the addition of two pairs of packed decimal numbers (one digit in each nibble) to obtain a pair of valid packed decimal digits as results. The carry flag will be set if carry was needed. Example: DAA DAS (Decimal Adjust for Subtraction) corrects the result of subtracting two valid packed decimal operands in AL. DAS must always follow the subtraction of one pair of packed decimal numbers (one digit in each nibble) from another to obtain a pair of valid packed decimal digits as results. The carry flag will be set if a borrow was needed. Example: DAS 3.10.2 Unpacked BCD Adjustment Instructions AAA (ASCII Adjust for Addition) changes the contents of register AL to a valid unpacked decimal number, and zeros the top 4 bits. AAA must always follow the addition of two unpacked decimal operands in AL. The carry flag will be set and AH will be incremented if a carry was necessary. Example: AAA AAS (ASCII Adjust for Subtraction) changes the contents of register AL to a valid unpacked decimal number, and zeros the top 4 bits. AAS must always follow the subtraction of one unpacked decimal operand from another in AL. The carry flag will be set and AH decremented if a borrow was necessary. Example: AAS AAM (ASCII Adjust for Multiplication) corrects the result of a multiplication of two valid unpacked decimal numbers. AAM must always follow the multiplication of two decimal numbers to produce a valid decimal result. The high order digit will be left in AH, the low order digit in AL. Example: AAM AAD (ASCII Adjust for Division) modifies the numerator in AH and AL to prepare for the division of two valid unpacked decimal operands so that the quotient produced by the division will be a valid unpacked decimal number. AH should contain the high-order digit and AL the low-order digit. This instruction will adjust the value and leave it in AL. AH will contain 0. Example: AAD 3.11 Trusted Instructions When operating in Protected Mode (Chapter 6 and following), the 80286 processor restricts the execution of trusted instructions according to the Current Privilege Level (CPL) and the current value of IOPL, the 2-bit I/O privilege flag. Only a program operating at the highest privilege level (level 0) may alter the value of IOPL. A program may execute trusted instructions only when executing at a level that is at least as privileged as that specified by IOPL. Trusted instructions control I/O operations, interprocessor communications in a multiprocessor system, interrupt enabling, and the HLT instruction. These protection considerations do not apply in the real address mode. 3.11.1 Trusted and Privileged Restrictions on POPF and IRET POPF (POP Flags) and IRET (Interrupt Return) are not affected by IOPL unless they attempt to alter IF (flag register bit 9). To change IF, POPF must be part of a program that is executing at a privilege level greater than or equal to that specified by IOPL. Any attempt to change IF when CPL  0 will be ignored (i.e., the IF flag will be ignored). To change the IOPL field, CPL must be zero. 3.11.2 Machine State Instructions These trusted instructions affect the machine state control interrupt response, the processor halt state, and the bus LOCK signal that regulates memory access in multiprocessor systems. CLI (Clear Interrupt-Enable Flag) and STI (Set Interrupt-Enable Flag) alter bit 9 in the flag register. When IF=0, the processor responds only to internal interrupts and to non-maskable external interrupts. When IF=1, the processor responds to all interrupts. An interrupt service routine might use these instructions to avoid further interruption while it processes a previous interrupt request. As with the other flag bits, the processor clears IF during initialization. These instructions may be executed only if CPL Ύ IOPL. A protection exception will occur if they are executed when CPL > IOPL. Example: STI. Sets IF=1, which enables the processing of maskable external interrupts. Example: CLI. Sets IF=0 to disable maskable interrupt processing. HLT (Halt) causes the processor to suspend processing operations pending an interrupt or a system reset. This trusted instruction provides an alternative to an endless software loop in situations where a program must wait for an interrupt. The return address saved after the interrupt will point to the instruction immediately following HLT. This instruction may be executed only when CPL = 0. Example: HLT LOCK (Assert Bus Lock) is a 1-byte prefix code that causes the processor to assert the bus LOCK signal during execution of the instruction that follows. LOCK does not affect any flags. LOCK may be used only when CPL Ύ IOPL. A protection exception will occur if LOCK is used when CPL > IOPL. 3.11.3 Input and Output Instructions These trusted instructions provide access to the processor's I/O ports to transfer data to and from peripheral devices. In Protected Mode, these instructions may be executed only when CPL Ύ IOPL. IN (Input from Port) transfers a byte or a word from an input port to AL or AX. If a program specifies AL with the IN instruction, the processor transfers 8 bits from the selected port to AL. Alternately, if a program specifies AX with the IN instruction, the processor transfers 16 bits from the port to AX. The program can specify the number of the port in two ways. Using an immediate byte constant, the program can specify 256 8-bit ports numbered 0 through 255 or 128 16-bit ports numbered 0,2,4,...,252,254. Using the current value contained in DX, the program can specify 8-bit ports numbered 0 through 65,535, or 16-bit ports using even-numbered ports in the same range. Example: IN AL, BYTE_PORT_NUMBER. Transfers 8 bits to AL from the port identified by the immediate constant BYTE_PORT_NUMBER. OUT (Output to Port) transfers a byte or a word to an output port from AL or AX. The program can specify the number of the port using the same methods of the IN instruction. Example: OUT AX, DX. Transfers 16 bits from AX to the port identified by the 16-bit number contained in DX. INS and OUTS (Input String and Output String) cause block input or output operations using a Repeat prefix. See Chapter 4 for more information on INS and OUTS. 3.12 Processor Extension Instructions Processor Extension provides an extension to the instruction set of the base architecture (e.g., 80287). The NPX extends the instruction set of the CPU-based architecture to support high-precision integer and floating-point calculations. This extended instruction set includes arithmetic, comparison, transcendental, and data transfer instructions. The NPX also contains a set of useful constants to enhance the speed of numeric calculations. A program contains instructions for the NPX in line with the instructions for the CPU. The system executes these instructions in the same order as they appear in the instruction stream. The NPX operates concurrently with the CPU to provide maximum throughput for numeric calculations. The software emulation of the NPX is transparent to application software but requires more time for execution. 3.12.1 Processor Extension Synchronization Instructions Escape and wait instructions allow a processor extension such as the 80287 NPX to obtain instructions and data from the system bus and to wait for the NPX to return a result. ESC (Escape) identifies floating point numeric instructions and allows the 80286 to send the opcode to the NPX or to transfer a memory operand to the NPX. The 80287 NPX uses the Escape instructions to perform high-performance, high-precision floating point arithmetic that conforms to the IEEE floating point standard 754. Example: ESC 6, ARRAY [SI]. The CPU sends the escape opcode 6 and the location of the array pointed to by SI to the NPX. WAIT (Wait) suspends program execution until the 80286 CPU detects a signal on the BUSY pin. In a configuration that includes a numeric processor extension, the NPX activates the BUSY pin to signal that it has completed its processing task and that the CPU may obtain the results. Example: WAIT 3.12.2 Numeric Data Processor Instructions This section describes the categories of instructions available with Numeric Data Processor systems that include a Numeric Processor Extension or a software emulation of this processor extension. 3.12.2.1 Arithmetic Instructions The extended instruction set includes not only the four arithmetic operations (add, subtract, multiply, and divide), but also subtract-reversed and divide-reversed instructions. The arithmetic functions include square root, modulus, absolute value, integer part, change sign, scale exponent, and extract exponent instructions. 3.12.2.2 Comparison Instructions The comparison operations are the compare, examine, and test instructions. Special forms of the compare instruction can optimize algorithms by allowing comparisons of binary integers with real numbers in memory. 3.12.2.3 Transcendental Instructions The instructions in this group perform the otherwise time-consuming calculations for all common trigonometric, inverse trigonometric, hyperbolic, inverse hyperbolic, logarithmic, and exponential functions. The transcendental instructions include tangent, arctangent, 2 x-1, Y. log{2} X, and Y. log{2} (X+1). 3.12.2.4 Data Transfer Instructions The data transfer instructions move operands among the registers and between a register and memory. This group includes the load, store, and exchange instructions. 3.12.2.5 Constant Instructions Each of the constant instructions loads a commonly used constant into an NPX register. The values have a real precision of 64 bits and are accurate to approximately 19 decimal places. The constants loaded by these instructions include 0, 1, Pi, log{e} 10, log{2} e, log{10} 2, and log 2{e}. Chapter 4 Extended Instruction Set ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ The instructions described in this chapter extend the capabilities of the base architecture instruction set described in Chapter 3. These extensions consist of new instructions and variations of some instructions that are not strictly part of the base architecture (in other words, not included on the 8086 and 8088). These instructions are also available on the 80186 and 80188. The instruction variations, described in Chapter 3, include the immediate forms of the PUSH and MUL instructions, PUSHA, POPA, and the privilege level restrictions on POPF. New instructions described in this chapter include the string input and output instructions (INS and OUTS), the ENTER procedure and LEAVE procedure instructions, and the check index BOUND instruction. 4.1 Block I/O Instructions REP, the Repeat prefix, modifies INS and OUTS (the string I/O instructions) to provide a means of transferring blocks of data between an I/O port and Memory. These block I/O instructions are string primitives. They simplify programming and increase the speed of data transfer by eliminating the need to use a separate LOOP instruction or an intermediate register to hold the data. INS and OUTS are trusted instructions. To use trusted instructions, a program must execute at a privilege level at least as privileged as that specified by the 2-bit IOPL flag (CPL Ύ IOPL). Any attempt by a less-privileged program to use a trusted instruction results in a protection exception. See Chapter 7 for information on protection concepts. One of two possible opcodes represents each string primitive depending on whether it operates on byte strings or word strings. After each transfer, the memory address in SI or DI is updated by 1 for byte values and by 2 for word values. The value in the DF field determines if SI or DI is to be auto incremented (DF=0) or auto decremented (DF=1). INS and OUTS use DX to specify I/O ports numbered 0 through 65,535 or 16-bit ports using only even port addresses in the same range. INS (Input String from Port) transfers a byte or a word string element from an input port to memory. If a program specifies INSB, the processor transfers 8 bits from the selected port to the memory location indicated by ES:DI. Alternately, if a program specifies INSW, the processor transfers 16 bits from the port to the memory location indicated by ES:DI. The destination segment register choice (ES) cannot be changed for the INS instruction. Combined with the REP prefix, INS moves a block of information from an input port to a series of consecutive memory locations. Example: REP INSB. The processor repeatedly transfers 8 bits to the memory location indicated by ES:DI from the port selected by the 16-bit port number contained in DX. Following each byte transfer, the CPU decrements CX. The instruction terminates the block transfer when CX=0. After decrementing CX, the processor increments DI by one if DF=0. It decrements DI by one if DF=1. OUTS (Output String to Port) transfers a byte or a word string element to an output port from memory. Combined with the REP prefix, OUTS moves a block of information from a series of consecutive memory locations indicated by DS:SI to an output port. Example: REP OUTS WSTRING. Assuming that the program declares WSTRING to be a word-length string element, the assembler uses the 16-bit form of the OUTS instruction to create the object code for the program. The processor repeatedly transfers words from the memory locations indicated by DI to the output port selected by the 16-bit port number in DX. Following each word transfer, the CPU decrements CX. The instruction terminates the block transfer when CX=0. After decrementing CX, the processor increments SI by two to point to the next word in memory if DF=0; it decrements SI by two if DF=1. 4.2 High-Level Instructions The instructions in this section provide machine-language functions normally found only in high-level languages. These instructions include ENTER and LEAVE, which simplify the programming of procedures, and BOUND, which provides a simple method of testing an index against its predefined range. ENTER (Enter Procedure) creates the stack frame required by most block-structured high-level languages. A LEAVE instruction at the end of a procedure complements an ENTER at the beginning of the procedure to simplify stack management and to control access to variables for nested procedures. Example: ENTER 2048,3. Allocates 2048 bytes of dynamic storage on the stack and sets up pointers to two previous stack frames in the stack frame that ENTER creates for this procedure. The ENTER instruction includes two parameters. The first parameter specifies the number of bytes of dynamic storage to be allocated on the stack for the routine being entered. The second parameter corresponds to the lexical nesting level (0-31) of the routine. (Note that the lexical level has no relationship to either the protection privilege levels or to the I/O privilege level.) The specified lexical level determines how many sets of stack frame pointers the CPU copies into the new stack frame from the preceding frame. This list of stack frame pointers is sometimes called the "display." The first word of the display is a pointer to the last stack frame. This pointer enables a LEAVE instruction to reverse the action of the previous ENTER instruction by effectively discarding the last stack frame. After ENTER creates the new display for a procedure, it allocates the dynamic storage space for that procedure by decrementing SP by the number of bytes specified in the first parameter. This new value of SP serves as a base for all PUSH and POP operations within that procedure. To enable a procedure to address its display, ENTER leaves BP pointing to the beginning of the new stack frame. Data manipulation instructions that specify BP as a base register implicitly address locations within the stack segment instead of the data segment. Two forms of the ENTER instruction exist: nested and non-nested. If the lexical level is 0, the non-nested form is used. Since the second operand is 0, ENTER pushes BP, copies SP to BP and then subtracts the first operand from SP. The nested form of ENTER occurs when the second parameter (lexical level) is not 0. Figure 4-1 gives the formal definition of ENTER. The main procedure (with other procedures nested within) operates at the highest lexical level, level 1. The first procedure it calls operates at the next deeper lexical level, level 2. A level 2 procedure can access the variables of the main program which are at fixed locations specified by the compiler. In the case of level 1, ENTER allocates only the requested dynamic storage on the stack because there is no previous display to copy. A program operating at a higher lexical level calling a program at a lower lexical level requires that the called procedure should have access to the variables of the calling program. ENTER provides this access through a display that provides addressability to the calling program's stack frame. A procedure calling another procedure at the same lexical level implies that they are parallel procedures and that the called procedure should not have access to the variables of the calling procedure. In this case, ENTER copies only that portion of the display from the calling procedure which refers to previously nested procedures operating at higher lexical levels. The new stack frame does not include the pointer for addressing the calling procedure's stack frame. ENTER treats a reentrant procedure as a procedure calling another procedure at the same lexical level. In this case, each succeeding iteration of the reentrant procedure can address only its own variables and the variables of the calling procedures at higher lexical levels. A reentrant procedure can always address its own variables; it does not require pointers to the stack frames of previous iterations. By copying only the stack frame pointers of procedures at higher lexical levels, ENTER makes sure that procedures access only those variables of higher lexical levels, not those at parallel lexical levels (see figure 4-2). Figures 4-2a, 4-2b, 4-2c, and 4-2d demonstrate the actions of the ENTER instruction if the modules shown in figure 4-1 were to call one another in alphabetic order. Block-structured high-level languages can use the lexical levels defined by ENTER to control access to the variables of previously nested procedures. For example, if PROCEDURE A calls PROCEDURE B which, in turn, calls PROCEDURE C, then PROCEDURE C will have access to the variables of MAIN and PROCEDURE A, but not PROCEDURE B because they operate at the same lexical level. Following is the complete definition of the variable access for figure 4-2. 1. MAIN PROGRAM has variables at fixed locations. 2. PROCEDURE A can access only the fixed variables of MAIN. 3. PROCEDURE B can access only the variables of PROCEDURE A and MAIN. PROCEDURE B cannot access the variables of PROCEDURE C or PROCEDURE D. 4. PROCEDURE C can access only the variables of PROCEDURE A and MAIN. PROCEDURE C cannot access the variables of PROCEDURE B or PROCEDURE D. 5. PROCEDURE D can access the variables of PROCEDURE C, PROCEDURE A, and MAIN. PROCEDURE D cannot access the variables of PROCEDURE B. ENTER at the beginning of the MAIN PROGRAM creates dynamic storage space for MAIN but copies no pointers. The first and only word in the display points to itself because there is no previous value for LEAVE to return to BP. See figure 4-2a. After MAIN calls PROCEDURE A, ENTER creates a new display for PROCEDURE A with the first word pointing to the previous value of BP (BPM for LEAVE to return to the MAIN stack frame) and the second word pointing to the current value of BP. Procedure A can access variables in MAIN since MAIN is at level 1. Therefore the base for the dynamic storage for MAIN is at [BP-2]. All dynamic variables for MAIN will be at a fixed offset from this value. See figure 4-2b. After PROCEDURE A calls PROCEDURE B, ENTER creates a new display for PROCEDURE B with the first word pointing to the previous value of BP, the second word pointing to the value of BP for MAIN, and the third word pointing to the value of BP for A and the last word pointing to the current BP. B can access variables in A and MAIN by fetching from the display the base addresses of the respective dynamic storage areas. See figure 4-2c. After PROCEDURE B calls PROCEDURE C, ENTER creates a new display for PROCEDURE C with the first word pointing to the previous value of BP, the second word pointing to the value of BP for MAIN, and the third word pointing to the BP value for A and the third word pointing to the current value of BP. Because PROCEDURE B and PROCEDURE C have the same lexical level, PROCEDURE C is not allowed access to variables in B and therefore does not receive a pointer to the beginning of PROCEDURE B's stack frame. See figure 4-2d. LEAVE (Leave Procedure) reverses the action of the previous ENTER instruction. The LEAVE instruction does not include any operands. Example: LEAVE. First, LEAVE copies BP to SP to release all stack space allocated to the procedure by the most recent ENTER instruction. Next, LEAVE pops the old value of BP from the stack. A subsequent RET instruction can then remove any arguments that were pushed on the stack by the calling program for use by the called procedure. BOUND (Detect Value Out of Range) verifies that the signed value contained in the specified register lies within specified limits. An interrupt (INT 5) occurs if the value contained in the register is less than the lower bound or greater than the upper bound. The BOUND instruction includes two operands. The first operand specifies the register being tested. The second operand contains the effective relative address of the two signed BOUND limit values. The BOUND instruction assumes that it can obtain the upper limit from the memory word that immediately follows the lower limit. These limit values cannot be register operands; if they are, an invalid opcode exception occurs. BOUND is useful for checking array bounds before using a new index value to access an element within the array. BOUND provides a simple way to check the value of an index register before the program overwrites information in a location beyond the limit of the array. The two-word block of memory that specifies the lower and upper limits of an array might typically reside just before the array itself. This makes the array bounds accessible at a constant offset of -4 from the beginning of the array. Because the address of the array will already be present in a register, this practice avoids extra calculations to obtain the effective address of the array bounds. Example: BOUND BX,ARRAY-4. Compares the value in BX with the lower limit at address ARRAY-4 and the upper limit at address ARRAY-2. If the signed value in BX is less than the lower bound or greater than the upper bound, the interrupt for this instruction (INT 5) occurs. Otherwise, this instruction has no effect. Figure 4-1. Formal Definition of the ENTER Instruction The Formal Definition Of The ENTER Instruction. For All Cases Is Given By The Following Listing. LEVEL Denotes The Value Of The Second Operand. Push BP Set a temporary value FRAME_PTR:=SP If LEVEL > 0 then Repeat (LEVEL - 1) times: BP:=BP - 2 Push the word pointed to by BP End repeat Push FRAME_PTR End if BP:=FRAME_PTR SP:=SP - first operand. Figure 4-2. Variable Access in Nested Procedures ‚ƒ € MAIN PROGRAM (LEXICAL LEVEL 1) € € ‚ƒ € € € PROCEDURE A (LEXICAL LEVEL 2) € € € € ‚ƒ € € € € €PROCEDURE B (LEXICAL LEVEL 3)€ € € € € „… € € € € € € € € ‚ƒ € € € € € PROCEDURE C (LEXICAL LEVEL 3) € € € € € € ‚ƒ € € € € € € €PROCEDURE D (LEXICAL LEVEL 4)€ € € € € € € „… € € € € € € € € € € € „… € € € € € € € „… € € € „… Figure 4-2a. Stack Frame for MAIN at Level 1   € 15 0 € †‡‘“ € OLD BP €  BP FOR MAIN‘‘†‡ –‘DISPLAY € BPM BPM = BP value for MAIN €  †‡‘• € € € € € €¨DYNAMIC € € STORAGE € € SP‘‘†‡ € € Figure 4-2b. Stack Frame for PROCEDURE A €15 0€ †‡ € OLD BP € †‡ € BPM € †‡ € € € € € € € € †‡‘“ € BPM €  BP FOR A‘‘†‡  € BPM €  †‡ –‘DISPLAY € BPA BPA = BP value for PROCEDURE A €  †‡Α € €  € € –‘DYNAMIC € €  STORAGE € €  SP‘‘†‡‘• € € †‡ € € Figure 4-2c. Stack Frame for PROCEDURE B at Level 3 Called from A €15 0€ †‡ € OLD BP € †‡ € BPM € †‡ € € € € € € € € †‡ € BPM € †‡ € BPM € †‡ € BPA € †‡ € € € € € € € € †‡‘“ € BPA €  BP‘‘†‡  € BPM €  †‡ –‘DISPLAY € BPA €  †‡  € BPB €  †‡Α € €  € € –‘DYNAMIC € €  STORAGE € €  †‡‘• € € SP‘‘†‡ € € Figure 4-2d. Stack Frame for PROCEDURE C at Level 3 Called from B €15 0€ †‡ € OLD BP € †‡ € BPM € †‡ € € € € € € € € †‡ € BPM € †‡ € BPM € †‡ € BPA € †‡ € € € € € € € € †‡ € BPA € BP‘‘†‡‘“ € BPM €  †‡  € BPA € –‘DISPLAY †‡  € BPB €  †‡Α € €  € € –‘DYNAMIC € €  STORAGE € €  SP‘‘†‡‘• € € Chapter 5 Real Address Mode ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ The 80286 can be operated in either of two modes according to the status of the Protection Enabled bit of the MSW status register. In contrast to the "modes" and "mode bits" of some processors, however, the 80286 modes do not represent a radical transition between conflicting architectures. Instead, the setting of the Protection Enabled bit simply determines whether certain advanced features, in addition to the baseline architecture of the 80286, are to be made available to system designers and programmers. If the Protection Enabled (PE) bit is set by the programmer, the processor changes into Protected Virtual Address Mode. In this mode of operation, memory addressing is performed in terms of virtual addresses, with on-chip mapping mechanisms performing the virtual-to-physical translation. Only in this mode can the system designer make use of the advanced architectural features of the 80286: virtual memory support, system-wide protection, and built-in multitasking mechanisms are among the new features provided in this mode of operation. Refer to Part II of this book (Chapters 6, 7, 8, 9, 10, and 11) for details on Protected Mode operation. Initially, upon system reset, the processor starts up in Real Address Mode. In this mode of operation, all memory addressing is performed in terms of real physical addresses. In effect, the architecture of the 80286 in this mode is identical to that of the 8086 and other processors in the 8086 family. The principal features of this baseline architecture have already been discussed throughout Part I (Chapters 2, 3, and 4) of this book. This chapter discusses certain additional topics‘‘addressing, interrupt handling, and system initialization‘‘that complete the system programmer's view of the 80286 in Real Address Mode. 5.1 Addressing and Segmentation Like other processors in the 8086 family, the 80286 provides a one-megabyte memory space (2^(20) bytes) when operated in Real Address Mode. Physical addresses are the 20-bit values that uniquely identify each byte location in this address space. Physical addresses, therefore, may range from 0 through FFFFFH. Address bits A20-A23 may not always be zero in Real Address Mode. A20-A23 should not be used by the system while the 80286 is operating in Real Address Mode. An address is specified by a 32-bit pointer containing two components: (1) a 16-bit effective address offset that determines the displacement, in bytes, of a particular location within a segment; and (2) a 16-bit segment selector component that determines the starting address of the segment. Both components of an address may be referenced explicitly by an instruction (such as JMP, LES, LDS, or CALL); more often, however, the segment selector is simply the contents of a segment register. The interpretation of the first component, the effective address offset, is straight-forward. Segments are at most 64K (2^(16)) bytes in length, so an unsigned 16-bit quantity is sufficient to address any arbitrary byte location with a segment. The lowest-addressed byte within a segment has an offset of 0, and the highest-addressed byte has an offset of FFFFH. Data operands must be completely contained within a segment and must be contiguous. (These rules apply in both modes.) A segment selector is the second component of a logical address. This 16-bit quantity specifies the starting address of a segment within a physical address space of 2^(20) bytes. Whenever the 80286 accesses memory in Real Address Mode, it generates a 20-bit physical address from a segment selector and offset value. The segment selector value is left-shifted four bit positions to form the segment base address. The offset is extended with 4 high order zeroes and added to the base to form the physical address (see figure 5-1). Therefore, every segment is required to start at a byte address that is evenly divisible by 16; thus, each segment is positioned at a 20-bit physical address whose least significant four bits are zeroes. This arrangement allows the 80286 to interpret a segment selector as the high-order 16 bits of a 20-bit segment base address. No limit or access checks are performed by the 80286 in the Real Address Mode. All segments are readable, writable, executable, and have a limit of 0FFFFH (65,535 bytes). To save physical memory, you can use unused portions of a segment as another segment by overlapping the two (see figure 5-2). The Intel 8086 software development tools support this feature via the segment override and group operators. However, programs that access segment B from segment A become incompatible in the protected virtual address mode. Figure 5-1a. Forming the Segment Base Address 16 BIT SEGMENT SELECTOR ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“ 15 0 ‚ΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠ      ƒ €                0 0 0 0 „€€€€€€€€€€€€€€€€      … 19 0 Figure 5-1b. Forming the 20-bit Physical Address in the Real Address Mode ‚ΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠ      ƒ SEGMENT BASE €                0 0 0 0 „€€€€€€€€€€€€€€€€      … 19 0 + ‚      ЁΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠƒ OFFSET 0 0 0 0                 € „      €€€€€€€€€€€€€€€€… 19 15 0 = ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ ‚ΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠƒ PHYSICAL €                    € ADDRESS „€€€€€€€€€€€€€€€€€€€… 19 0 Figure 5-2. Overlapping Segments to Save Physical Memory   € € Γ‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘Ξ ‘‘‘ € €  € €  € € 64K SEGMENT B € €  ‘‘‘ Ξ‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘Ξ   € OVERLAP €   †‡‘‘‘‘‘ BASE OF SEGMENT A 64K € € SEGMENT B  € €  € €  € € ‘‘‘ †‡‘‘‘‘‘ BASE OF € € SEGMENT A   5.2 Interrupt Handling Program interrupts may be generated in either of two distinct ways. An internal interrupt is caused directly by the currently executing program. The execution of a particular instruction results in the occurrence of an interrupt, whether intentionally (e.g., an INT n instruction) or as an unanticipated exception (e.g., invalid opcode). On the other hand, an external interrupt occurs asynchronously as the result of an event external to the processor, and bears no necessary relationship with the currently executing program. The INTR and NMI pins of the 80286 provide the means by which external hardware signals the occurrence of such events. 5.2.1 Interrupt Vector Table Whatever its origin, whether internal or external, an interrupt demands immediate attention from an associated service routine. Control must be transferred, at least for the moment, from the currently executing program to the appropriate interrupt service routine. By means of interrupt vectors, the 80286 handles such control transfers uniformly for both kinds of interrupts. An interrupt vector is an unsigned integer in the range of 0-255; every interrupt is assigned such a vector. In some cases, the assignment is predetermined and fixed: for example, an external NMI interrupt is invariably associated with vector 2, while an internal divide exception is always associated with vector 0. In most cases, however, the association of an interrupt and a vector is established dynamically. An external INTR interrupt, for example, supplies a vector in response to an interrupt acknowledge bus cycle, while the INT n instruction supplies a vector incorporated within the instruction itself. The vector is shifted two places left to form a byte address into the table (see figure 5-3). In any case, the 80286 uses the interrupt vector as an index into a table in order to determine the address of the corresponding interrupt service routine. For Real Address Mode, this table is known as the Interrupt Vector Table. Its format is illustrated in figure 5-3. The Interrupt Vector Table consists of as many as 256 consecutive entries, each four bytes long. Each entry defines the address of a service routine to be associated with the correspondingly numbered interrupt vector code. Within each entry, an address is specified by a full 32-bit pointer that consists of a 16-bit offset and a 16-bit segment selector. Interrupts 0-31 are reserved by Intel. In Real Address Mode, the interrupt table can be accessed directly at physical memory location 0 through 1023. In the protected virtual address mode, however, the interrupt vector table has no fixed physical address and cannot be directly accessed. Therefore, Real Address mode programs that directly manipulate the interrupt vector table will not work in the protected virtual address mode. Table 5-1. Interrupt Processing Order Order Interrupt 1. Instruction exception 2. Single step 3. NMI 4. Processor extension segment overrun 5. INTR Figure 5-3. Interrupt Vector Table for Real Address Mode POWER TO INTERRUPT HANDLER PHYSICAL FOR: ADDRESS ‚ƒ INTERRUPT 255 € POINTER € 1020 †‡ INTERRUPT 254 € POINTER € 1018 †‡ INTERRUPT 253 € POINTER €“ 1012 †‡ ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“ € € ‚Π€ΠΠƒ € € €0 ¨ ¨ ¨ ¨ ¨ ¨ ¨ 0 VECTOR 00€ Έ Έ „€€€… € € 19 10 9 2 1 0 € € †‡ INTERRUPT 1 € POINTER € 4 †‡ INTERRUPT 0 € POINTER € 0 „… 5.2.1.1 Interrupt Priorities When simultaneous interrupt requests occur, they are processed in a fixed order as shown in table 5-1. Interrupt processing involves saving the flags, the return address, and setting CS:IP to point at the first instruction of the interrupt handler. If other interrupts remain enabled, they are processed before the first instruction of the current interrupt handler is executed. The last interrupt processed is therefore the first one serviced. 5.2.2 Interrupt Procedures When an interrupt occurs in Real Address Mode, the 8086 performs the following sequence of steps. First, the FLAGS register, as well as the old values of CS and IP, are pushed onto the stack (see figure 5-4). The IF and TF flag bits are cleared. The vector number is then used to read the address of the interrupt service routine from the interrupt table. Execution begins at this address. Thus, when control is passed to an interrupt service routine, the return linkage is placed on the stack, interrupts are disabled, and single-step trace (if in effect) is turned off. The IRET instruction at the end of the interrupt service routine will reverse these steps before transferring control to the program that was interrupted. An interrupt service routine may affect registers other than other IP, CS, and FLAGS. It is the responsibility of an interrupt routine to save additional context information before proceeding so that the state of the machine can be restored upon completion of the interrupt service routine (PUSHA and POPA instructions are intended for these operations). Finally, execution of the IRET instruction pops the old IP, CS, and FLAGS from the stack and resumes the execution of the interrupted program. Figure 5-4. Stack Structure after Interrupt (Real Address Mode) € € Έ Έ  †‡  € OLD FLAGS € INCREASING  †‡ ADDRESSES  € OLD CS €  †‡  € OLD IP €‘‘  †‡ €  € Έ  Έ €  € 5.2.3 Reserved and Dedicated Interrupt Vectors In general, the system designer is free to use almost any interrupt vectors for any given purpose. Some of the lowest-numbered vectors, however, are reserved by Intel for dedicated functions; their use is specifically implied by certain types of exceptions. None of the first 32 vectors should be defined by the user; these vectors are either invoked by pre-defined exceptions or reserved by Intel for future expansion. Table 5-2 shows the dedicated and reserved vectors of the 80286 in Real Address Mode. The purpose and function of the dedicated interrupt vectors may be summarized as follows (the saved value of CS:IP will include all leading prefixes): Ž Divide error (Interrupt 0). This exception will occur if the quotient is too large or an attempt is made to divide by zero using either the DIV or IDIV instruction. The saved CS:IP points at the first byte of the failing instruction. DX and AX are unchanged. Ž Single-Step (Interrupt 1). This interrupt will occur after each instruction if the Trap Flag (TF) bit of the FLAGS register is set. Of course, TF is cleared upon entry to this or any other interrupt to prevent infinite recursion. The saved value of CS:IP will point to the next instruction. Ž Nonmaskable (Interrupt 2). This interrupt will occur upon receipt of an external signal on the NMI pin. Typically, the nonmaskable interrupt is used to implement power-fail/auto-restart procedures. The saved value of CS:IP will point to the first byte of the interrupted instruction. Ž Breakpoint (Interrupt 3). Execution of the one-byte breakpoint instruction causes this interrupt to occur. This instruction is useful for the implementation of software debuggers since it requires only one code byte and can be substituted for any instruction opcode byte. The saved value of CS:IP will point to the next instruction. Ž INTO Detected Overflow (Interrupt 4). Execution of the INTO conditional software interrupt instruction will cause this interrupt to occur if the overflow bit (OF) of the FLAGS register is set. The saved value of CS:IP will point to the next instruction. Ž BOUND Range Exceeded (Interrupt 5). Execution of the BOUND instruction will cause this interrupt to occur if the specified array index is found to be invalid with respect to the given array bounds. The saved value of CS:IP will point to the first byte of the BOUND instruction. Ž Invalid Opcode (Interrupt 6). This exception will occur if execution of an invalid opcode is attempted. (In Real Address Mode, most of the Protected Virtual Address Mode instructions are classified as invalid and should not be used). This interrupt can also occur if the effective address given by certain instructions, notably BOUND, LDS, LES, and LIDT, specifies a register rather than a memory location. The saved value of CS:IP will point to the first byte of the invalid instruction or opcode. Ž Processor Extension Not Available (Interrupt 7). Execution of the ESC instruction will cause this interrupt to occur if the status bits of the MSW indicate that processor extension functions are to be emulated in software. Refer to section 10.2.1 for more details. The saved value of CS:IP will point to the first byte of the ESC or the WAIT instruction. Ž Interrupt Table Limit Too Small (Interrupt 8). This interrupt will occur if the limit of the interrupt vector table was changed from 3FFH by the LIDT instruction and an interrupt whose vector is outside the limit occurs. The saved value of CS:IP will point to the first byte of the instruction that caused the interrupt or that was ready to execute before an external interrupt occurred. No error code is pushed. Ž Processor Extension Segment Overrun Interrupt (Interrupt 9). The interrupt will occur if a processor extension memory operand does not fit in a segment. The saved CS:IP will point at the first byte of the instruction that caused the interrupt. Ž Segment Overrun Exception (Interrupt 13). This interrupt will occur if a memory operand does not fit in a segment. In Real Mode this will occur only when a word operand begins at segment offset 0FFFFH. The saved CS:IP will point at the first byte of the instruction that caused the interrupt. No error code is pushed. Ž Processor Extension Error (Interrupt 16). This interrupt occurs after the numeric instruction that caused the error. It can only occur while executing a subsequent WAIT or ESC. The saved value of CS:IP will point to the first byte of the ESC or the WAIT instruction. The address of the failed numeric instruction is saved in the NPX. Table 5-2. Dedicated and Reserved Interrupt Vectors in Real Address Mode Function Interrupt Related Instructions Return Address Number Before Instruction Causing Exception? Divide error exception 0 DIV, IDIV Yes Single step interrupt 1 All N/A NMI interrupt 2 All N/A Breakpoint interrupt 3 INT N/A INTO detected overflow 4 INTO No exception BOUND range exceeded 5 BOUND Yes exception Invalid opcode exception 6 Any undefined opcode Yes Processor extension 7 ESC or WAIT Yes not available exception Interrupt table 8 LIDT Yes limit too small Processor extension 9 ESC Yes segment overrun interrupt Segment overrun exception 13 Any memory reference Yes instruction that attempts to reference 16-bit word at offset 0FFFFH. Reserved 10-12, 14, 15 Processor extension 16 ESC or WAIT N/A error interrupt Reserved 17-31 User defined 32-255 N/A = Not Applicable 5.3 System Initialization The 80286 provides an orderly way to start or restart an executing system. Upon receipt of the RESET signal, certain processor registers go into the determinate state shown in table 5-3. Since the CS register contains F000 (thus specifying a code segment starting at physical address F0000) and the instruction pointer contains FFF0, the processor will execute its first instruction at physical address FFFF0H. The uppermost 16 bytes of physical memory are therefore reserved for initial startup logic. Ordinarily, this location contains an intersegment direct JMP instruction whose target is the actual beginning of a system initialization or restart program. Some of the steps normally performed by a system initialization routine are as follows: Ž Allocate a stack. Ž Load programs and data from secondary storage into memory. Ž Initialize external devices. Ž Enable interrupts (i.e., set the IF bit of the FLAGS register). Set any other desired FLAGS bit as well. Ž Set the appropriate MSW flags if a processor extension is present, or if processor extension functions are to be emulated by software. Ž Set other registers, as appropriate, to the desired initial values. Ž Execute. (Ordinarily, this last step is performed as an intersegment JMP to the main system program.) Table 5-3. Processor State after RESET Register Contents FLAGS 0002 MSW FFF0 IP FFF0 CS F000 DS 0000 SS 0000 ES 0000 Chapter 6 Memory Management and Virtual Addressing ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ In Protected Virtual Address Mode, the 80286 provides an advanced architecture that retains substantial compatibility with the 8086 and other processors in the 8086 family. In many respects, the baseline architecture of the processor remains constant regardless of the mode of operation. Application programmers continue to use the same set of instructions, addressing modes, and data types in Protected Mode as in Real Address Mode. The major difference between the two modes of operation is that the Protected Mode provides system programmers with additional architectural features, supplementary to the baseline architecture, that can be used to good advantage in the design and implementation of advanced systems. Especially noteworthy are the mechanisms provided for memory management, protection, and multitasking. This chapter focuses on the memory management mechanisms of Protected Mode; the concept of a virtual address and the process of virtual-to-physical address translation are described in detail in this chapter. Subsequent chapters deal with other key aspects of Protected Mode operation. Chapter 7 discusses the issue of protection and the integrated mechanisms that support a system-wide protection policy. Chapter 8 discusses the notion of a task and its central role in the 80286 architecture. Chapters 9, 10, and 11 discuss certain additional topics‘‘interrupt handling, special instructions, system initialization, etc.‘‘that complete the system programmer's view of 80286 Protected Mode. 6.1 Memory Management Overview A memory management scheme interposes a mapping operation between logical addresses (i.e., addresses as they are viewed by programs) and physical addresses (i.e., actual addresses in real memory). Since the logical address spaces are independent of physical memory (dynamically relocatable), the mapping (the assignment of real address space to virtual address space) is transparent to software. This allows the program development tools (for static systems) or the system software (for reprogrammable systems) to control the allocation of space in real memory without regard to the specifics of individual programs. Application programs may be translated and loaded independently since they deal strictly with virtual addresses. Any program can be relocated to use any available segments of physical memory. The 80286, when operated in Protected Mode, provides an efficient on-chip memory management architecture. Moreover, as described in Chapter 11, the 80286 also supports the implementation of virtual memory systems‘‘that is, systems that dynamically swap chunks of code and data between real memory and secondary storage devices (e.g., a disk) independent of and transparent to the executing application programs. Thus, a program-visible address is more aptly termed a virtual address rather than a logical address since it may actually refer to a location not currently present in real memory. Memory management, then, consists of a mechanism for mapping the virtual addresses that are visible to the program onto the physical addresses of real memory. With the 80286, segmentation is the key to virtual memory addressing. Virtual memory is partitioned into a number of individual segments, which are the units of memory that are mapped into physical memory and swapped to and from secondary storage devices. Most of this chapter is devoted to a detailed discussion of the mapping and virtual memory mechanisms of the 80286. The concept of a task also plays a significant role in memory management since distinct memory mappings may be assigned to the different tasks in a multitask or multi-user environment. A complete discussion of tasks is deferred until Chapter 8, "Tasks and State Transition." For present purposes, it is sufficient to think of a task as an ongoing process, or execution path, that is dedicated to a particular function. In a multi-user time-sharing environment, for example, the processing required to interact with a particular user may be considered as a single task, functionally independent of the other tasks (i.e., users) in the system. 6.2 Virtual Addresses In Protected Mode, application programs deal exclusively with virtual addresses; programs have no access whatsoever to the actual physical addresses generated by the processor. As discussed in Chapter 2, an address is specified by a program in terms of two components: (1) a 16-bit effective address offset that determines the displacement, in bytes, of a location within a segment; and (2) a 16-bit segment selector that uniquely references a particular segment. Jointly, these two components constitute a complete 32-bit address (pointer data type), as shown in figure 6-1. These 32-bit virtual addresses are manipulated by programs in exactly the same way as the two-component addresses of Real Address Mode. After a program loads the segment selector component of an address into a segment register, each subsequent reference to locations within the selected segment requires only a 16-bit offset be specified. Locality of reference will ordinarily insure that addresses can be specified very efficiently using only 16-bit offsets. An important difference between Real Address Mode and Protected Mode, however, concerns the actual format and information content of segment selectors. In Real Address Mode, as with the 8086 and other processors in the 8086 family, a 16-bit selector is merely the upper bits of a segment's physical base address. By contrast, segment selectors in Protected Mode follow an entirely different format, as illustrated by figure 6-1. Two of the selector bits, designated as the RPL field in figure 6-1, are not actually involved in the selection and specification of segments; their use is discussed in Chapter 7. The remaining 14 bits of the selector component uniquely designate a particular segment. The virtual address space of a program, therefore, may encompass as many as 16,384 (2^(14)) distinct segments. Segments themselves are of variable size, ranging from as small as a single byte to as large as 64K (2^(16)) bytes. Thus, a program's virtual address space may contain, altogether, up to a full gigabyte (2^(30) = 2^(14) * 2^(16)) of individually addressable byte locations. The entirety of a program's virtual address space is further subdivided into two separate halves, as distinguished by the TI ("table indicator") bit in the virtual address. These two halves are the global address space and the local address space. The global address space is used for system-wide data and procedures including operating system software, library routines, runtime language support and other commonly shared system services. (To application programs, the operating system appears to be a set of service routines that are accessible to all tasks.) Global space is shared by all tasks to avoid unnecessary replication of system service routines and to facilitate shared data and interrupt handling. Global address space is defined by addresses with a zero in the TI bit position; it is identically mapped for all tasks in the system. The other half of the virtual address space‘‘comprising those addresses with the TI bit set‘‘is separately mapped for each task in the system. Because such an address space is local to the task for which it is defined, it is referred to as a local address space. In general, code and data segments within a task's local address space are private to that particular task or user. Figure 6-2 illustrates the task isolation made possible by partitioning the virtual address spaces into local and global regions. Within each of the two regions addressable by a program‘‘either the global address space or a particular local address space‘‘as many as 8,192 (2^(13)) distinct segments may be defined. The INDEX field of the segment selector allows for a unique specification of each of these segments. This 13-bit quantity acts as an index into a memory-resident table, called a descriptor table, that records the mapping between segment address and the physical locations allocated to each distinct segment. (These descriptor tables, and their role in virtual-to-physical address translation, are described in the sections that follow.) In summary, a Protected Mode virtual address is a 32-bit pointer to a particular byte location within a one-gigabyte virtual address space. Each such pointer consists of a 16-bit selector component and a 16-bit offset component. The selector component, in turn, comprises a 13-bit table index, a 1-bit table indicator (local versus global), and a 2-bit RPL field; all but this last field serve to select a particular segment from among the 16K segments in a task's virtual address space. The offset component of a full pointer is an unsigned 16-bit integer that specifies the desired byte location within the selected segment. Figure 6-1. Format of the Segment Selector Component 32-BIT POINTER ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“ 31 16 15 0 ‚Πƒ € SEGMENT SELECTOR  SEGMENT OFFSET € „€…       ’‘‘• ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“ 15 3 2 1 0 ‚ΠΠΠΠΠΠΠΠΠΠΠΠΠΠΠƒ € INDEX TI RPL € „€€€€€€€€€€€€€€€… ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘• SELECTOR Figure 6-2. Address Spaces and Task Isolation ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘“  ‚ƒ   €TASK 1 €   €LOCAL €  TASK 3  €ADDRESS €  VIRTUAL ADDRESS SPACE “  €SPACE € ‘‘‘‘TASK 1   „…  VIRTUAL ADDRESS SPACE ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“  ‚ƒ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“  €TASK 3 € ‚ƒ  ‚ƒ   €LOCAL € €GLOBAL €  €TASK 2 €   €ADDRESS € €ADDRESS €  €LOCAL €   €SPACE € €SPACE €  €ADDRESS €   „… „…  €SPACE €  ”‘‘‘‘‘‘‘‘‘‘‘‘‘”‘‘‘‘‘‘‘‘‘‘‘‘‘‘•• „…  ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•  ”TASK 2 VIRTUAL ADDRESS SPACE 6.3 Descriptor Tables A descriptor table is a memory-resident table either defined by program development tools in a static system or controlled by operating system software in systems that are reprogrammable. The descriptor table contents govern the interpretation of virtual addresses. Whenever the 80286 decodes a virtual address, translating a full 32-bit pointer into a corresponding 24-bit physical address, it implicitly references one of these tables. Within a Protected Mode system, there are ordinarily several descriptor tables resident in memory. One of these is the global descriptor table (GDT); this table provides a complete description of the global address space. In addition, there may be one or more local descriptor tables (LDTs), each describing the local address space of one or more tasks. For each task in the system, a pair of descriptor tables‘‘consisting of the GDT (shared by all tasks) and a particular LDT (private to the task or to a group of closely related tasks)‘‘provides a complete description of that task's virtual address space. The protection mechanism described in Chapter 7, "Protection," ensures that a task is granted access only to its own virtual address space. In the simplest of system configurations, tasks can reside entirely within the GDT without the use of local descriptor tables. This will simplify system software by only requiring maintenance of one table (the GDT) at the expense of no isolation between tasks. The point is: the 80286 memory management scheme is flexible enough to accommodate a variety of implementations and does not require use of all possible facilities when implementing a system. The descriptor tables consist of a sequence of 8-byte entries called descriptors. A descriptor table may contain from 1 to 8192 entries. Within a descriptor table, two main classes of descriptors are recognized by the 80286 architecture. The most important of these, from the standpoint of memory management, are called segment descriptors; these determine the set of segments that are included within a given address space. The other class are special-purpose control descriptors‘‘such as call gates and task descriptors‘‘to implement protection (described in succeeding chapters) and special system data segments. Figure 6-3 shows the format of a segment descriptor. Note that it provides information about the physical-memory base address and size of a segment, as well as certain access information. If a particular segment is to be included within a virtual address space, then a segment descriptor that describes that segment must be included within the appropriate descriptor table. Thus, within the GDT, there are segment descriptors for all of the segments that comprise a system's global address space. Similarly, within a task's LDT, there must be a descriptor for each of the segments that are to be included in that task's local address space. Each local descriptor table is itself a special system segment, recognizable as such by the 80286 architecture and described by a specific type of segment descriptor (see figure 6-4). Because there is only a single GDT segment, it is not defined by a segment descriptor. Its base and size information is maintained in a dedicated register, GDTR, as described below (section 6.6.2). Similarly, there is another dedicated register within the 80286, LDTR, that records the base and size of the current LDT segment (i.e., the LDT associated with the currently executing task). The LDTR register state, however, is volatile: its contents are automatically altered whenever a task switch is made from one task to another. An alternate specification independent of changeable register contents must therefore exist for each LDT in the system. This independent specification is accomplished by means of special system segment descriptors known as descriptor table descriptors or LDT descriptors. Figure 6-4 shows the format of a descriptor table descriptor. (Note that it is distinguished from an ordinary segment descriptor by the contents of certain bits in the access byte.) This special type of descriptor is used to specify the physical base address and size of a local descriptor table that defines the virtual address space and address mapping for an individual user or task (figure 6-5). Each LDT segment in a system must lie within that system's global address space. Thus, all of the descriptor table descriptors must be included among the entries in the global descriptor table (the GDT) of a system. In fact, these special descriptors may appear only in the GDT. Reference to an LDT descriptor within an LDT will cause a protection violation. Even though they are in the global address space available to all tasks, the descriptor table descriptors are protected from corruption within the GDT since they are special system segments and can only be accessed for loading into the LDTR register. Figure 6-3. Segment Descriptors (S=1) 7 0 7 0 ‚Πƒ +7€ INTEL RESERVED Must be set to 0 for compatibility with iAPX 386 MUST BE 0 €+6 ACCESS Γ‘‘‘˜‘‘‘‘‘‘‘˜‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β +5€ P  DPL S=1 TYPE  A  BASE{23-16} €+4 RIGHTS Γ‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β +3€ BASE{15-0} €+2 BYTES Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β +1€ LIMIT{15-0} € 0 „€… 15 8 7 0 ACCESS RIGHTS BYTES: P = PRESENT DPL = DESCRIPTOR PRIVILEGE LEVEL S = SEGMENT DESCRIPTOR TYPE = SEGMENT TYPE AND ACCESS INFORMATION (see Figure 6-7) A = ACCESSED Figure 6-4. Special Purpose Descriptors or System Segment Descriptors (S=1) 7 0 7 0 ‚Πƒ +7€ INTEL RESERVED Must be set to 0 for compatibility with iAPX 386 MUST BE 0 €+6 Γ‘‘‘˜‘‘‘‘‘‘‘˜‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β +5€ P  DPL S=1 TYPE  BASE{23-16} €+4 Γ‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β +3€ BASE{15-0} €+2 €‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘€ +1€ LIMIT{15-0} € 0 „€… 15 8 7 0 ACCESS RIGHTS BYTES: P = PRESENT DPL = DESCRIPTOR PRIVILEGE LEVEL S = SEGMENT DESCRIPTOR TYPE = SEGMENT TYPE AND ACCESS INFORMATION (Includes control and system segments) 0 = INVALID DESCRIPTOR 1 = AVAILABLE TASK STATE SEGMENT 2 = LDT DESCRIPTOR 3 = BUSY TASK STATE SEGMENT 4-7 = CONTROL DESCRIPTOR (see Chapter 7) 8 = INVALID DESCRIPTOR (reserved by Intel) 9-F = RESERVED BY INTEL Figure 6-5. LDT Descriptors     € € ’‘€ € ’‘†‡  Έ Έ  € €    € €  € ONE € € €  †‡  € SEGMENT € †‡  € RESERVED ZERO €  € OF THE €SEGMENT € RESERVED ZERO €  †Π‡“  € TASKS €LIMIT †Π‡“  € BASE{23-16}  € LOCAL € € BASE{23-16}  †€‡–‘“  € (private) € †€‡–‘“  € BASE{15-0} €   € ADDRESS € € BASE{15-0} €   †‡•   € SPACE € †‡•   € BASE{15-0} Γ‘‘‘• € € € LIMIT{15-0} Γ‘‘‘• †‡ ”‘‘‘†‡SEGMENT †‡  € € € €BASE € LDT €  € € € €  DESCRIPTION IN   € € € € THE GDT IN MEMORY  †‡ € €  Έ Έ € €  € € € € ”‘‘‘†‡ € € € DESCRIPTOR € € SEGMENT €  TABLES IN RAM   IN RAM  6.4 Virtual-to-Physical Address Translation The translation of a full 32-bit virtual address pointer into a real 24-bit physical address is shown by figure 6-6. When the segment's base address is determined as a result of the mapping process, the offset value is added to the result to obtain the physical address. The actual mapping is performed on the selector component of the virtual address. The 16-bit segment selector is mapped to a 24-bit segment base address via a segment descriptor maintained in one of the descriptor tables. The TI bit in the segment selector (see figure 6-1) determines which of two descriptor tables, either the GDT or the current LDT, is to be chosen for memory mapping. In either case, using the GDTR or LDTR register, the processor can readily determine the physical base address of the memory-resident table. The INDEX field in the segment selector specifies a particular descriptor entry within the chosen table. The processor simply multiplies this index value by 8 (the length of a descriptor), and adds the result to the base address of the descriptor table in order to access the appropriate segment descriptor in the table. Finally, the segment descriptor contains the physical base address of the target segment, as well as size (limit) and access information. The processor sums the 24-bit segment base and the specified 16-bit offset to generate the resulting 24-bit physical address. Figure 6-6. Virtual-to-Physical Address Translation ‚ƒ € VIRTUAL ADDRESS € € ‚Πƒ €  TARGET  € € SELECTOR  OFFSET € € € SEGMENT € € „ΠΠ€Π… € € € „… € €   TI  € €   ‚ƒ Γ‘‘‘‘‘‘‘‘‘Β   €+Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘€ DATUM €  DESCRIPTOR „… PHYSICAL ADDRESS Γ‘‘‘‘‘‘‘‘‘Β   TABLE   € €  †‡  € €  Έ Έ  € €  Γ‘‘‘‘‘‘‘‘‘‘‘‘Β  € €  € SEGMENT €  SEGMENT BASE € €  € DESCRIPTOR Γ‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘†‡ ‘ ‘ ‘ ‘ ‘ ‘ Ξ‘‘‘‘‘‘‘‘‘‘‘‘Β € € INDEX  Έ Έ   ‘ ‘ ‘ ™ ‘ ‘ ΁‡   6.5 Segments and Segment Descriptors Segments are the basic units of 80286 memory management. In contrast to schemes based on fixed-size pages, segmentation allows for a very efficient implementation of software: variable-length segments can be tailored to the exact requirements of an application. Segmentation, moreover, is consistent with the way a programmer naturally deals with his virtual address space: programmers are encouraged to divide code and data into clearly defined modules and structures which are manipulated as consistent entities. This reduces (minimizes) the potential for virtual memory thrashing. Segmentation also eliminates the restrictions on data structures that span a page (e.g., a word that crosses page boundaries). Each segment within an 80286 system is defined by an associated segment descriptor, which may appear in one or more descriptor tables. Its inclusion within a descriptor table represents the presence of its associated segment within the virtual address space defined by that table. Conversely, its ommission from a descriptor table means that the segment is absent from the corresponding address space. As shown previously in figure 6-3, an 8-byte segment descriptor encodes the following information about a particular segment: Ž Size. This 16-bit field, comprising bytes 0 and 1 of a segment descriptor, specifies an unsigned integer as the size, in bytes (from 1 byte to 64K bytes), of the segment. Unlike segments in the 8086 (or the 80286 in Real Address Mode)‘‘which are never explicitly limited to less than a full 64K bytes‘‘Protected Mode segments are always assigned a specific size value. In conjunction with the protection features described in Chapter 7, this assigned size allows the enforcement of a very desirable and natural rule: inadvertent accesses to locations beyond a segment's actual boundaries are prohibited. Ž Base. This 24-bit field, comprising bytes 2 through 4 of a segment descriptor, specifies the physical base address of the segment; it thus defines the actual location of the segment within the 16-megabyte real memory space. The base may be any byte address within the 16-megabyte real memory space. Ž Access. This 8-bit field comprises byte 5 of a segment descriptor. This access byte specifies a variety of additional information about a segment, particularly in regard to the protection features of the 80286. For example, code segments are distinguished from data segments; and certain special access restrictions (such as Execute-Only or Read-Only) may be defined for segments of each type. Access byte values of 00H or 80H will always denote "invalid." Figure 6-7 shows the access byte format for both code and data segment descriptors. Detailed discussion of the protection related fields within an access byte (Conforming, Execute-Only, Descriptor Privilege Level, Expand Down, and Write-Permitted), and their use in implementing protection policies, is deferred to Chapter 7. The two fields Accessed and Present are used for virtual memory implementations. Figure 6-7. Segment Descriptor Access Bytes CODE SEGMENT TYPE MSB ’‘‘‘‘‘™‘‘‘‘‘“LSB ‚ΠΠΠΠΠΠƒ € P  DPL  1  1  C  R  A € „€€€€€€…  ”‘‘˜‘‘•      PRESENT (1 = yes)‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•       DESCRIPTOR PRIVILEGE LEVEL‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•      (indicates segment descriptor)‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•     EXECUTABLE (1 = yes for code)‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•    CONFORMING (1 = yes)‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•   READABLE (1 = yes)‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•  ACCESSED (1 = yes)‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘• DATA OR STACK SEGMENT MSB LSB ‚ΠΠΠΠΠΠƒ € P  DPL  1  0  ED  W  A € „€€€€€€…        PRESENT (1 = yes)‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•       DESCRIPTOR PRIVILEGE LEVEL‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•      (indicates segment descriptor)‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•     EXECUTABLE (0 = no for data) ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•    CONFORMING (1 = yes)‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•   WRITEABLE (1 = yes)‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•  ACCESSED (1 = yes)‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘• 6.6 Memory Management Registers The Protected Virtual Address Mode features of the 80286 operate at high performance due to extensions to the basic 8086 register set. Figure 6-8 illustrates that portion of the extended register structure that pertains to memory management. (For a complete summary of all Protected Mode registers, refer to section 10.1). 6.6.1 Segment Address Translation Registers Figure 6-8 shows the segment registers CS, DS, ES, and SS. In contrast to their usual representation, however, these registers are now depicted as 64-bit registers, each with "visible" and "hidden" components. The visible portions of these segment address translation registers are manipulated by programs exactly as if they were simply the 16-bit segment registers of Real Address Mode. By loading a segment selector into one of these registers, the program makes the associated segment one of its four currently addressable segments. The operations that load these registers‘‘or, more exactly, those that load the visible portion of these registers‘‘are normal program instructions. These instructions may be divided into two categories: 1. Direct segment-register load instructions. These instructions (such as LDS, LES, MOV, POP, etc.) can explicitly reference the SS, DS, or ES segment registers as the destination operand. 2. Implied segment-register load instructions. These instructions (such as intersegment CALL and JMP) implicitly reference the CS code segment register; as a result of these operations, the contents of CS are altered. Using these instructions, a program loads the visible part of the segment register with a 16-bit selector (i.e., the high-order word of a virtual address pointer). Whenever this is done, the processor automatically uses the selector to reference the appropriate descriptor and loads the 48-bit hidden descriptor cache for that segment register. The correspondence between selectors and descriptors has already been described. Remember that the selector's TI bit indicates one of the two descriptor tables, either the LDT or the GDT. Within the indicated table, a particular entry is chosen by the selector's 13-bit INDEX field. This index, scaled by a factor of 8, represents the relative displacement of the chosen table entry (a descriptor). Thus, so long as a particular selector value is valid (i.e., it points to a valid segment descriptor within the bounds of the descriptor table), it can be readily associated with an 8-byte descriptor. When a selector value is loaded into the visible part of a segment register, the 80286 automatically loads 6 bytes of the associated descriptor into the hidden part of the register. These 6 bytes, therefore, contain the size, base, and access type of the selected segment. Figure 6-9 illustrates this transparent process of descriptor loading. In effect, the hidden descriptor fields of the segment registers function as the memory management cache of the 80286. All the information required to address the current working set of segments‘‘that is, the base address, size, and access rights of the currently addressable segments‘‘is stored in this memory cache. Unlike the probabilistic caches of other architectures, however, the 80286 cache is completely deterministic: the caching of descriptors is explicitly controlled by the program. Most memory references do not require the translation of a full 32-bit virtual address, or long pointer. Operands that are located within one of the currently addressable segments, as determined by the four segment registers, can be referenced very efficiently by means of a short pointer, which is simply a 16-bit offset. In fact, most 80286 instructions reference memory locations in precisely this way, specifying only a 16-bit offset with respect to one of the currently addressable segments. The choice of segments (CS, DS, ES, or SS) is either implicit within the instruction itself, or explicitly specified by means of a segment-override prefix (as described in Chapter 2). Thus, in most cases, virtual-to-physical address translation is actually performed in two separate steps. First, when a program loads a new value into a segment register, the processor immediately performs a mapping operation; the physical base address of the selected segment (as well as certain additional information) is automatically loaded into the hidden portion of the register. The internal cache registers (virtual address translation hardware) are therefore dynamically shared among the 16K different segments potentially addressable within the user's virtual address space. No software overhead (either system or application) is required to perform this operation. Subsequently, as the program utilizes a short pointer to reference a location within a segment, the processor generates a 24-bit physical address simply by adding the specified offset value to the previously cached segment base address. By encouraging the use of short pointers in this way, rather than requiring a full 32-bit virtual address for every memory reference, the 80286 provides a very efficient on-chip mechanism for address translation, with minimum overhead for references to memory-based tables or the need for external address-translation devices. Figure 6-8. Memory Management Registers SEGMENT ADDRESS TRANSLATION REGISTERS 16-BIT 48-BIT HIDDEN DESCRIPTOR CACHE SELECTOR (PROGRAM INVISIBLE‘‘LOADED BY CPU) ‚ΠΠΠƒ CS€    €CODE SEGMENT REGISTER Γ‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β DS€    €DATA SEGMENT REGISTER Γ‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β ES€    €EXTRA SEGMENT REGISTER Γ‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β SS€    €STACK SEGMENT REGISTER „€€€… 63 48 47 40 39 16 15 0 ACCESS SEGMENT BASE SEGMENT RIGHTS ADDRESS SIZE SYSTEM ADDRESS REGISTERS 40-BIT EXPLICIT REGISTER ‚Πƒ GDTR € €GLOBAL DESCRIPTOR TABLE REGISTER Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘Β IDTR € €INTERRUPT DESCRIPTOR TABLE REGISTER „€… 39 16 15 0 BASE LIMIT 16-BIT VISIBLE 40-BIT HIDDEN SELECTOR DESCRIPTOR CACHE ‚ΠΠƒ LDTR€  €LOCAL DESCRIPTOR TABLE REGISTER „€€… 55 40 39 16 15 0 BASE LIMIT Figure 6-9. Descriptor Loading ’‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘“  CPU  APPLICATION DESCRIPTOR    VISIBLE CACHE  € SYSTEM € ’‘‘‘‘™‘‘‘‘‘“ ’‘‘‘‘™‘‘‘‘‘“ € MEMORY €  SEGMENT SEGMENT  € € REGISTER DESCRIPTOR € €  ‚ƒ ‚ƒ  € € € SELECTOR € € TYPE € € €  „Π… Γ‘‘‘‘‘‘‘‘‘‘Β  € € € BASE € € €   Γ‘‘‘‘‘‘‘‘‘‘Β  Έ Έ € LIMIT € € €   „…  € €  € €   TRANSPARENT € € DESCRIPTOR †‡‘“   LOADING  € €  ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Ξ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β     € € –‘DESCRIPTOR ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β  TABLE  ”‘‘ ‘‘ ‘‘ ‘‘ ‘‘   INDEX  € €  ’ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘™ ‘‘ ‘‘ ‘‘ †‡‘•   € € ‚€ƒ € €  €DESCRIPTOR€  € € €TABLE BASE€ € €  „…    ”‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘• 6.6.2 System Address Registers The Global Descriptor Table Register (GDTR) is a dedicated 40-bit (5 byte) register used to record the base and size of a system's global descriptor table (GDT). Thus, two of these bytes define the size of the GDT, and three bytes define its base address. In figure 6-8, the contents of the GDTR are referred to as a "hidden descriptor." The term "descriptor" here emphasizes the analogy with the segment descriptors ordinarily found in descriptor tables. Just as these descriptors specify the base and size (limit) of ordinary segments, the GDTR register specifies these same parameters for that segment of memory serving as the system GDT. The limit prevents accesses to descriptors in the GDT from accessing beyond the end of the GDT and thus provides address space isolation at the system level as well as at the task level. The register contents are "hidden" only in the sense that they are not accessible by means of ordinary instructions. Instead, the dedicated protected instructions LGDT and SGDT are reserved for loading and storing, respectively, the contents of the GDTR at Protected Mode initialization (refer to section 10.2 for details). Subsequent alteration of the GDT base and size values is not recommended but is a system option at the most privileged level of software (see section 7.3 for a discussion of privilege levels). The Local Descriptor Table Register (LDTR) is a dedicated 40-bit register that contains, at any given moment, the base and size of the local descriptor table (LDT) associated with the currently executing task. Unlike GDTR, the LDTR register contains both a "visible" and a "hidden" component. Only the visible component is accessible, while the hidden component remains truly inaccessible even to dedicated instructions. The visible component of the LDTR is a 16-bit "selector" field. The format of these 16 bits corresponds exactly to that of a segment selector in a virtual address pointer. Thus, it contains a 13-bit INDEX field, a 1-bit TI field, and a 2-bit RPL field. The TI "table indicator" bit must be zero, indicating a reference to the GDT (i.e., to global address space). The INDEX field consequently provides an index to a particular entry within the GDT. This entry, in turn, must be an LDT descriptor (or descriptor table descriptor), as defined in the previous section. In this way, the visible "selector" field of the LDTR, by selecting an LDT descriptor, uniquely designates a particular LDT in the system. The dedicated, protected instructions LLDT and SLDT are reserved for loading and storing, respectively, the visible selector component of the LDTR register (refer to section 10.2 for details). Whenever a new value is loaded into the visible "selector" portion of LDTR, an LDT descriptor will have been uniquely chosen (assuming, of course, that the "selector" value is valid). In this case, the 80286 automatically loads the hidden "descriptor" portion of LDTR with five bytes from the chosen LDT descriptor. Thus, size and base information about a particular LDT, as recorded in a memory-resident global descriptor table entry, is cached in the LDTR register. New values may be loaded into the visible portion of the LDTR (and, thus, into the hidden portion as well) in either of two ways. The LLDT instruction, during system initialization, is used explicitly to set an initial value for the LDTR register; in this way, a local address space is provided for the first task in a multitasking environment. After system startup, explicit changes are not required since operations that automatically invoke a task switch (described in section 8.4) appropriately manage the LDTR. At all times, the LDTR register thus records the physical base address (and size) of the current task's LDT; the descriptor table required for mapping the current local address space, therefore, is immediately accessible to the processor. Moreover, since GDTR always maintains the base address of the GDT, the table that maps the global address space is similarly accessible. The two system address registers, GDTR and LDTR, act as a special processor cache, maintaining current information about the two descriptor tables required, at any given time, for addressing the entire current virtual address space. Chapter 7 Protection ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ 7.1 Introduction In most microprocessor based products, the product's availability, quality, and reliability are determined by the software it contains. Software is often the key to a product's success. Protection is a tool used to shorten software development time, and improve software quality and reliability. Program testing is an important step in developing software. A system with protection will detect software errors more quickly and accurately than a system without protection. Eliminating errors via protection reduces the development time for a product. Testing software is difficult. Many errors occur only under complex circumstances which are difficult to anticipate. The result is that products are shipped with undetected errors. When such errors occur, products appear unreliable. The impact of a software error is multiplied if it introduces errors in other bug-free programs. Thus, the total system reliability reduces to that of the least reliable program running at any given time. Protection improves the reliability of an entire system by preventing software errors in one program from affecting other programs. Protection can keep the system running even when some user program attempts an invalid or prohibited operation. Hardware protection performs run-time checks in parallel with the execution of the program. But, hardware protection has traditionally resulted in a design that is more expensive and slower than a system without protection. However, the 80286 provides hardware-enforced protection without the performance or cost penalties normally associated with protection. The protected mode 80286 implements extensive protection by integrating these functions on-chip. The 80286 protection is more comprehensive and flexible than comparable solutions. It can locate and isolate a large number of program errors and prevent the propagation of such errors to other tasks or programs. The protection of the total system detects and isolates bugs both during development and installed usage. Chapter 9 discusses exceptions in more detail. The remaining sections of this chapter explain the protection model implemented in the 80286. 7.1.1 Types of Protection Protection in the 80286 has three basic aspects: 1. Isolation of system software from user applications. 2. Isolation of users from each other (Inter-task protection). 3. Data-type checking. The 80286 provides a four-level, ringed-type, increasingly-privileged protection mechanism to isolate applications software from various layers of system software. This is a major improvement and extension over the simpler two-level user/supervisor mechanism found in many systems. Software modules in a supervisor level are protected from modules in the application level and from software in less privileged supervisor levels. Restricting the addressability of a software module enables an operating system to control system resources and priorities. This is especially important in an environment that supports multiple concurrent users. Multi-user, multi-tasking, and distributed processing systems require this complete control of system resources for efficient, reliable operation. The second aspect of protection is isolating users from each other. Without such isolation an error in one user program could affect the operation of another error-free user program. Such subtle interactions are difficult to diagnose and repair. The reliability of applications programs is greatly enhanced by such isolation of users. Within a system or application level program, the 80286 will ensure that all code and data segments are properly used (e.g., data cannot be executed, programs cannot be modified, and offset must be within defined limits, etc.). Such checks are performed on every memory access to provide full run-time error checking. 7.1.2 Protection Implementation The protection hardware of the 80286 establishes constraints on memory and instruction usage. The number of possible interactions between instructions, memory, and I/O devices is practically unlimited. Out of this very large field the protection mechanism limits interactions to a controlled, understandable subset. Within this subset fall the list of "correct" operations. Any operation that does not fall into this subset is not allowed by the protection mechanism and is signalled as a protection violation. To understand protection on the 80286, you must begin with its basic parts: segments and tasks. 80286 segments are the smallest region of memory which have unique protection attributes. Modular programming automatically produces separate regions of memory (segments) whose contents are treated as a whole. Segments reflect the natural construction of a program, e.g., code for module A, data for module A, stack for the task, etc. All parts of the segment are treated in the same way by the 80286. Logically separate regions of memory should be in separate segments. The memory segmentation model (see figure 7-1) of the 80286 was designed to optimally execute code for software composed of independent modules. Modular programs are easier to construct and maintain. Compared to monolithic software systems, modular software systems have enhanced capabilities, and are typically easier to develop and test for proper operation. Each segment in the system is defined by a memory-resident descriptor. The protection hardware prevents accesses outside the data areas and attempts to modify instructions, etc., as defined by the descriptors. Segmentation on the 80286 allows protection hardware to be integrated into the CPU for full data access control without any performance impact. The segmented memory architecture of the 80286 provides unique capabilities for regulating the transfer of control between programs. Programs are given direct but controlled access to other procedures and modules. This capability is the heart of isolating application and system programs. Since this access is provided and controlled directly by the 80286 hardware, there is no performance penalty. A system designer can take advantage of the 80286 access control to design high-performance modular systems with a high degree of confidence in the integrity of the system. Access control between programs and the operating system is implemented via address space separation and a privilege mechanism. The address space control separates applications programs from each other while the privilege mechanism isolates system software from applications software. The privilege mechanism grants different capabilities to programs to access code, data, and I/O resources based on the associated protection level. Trusted software that controls the whole system is typically placed at the most privileged level. Ordinary application software does not have to deal with these control mechanisms. They come into play only when there is a transfer of control between tasks, or if the Operating System routines have to be invoked. The protection features of multiple privilege levels extend to ensuring reliable I/O control. However, for a system designer to enable only one specific level to do I/O would excessively constrain subsequent extensions or application development. Instead, the 80286 permits each task to be assigned a separate minimum level where I/O is allowed. I/O privilege is discussed in section 10.3. An important distinction exists between tasks and programs. Programs (e.g., instructions in code segments) are static and consist of a fixed set of code and data segments each with an associated privilege level. The privilege assigned to a program determines what the program may do when executed by a task. Privilege is assigned to a program when the system is built or when the program is loaded. Tasks are dynamic; they execute one or more programs. Task privilege changes with time according to the privilege level of the program being executed. Each task has a unique set of attributes that define it, e.g., address space, register values, stack, data, etc. A task may execute a program if that program appears in the task's address space. The rules of protection control determine when a program may be executed by a task, and once executed, determine what the program may do. Figure 7-1. Addressing Segments of a Module within a Task ’‘ ‘‘ ‘“ ‚ƒ € CODE € Γ‘‘‘‘‘‘Β MODULE A € DATA € „… CPU   ’‘‘‘‘‘‘‘‘‘‘‘“ ‚ƒ  ‚ƒ  € CODE €  € CODE Γ‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Γ‘‘‘‘‘‘Β MODULE B  Γ‘‘‘‘‘‘‘Β  € DATA €  € DATA Γ‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘„…  Γ‘‘‘‘‘‘‘Β     € STACK Γ‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“ ‚ƒ  Γ‘‘‘‘‘‘‘Β   € € TASK STACK  € EXTRA Γ‘š‘‘‘‘‘‘‘‘‘‘‘“ ”‘‘‘‘‘‘‘‘‘„…  „…      SEGMENT   ‚ƒ TASK  REGISTERS   € € DATA ”‘‘‘‘‘‘‘‘‘‘‘• ”‘‘‘‘‘‘‘‘‘‘‘‘‘„… BLOCK 1   ‚ƒ TASK € € DATA „… BLOCK 2 ”‘ ‘‘ ‘• MEMORY 7.2 Memory Management and Protection The protection hardware of the 80286 is related to the memory management hardware. Since protection attributes are assigned to segments, they are stored along with the memory management information in the segment descriptor. The protection information is specified when the segment is created. In addition to privilege levels, the descriptor defines the segment type (e.g., Code segment, Data segment, etc.). Descriptors may be created either by program development tools or by a loader in a dynamically loaded reprogrammable environment. The protection control information consists of a segment type, its privilege level, and size. These are fields in the access byte of the segment descriptor (see figure 7-2). This information is saved on-chip in the programmer invisible section of the segment register for fast access during execution. These entries are changed only when a segment register is loaded. The protection data is used at two times: upon loading a segment register and upon each reference to the selected segment. The hardware performs several checks while loading a segment register. These checks enforce the protection rules before any memory reference is generated. The hardware verifies that the selected segment is valid (is identified by a descriptor, is in memory, and is accessible from the privilege level in which the program is executing) and that the type is consistent with the target segment register. For example, you cannot load a read-only segment descriptor into SS because the stack must always be writable. Each reference into the segment defined by a segment register is checked by the hardware to verify that it is within the defined limits of the segment and is of the proper type. For example, a code segment or read-only data segment cannot be written. All these checks are made before the memory cycle is started; any violation will prevent that cycle from starting and cause an exception to occur. Since the checks are performed concurrently with address formation, there is no performance penalty. By controlling the access rights and privilege attributes of segments, the system designer can assure a program will not change its code or overwrite data belonging to another task. Such assurances are vital to maintaining system integrity in the face of error-prone programs. Figure 7-2. Descriptor Cache Registers ’‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘“ PROGRAM VISIBLE  PROGRAM INVISIBLE   ACCESS  SEGMENT SELECTORS RIGHTS SEGMENT BASE ADDRESS SEGMENT SIZE ‚ƒ  ‚ΠΠƒ  CSΓ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β Γ‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β DSΓ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β  Γ‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β  SSΓ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β Γ‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β „…  „€€…  15 0 47 40 39 16 15 0   SEGMENT REGISTERS SEGMENT DESCRIPTOR CACHE REGISTERS (loaded by program)  (loaded by CPU)  ”‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘• 7.2.1 Separation of Address Spaces As described in Chapter 6, each task can address up to a gigabyte (2^(14) - 2 segments of up to 65,536 bytes each) of virtual memory defined by the task's LDT (Local Descriptor Table) and the system GDT. Up to one-half gigabyte (2^(13) segments of up to 65,536 bytes each) of the task's address space is defined by the LDT and represents the task's private address space. The remaining virtual address space is defined by the GDT and is common to all tasks in the system. Each descriptor table is itself a special kind of segment recognized by the 80286 architecture. These tables are defined by descriptors in the GDT (Global Descriptor Table). The CPU has a set of base and limit registers that point to the GDT and the LDT of the currently running task. The local descriptor table register is loaded by a task switch operation. An active task can only load selectors that reference segments defined by descriptors in either the GDT or its private LDT. Since a task cannot reference descriptors in other LDTs, and no descriptors in its LDT refer to data or code belonging to other tasks, it cannot gain access to another tasks' private code and data (see figure 7-3). Since the GDT contains information that is accessible by all users (e.g., library routines, common data, Operating System services, etc.), the 80286 uses privilege levels and special descriptor types to control access (see section 7.2.2). Privilege levels protect more trusted data and code (in GDT and LDT) from less trusted access (WITHIN a task), while the private virtual address spaces defined by unique LDTs provide protection BETWEEN tasks (see figure 7-4). Figure 7-3. 80286 Virtual Address Space ‚ƒ ‚ƒ € ‚ƒ € € ‚ƒ65535 € € € ‚ƒ65535 € € € € SEG. €  € € € € SEG. €  € € € € €OFFSET€ € € € €OFFSET€ € € 8191‚ƒ ’‘„…0  € € € 8191‚ƒ ’‘„…0  € € €  € LDT Γ‘‘‘•  € € €  € LDT Γ‘‘‘•  € € €  € A Γ‘‘‘“  € € €  € B Γ‘‘‘“  € € € 0„…   € € € 0„…   € € €  ‚ƒ65535 € € €  ‚ƒ65535 € € €  € SEG. €  € € €  € SEG. €  € € €  € €OFFSET€ € €  € €OFFSET€ € € ”‘„…0  € € € ”‘„…0  € € „… € „… € TASK A PRIVATE ADDRESS SPACE € TASK B PRIVATE ADDRESS SPACE € € € ‚ƒ € ‚ƒ € € ‚ƒ65535 € € € ‚ƒ65535 € € € € SEG. €  € € € € SEG. €  € € € € €OFFSET€ € € € €OFFSET€ € € 8191‚ƒ ’‘„…0  € € € 8191‚ƒ ’‘„…0  € € €  € LDT Γ‘‘‘•  € € €  € GDT Γ‘‘‘•  € € €  € C Γ‘‘‘“  € € €  € Γ‘‘‘“  € € € 0„…   € € € 0„…   € € €  ‚ƒ65535 € € €  ‚ƒ65535 € € €  € SEG. €  € € €  € SEG. €  € € €  € €OFFSET€ € €  € €OFFSET€ € € ”‘„…0  € € € ”‘„…0  € € „… € „… € TASK C PRIVATE ADDRESS SPACE € SHARED ADDRESS SPACE € „… TASK B ADDRESS SPACE Figure 7-4. Local and Global Descriptor Table Definitions MEMORY   ’‘˜‘‘‘Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β‘“  Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β  CPU   Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β  ‚ƒ  € ¨ €  € €   € ¨ € –‘ GDT € 15 0 €  € ¨ €  € ‚ƒ €   Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β  € 23 €LDT LIMITΓ‘‘‘Ξ‘• Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β  € ‚π‘‘‘‘‘‘‘‘‘Β €  Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β  GDTR € € GDT BASE Γ‘‘‘Ξ‘‘‘‘‘‘‘Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β‘• € „… € € € € € € € Γ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘Β € € € € € LDT{1} € € 15 0 € ’‘˜‘‘‘Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β‘“ € ‚ƒ €  Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β  € € LDT € €   Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β  € € SELECTOR € €  € ¨ €  € „… €   € ¨ € –‘ CURRENT LDT €’‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘“€  € ¨ €  € 15 0 €   Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β  € ‚ƒ €  Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β  € 23 €LDT LIMITΓ‘‘šΞ‘•  Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β  € ‚π‘‘‘‘‘‘‘‘‘Β € ’‘‘‘‘Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β‘• LDTR € € LDT BASE Γ‘‘šΓ‘‘• € € € „… € € € € PROGRAM INVISIBLE € € € €”‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘•€ € LDT{n} € „… Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β € ¨ € € ¨ € € ¨ € Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β   7.2.2 LDT and GDT Access Checks All descriptor tables have a limit used by the protection hardware to ensure address space separation of tasks. Each task's LDT can be a different size as defined by its descriptor in the GDT. The GDT may also contain less than 8191 descriptors as defined by the GDT limit value. The descriptor table limit identifies the last valid byte of the last descriptor in that table. Since each descriptor is eight bytes long, the limit value is N * 8 - 1 for N descriptors. Any attempt by a program to load a segment register, local descriptor table register (LDTR), or task register (TR) with a selector that refers to a descriptor outside the corresponding limit causes an exception with an error code identifying the invalid selector used (see figure 7-5). Not all descriptor entries in the GDT or LDT need contain a valid descriptor. There can be holes, or "empty" descriptors, in the LDT and GDT. "Empty" descriptors allow dynamic allocation and deletion of segments or other system objects without changing the size of the GDT or LDT. Any descriptor with an access byte equal to zero is considered empty. Any attempt to load a segment register with a selector that refers to an empty descriptor will cause an exception with an error code identifying the invalid selection. Figure 7-5. Error Code Format (on the stack) 15 3 2 1 0 ‚ΠΠΠƒ €  T  I  E € € INDEX  I  D  X € €   T  T € „€Π€Π€Π… ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•    ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•     ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•     ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•      ’‘‘‘‘‘‘‘“’‘‘‘‘‘‘‘‘‘“’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“  Entry  1 means  1 means use  1 means that an event external to   in  use  IDT and  the program caused the exception   IDT,  LDT  ignore  (i.e., external interrupt, single   GDT,  0 means  bit 2.  step, processor extension error)   or  use  0 means bit 2  0 means that an exception occurred   LDT  GDT  indicates  while processing the instruction     table usage  at CS:IP saved on the stack.  ”‘‘‘‘‘‘‘•”‘‘‘‘‘‘‘‘‘•”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘• 7.2.3 Type Validation After checking that a selector reference is within the bounds of a descriptor table and refers to a non-empty descriptor, the type of segment defined by the descriptor is checked against the destination register. Since each segment register has predefined functions, each must refer to certain types of segments (see section 7.4.1). An attempt to load a segment register in violation of the protection rules causes an exception. The "null" selector is a special type of segment selector. It has an index field of all zeros and a table indicator of 0. The null selector appears to refer to GDT descriptor entry #0 (see GDT in figure 7-3). This selector value may be used as a place holder in the DS or ES segment registers; it may be loaded into them without causing an exception. However, any attempt to use the null segment registers to reference memory will cause an exception and prevent any memory cycle from occurring. 7.3 Privilege Levels and Protection As explained in section 6.2, each task has its own separate virtual address space defined by its LDT. All tasks share a common address space defined by the GDT. The system software then has direct access to task data and can treat all pointers in the same way. Protection is required to prevent programs from improperly using code or data that belongs to the operating system. The four privilege levels of the 80286 provide the isolation needed between the various layers of the system. The 80286 privilege levels are numbered from 0 to 3, where 0 is the most trusted level, 3 the least. Privilege level is a protection attribute assigned to all segments. It determines which procedures can access the segment. Like access rights and limit checks, privilege checks are automatically performed by the hardware, and thus protect both data and code segments. Privilege on the 80286 is hierarchical. Operating system code and data segments placed at the most privileged level (0) cannot be accessed directly by programs at other privilege levels. Programs at privilege level 0 may access data at all other levels. Programs at privilege levels 1-3 may only access data at the same or less trusted (numerically greater) privilege levels. Figure 7-6 illustrates the privilege level protection of code or data within tasks. In figure 7-6, programs can access data at the same or outer level, but not at inner levels. Code and data segments placed at level 1 cannot be accessed by programs executing at levels 2 or 3. Programs at privilege level 0 can access data at level 1 in the course of providing service to that level. 80286 provides mechanisms for inter-level transfer of control when needed (see section 7.5). The four privilege levels of the 80286 are an extension of the typical two-level user/supervisor privilege mechanism. Like user mode, application programs in the outer level are not permitted direct access to data belonging to more privileged system services (supervisor mode). The 80286 adds two more privilege levels to provide protection for different layers of system software (system services, I/O drivers, etc.). Figure 7-6. Code and Data Segments Assigned to a Privilege Level TASK C ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“  ‚ƒ   € APPLICATIONS €   € ‚ƒ €   € € CUSTOM EXTENSIONS € €   € € ‚ƒ € €   € € € SYSTEM SERVICES € € €   € € € ‚ƒ € € €   € € € € KERNAL € € € €  γΓ‘‘‘‘‘Ξ‘‘‘‘‘Ξ‘‘‘‘‘Ξ‘‘‘‘‘˜‘‘‘‘‘Ξ‘‘‘‘‘Ξ‘‘‘‘‘Ξ‘‘‘‘‘Α  € € € € LEVEL€LEVEL€LEVEL€LEVEL€   € € € €  0 € 1 € 2 € 3 €   € € € „Ο… € € €   € € €  € € €   € € „Ο… € €   € €  € €   € „Ο… €   €  €  TASK B— „€… –TASK A ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘• ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘• 7.3.1 Example of Using Four Privilege Levels Two extra privilege levels allow development of more reliable, and flexible system software. This is achieved by dividing the system into small, independent units. Figure 7-6 shows an example of the usage of different protection levels. Here, the most privileged level is called the kernel. This software would provide basic, application-independent, CPU-oriented services to all tasks. Such services include memory management, task isolation, multitasking, inter-task communication, and I/O resource control. Since the kernel is only concerned with simple functions and cannot be affected by software at other privilege levels, it can be kept small, safe, and understandable. Privilege level one is designated system services. This software provides high-level functions like file access scheduling, character I/O, data communcations, and resource allocation policy which are commonly expected in all systems. Such software remains isolated from applications programs and relies on the services of the kernel, yet cannot affect the integrity of level 0. Privilege level 2 is the custom operating system extensions level. It allows standard system software to be customized. Such customizing can be kept isolated from errors in applications programs, yet cannot affect the basic integrity of the system software. Examples of customized software are the data base manager, logical file access services, etc. This is just one example of protection mechanism usage. Levels 1 and 2 may be used in many different ways. The usage (or non-usage) is up to the system designer. Programs at each privilege level are isolated from programs at outer layers, yet cannot affect programs in inner layers. Programs written for each privilege level can be smaller, easier to develop, and easier to maintain than a monolithic system where all system software can affect all other system software. 7.3.2 Privilege Usage Privilege applies to tasks and three types of descriptors: 1. Main memory segments 2. Gates (control descriptors for state or task transitions, discussed in sections 7.5.1, 8.3, 8.4 and 9.2) 3. Task state segments (discussed in Chapter 8). Task privilege is a dynamic value. It is derived from the code segment currently being executed. Task privilege can change only when a control transfers to a different code segment. Descriptor privilege, including code segment privilege, is assigned when the descriptor (and any associated segment) is created. The system designer assigns privilege directly when the system is constructed with the system builder (see the 80286 Builder User's Guide) or indirectly via a loader. Each task operates at only one privilege level at any given moment: namely that of the code segment being executed. (The conforming segments discussed in section 11.2 permit some flexibility in this regard.) However, as figure 7-6 indicates, the task may contain segments at one, two, three, or four levels, all of which are to be used at appropriate times. The privilege level of the task, then, changes under the carefully enforced rules for transfer of control from one code segment to another. The descriptor privilege attribute is stored in the access byte of a descriptor and is called the Descriptor Privilege Level (DPL). Task privilege is called the Current Privilege Level (CPL). The least significant two bits of the CS register specify the CPL. A few general rules of privilege can be stated before the detailed discussions of later sections. Data access is restricted to those data segments whose privilege level is the same as or less privileged (numerically greater) than the current privilege level (CPL). Direct code access, e.g., via call or jump, is restricted to code segments of equal privilege. A gate (section 7.5.1) is required for access to code at more privileged levels. 7.4 Segment Descriptor Although the format of access control information, discussed below, is similar for both data and code segment descriptors, the rules for accessing data segments differ from those for transferring control to code segments. Data segments are meant to be accessible from many privilege levels, e.g., from other programs at the same level or from deep within the operating system. The main restriction is that they cannot be accessed by less privileged code. Code segments, on the other hand, are meant to be executed at a single privilege level. Transfers of control that cross privilege boundaries are tightly restricted, requiring the use of gates. Control transfers within a privilege level can also use gates, but they are not required. Control transfers are discussed in section 7.5. Protection checks are automatically invoked at several points in selecting and using new segments. The process of addressing memory begins when the currently executing program attempts to load a selector into one of the segment registers. As discussed in Chapter 6, the selector has the form shown in figure 7-7. When a new selector is loaded into a segment register, the processor accesses the associated descriptor to perform the necessary loading and privilege checks. The protection mechanism verifies that the selector points to a valid descriptor type for the segment register (see section 7.4.1). After verifying the descriptor type, the CPU compares the privilege level of the task (CPL) to the privilege level in the descriptor (DPL) before loading the descriptor's information into the cache. The general format of the eight bits in the segment descriptor's access rights byte is shown in table 7-1. For example, the access rights byte for a data and code segment present in real memory but not yet accessed (at the same privilege level) is shown in figure 7-8. Whenever a segment descriptor is loaded into a segment register, the accessed bit in the descriptor table is set to 1. This bit is useful for determining the usage profile of the segment. Table 7-1. Segment Access Rights Byte Format Bit Name Description 7 Present 1 means Present and addressable in real memory; 0 means not present. See section 11.3. 6,5 DPL 2-bit Descriptor Privilege Level, 0 to 3. 4 Segment 1 means Segment descriptor; 0 means control descriptor. For Segment=1, the remaining bits have the following meanings: 3 Executable 1 means code, 0 means data. 2 C or ED If code, Conforming: 1 means yes, 0 no. If data, Expand Down: 1 yes, 0 no‘‘normal case. 1 R or W If code, Readable: 1 means readable, 0 not. If data, Writable: 1 means writable, 0 not. 0 Accessed 1 if segment descriptor has been Accessed, 0 if not. ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ NOTE When the Segment bit (bit 4) is 0, the descriptor is for a gate, a task state segment, or a Local Descriptor Table, and the meanings of bits 0 through 3 change. Control transfers and descriptors are discussed in section 7.5. ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Table 7-2. Allowed Segment Types in Segment Registers Allowed Segment Types ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“ Segment Register Read Only Read-Write Execute Only Execute-Read Data Segment Data Segment Code Segment Code Segment DS Yes Yes No Yes ES Yes Yes No Yes SS No Yes No No CS No No Yes Yes ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ NOTE The Intel reserved bytes in the segment descriptor must be set to 0 for compatibility with the 80386. ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Figure 7-7. Selector Fields SELECTOR ‚ΠΠƒ € INDEX  T  € €  I  RPL € „€€€€€€€€€€€€€€€… 15 8 7 2 1 0 ‚ΠΠƒ € BITS  NAME  FUNCTION € Γ‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β € 1-0  REQUESTED PRIVELEGE  INDICATES SELECTOR PRIVILEGE LEVEL DESIRED € €  LEVEL (RPL)  € Γ‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β € 2  TABLE INDICATOR (TI)  TI = 0 USE GLOBAL DESCRIPTOR TABLE (GDT) € €   TI = 1 USE LOCAL DESCRIPTORTABLE (LDT) € Γ‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β € 15-3  INDEX  SELECT DESCRIPTOR ENTRY IN TABLE € „€€… Figure 7-8. Access Byte Examples READABLE CODE SEGMENT WRITABLE CODE SEGMENT P DPL S E C R A P DPL S E ED W A ‚ƒ ‚ƒ € 1 01 1 1 0 1 0 € € 1 01 1 0 0 1 0 € „… „… 7 0 7 0 7.4.1 Data Accesses Data may be accessed in data segments or readable code segments. When DS or ES is loaded with a new selector, e.g., by an LDS, LES, or MOV to ES, SS, or DS instruction, the bits in the access byte are checked to verify legitimate descriptor type and access (see table 7-2). If any test fails, an error code is pushed onto the stack identifying the selector involved (see figure 7-5 for the error code format). A privilege check is made when the segment register is loaded. In general, a data segment's DPL must be numerically greater than or equal to the CPL. The DPL of a descriptor loaded into the SS must equal the CPL. Conforming code segments are an exception to privilege checking rules (see section 11.2). Once the segment descriptor and selector are loaded, the offset of subsequent accesses within the segment are checked against the limit given in the segment descriptor. Violating the segment size limit causes a General Protection exception with an error code of 0. A normal data segment is addressed with offset values ranging from 0 to the size of the segment. When the ED bit of the access rights byte in the segment descriptor is 0, the allowed range of offsets is 0000H to the limit. If limit is 0FFFFH, the data segment contains 65,536 bytes. Since stacks normally occupy different offset ranges (lower limit to 0FFFFH) than data segments, the limit field of a segment descriptor can be interpreted in two ways. The Expand Down (ED) bit in the access byte allows offsets for stack segments to be greater than the limit field. When ED is 1, the allowed range of offsets within the segment is limit + 1 to 0FFFFH. To allow a full stack segment, set ED to 1 and the limit to 0FFFFH. The ED bit of a data segment descriptor does not have to be set for use in SS (i.e., it will not cause an exception). Section 7.5.1.4 discusses stack segment usage in greater detail. An expand down (ED=1) segment can also be loaded into ES or DS. Limit and access checks are performed before any memory reference is started. For stack push instructions (PUSH, PUSHA, ENTER, CALL, INT), a possible limit violation is identified before any internal registers are updated. Therefore, these instructions are fully restartable after a stack size violation. 7.4.2 Code Segment Access Code segments are accessed via CS for execution. Segments that are execute-only can ONLY be executed; they cannot be accessed via DS or ES, nor read via CS with a CS override prefix. If a segment is executable (bit 3=1 in the access byte), access via DS or ES is possible only if it is also readable. Thus, any code segment that also contains data must be readable. (Refer to Chapter 2 for a discussion of segment override prefixes.) An execute-only segment preserves the privacy of the code against any attempt to read it; such an attempt causes a general protection fault with an error code of 0. A code segment cannot be loaded into SS and is never writable. Any attempted write will cause a general protection fault with an error code of 0. The limit field of a code segment descriptor identifies the last byte in the segment. Any offset greater than the limit value will cause a general protection fault. The prefetcher of the 80286 can never cause a code segment limit violation with an error code of 0. The program must actually attempt to execute an instruction beyond the end of the code segment to cause an exception. If a readable non-conforming code segment is to be loaded into DS or ES, the privilege level requirements are the same as those stated for data segments in 7.4.1. Code segments are subject to different privilege checks when executed. The normal privilege requirement for a jump or call to another code segment is that the current privilege level equal the descriptor privilege level of the new code segment. Jumps and calls within the current code segment automatically obey this rule. Return instructions may pass control to code segments at the same or less (numerically greater) privileged level. Code segments at more privileged levels may only be reached via a call through a call gate as described in section 7.5. An exception to this, previously stated, is the conforming code segment that allows the DPL of the requested code segment to be numerically less than (of greater privilege than) the CPL. Conforming code segments are discussed in section 11.2. 7.4.3 Data Access Restriction by Privilege Level This section describes privilege verification when accessing either data segments (loading segment selectors into DS, ES, or SS) or readable code segments. Privilege verification when loading CS for transfer of control across privilege levels is described in the next section. Three basic kinds of privilege level indicators are used when determining accessibility to a segment for reading and writing. They are termed Current Privilege Level (CPL), Descriptor Privilege Level (DPL), and Requested Privilege Level (RPL). The CPL is simply the privilege level of the code segment that is executing (except if the current code segment is conforming). The CPL is stored as bits 0 and 1 of the CS and SS registers. Bits 0 and 1 of DS and ES are not related to CPL. DPL is the privilege level of the segment; it is stored in bits 5 and 6 of the access byte of a descriptor. For data access to data segments and non-conforming code segments, CPL must be numerically less than or equal to DPL (the task must be of equal or greater privilege) for access to be granted. Violation of this rule during segment load instruction causes a general protection exception with an error code identifying the selector. While the enforcement of DPL protection rules provides the mechanism for the isolation of code and data at different privilege levels, it is conceivable that an erroneous pointer passed onto a more trusted program might result in the illegal modification of data with a higher privilege level. This possibility is prevented by the enforcement of effective privilege level protection rules and correct usage of the RPL value. The RPL (requested privilege level) is used for pointer validation. It is the least significant two bits in the selector value loaded into any segment register. RPL is intended to indicate the privilege level of the originator of that selector. A selector may be passed down through several procedures at different levels. The RPL reflects the privilege level of the original supplier of the selector, not the privilege level of the intermediate supplier. The RPL must be numerically less than or equal to the DPL of the descriptor selected, thereby indicating greater or equal privilege of the supplier; otherwise, access is denied and a general protection violation occurs. Pointer validity testing is required in any system concerned with preventing program errors from destroying system integrity. The 80286 provides hardware support for pointer validity testing. The RPL field indicates the privilege level of the originator of the pointer to the hardware. Access will be denied if the originator of the pointer did not have access to the selected segment even if the CPL is numerically less than or equal to the DPL. RPL can reduce the effective privilege of a task when using a particular selector. RPL never allows access to more privileged segments (CPL must always be numerically less than or equal to DPL). A fourth term is sometimes used: the Effective Privilege Level (EPL). It is defined as the numeric maximum of the CPL and the RPL‘‘meaning the one of lesser privilege. Access to a protected entity is granted only when the EPL is numerically less than or equal to the DPL of that entity. This is simply another way of saying that both CPL and RPL must be numerically less than or equal to DPL for access to be granted. 7.4.4 Pointer Privilege Stamping via ARPL The ARPL instruction is provided in the 80286 to fill the RPL field of a selector with the minimum privilege (maximum numeric value) of the selector's current RPL and the caller's CPL (given in an instruction-specified register). A straight insertion of the caller's CPL would stamp the pointer with the privilege level of the caller, but not necessarily the ultimate originator of the selector (e.g., Level 3 supplies a selector to a level 2 routine that calls a level 0 routine with the same selector). Figure 7-9 shows a program with an example of such a situation. The program at privilege level 3 calls a routine at level 2 via a gate. The routine at level 2 uses the ARPL instruction to assure that the selector's RPL is 3. When the level 2 routine calls a routine at level 0 and passes the selector, the ARPL instruction at level 0 leaves the RPL field unchanged. Stamping a pointer with the originator's privilege eliminates the complex and time-consuming software typically associated with pointer validation in less comprehensive architectures. The 80286 hardware performs the pointer test automatically while loading the selector. Privilege errors are trapped at the time the selector is loaded because pointers are commonly passed to other routines, and it may not be possible to identify a pointer's originator. To verify the access capabilities of a pointer, it should be tested when the pointer is first received from an untrusted source. The VERR (Verify Read), VERW (Verify Write), and LAR (Load Access Rights) instructions are provided for this purpose. Although pointer validation is fully supported in the 80286, its use is an option of the system designer. To accommodate systems that do not require it, RPL can be ignored by setting selector RPLs to zero (except stack segment selectors) and not adjusting them with the ARPL instruction. Figure 7-9. Pointer Privilege Stamping Level 3 PUSH SELECTOR ; RPL value doesn't matter at level 3 CALL LEVEL_2 Level_2: ENTER 4,0 MOV AX, [BP] + 4 ; GET CS of return address, RPL=3 ARPL [BP] + 6, AX ; Put 3 in RPL field Level 2 ¨ ¨ ¨ PUSH WORD PTR [BP] + 6 ; Pass selector CALL LEVEL_0 Level_0: ENTER 6,0 Level 0 MOV AX, [BP] + 4 ; Get CS of return address, RPL=2 ARPL [BP] + 6, AX ; Leaves RPL unchanged 7.5 Control Transfers Three kinds of control transfers can occur within a task: 1. Within a segment, causing no change of privilege level (a short jump, call, or return). 2. Between segments at the same privilege level (a long jump, call, or return). 3. Between segments at different privilege levels (a long call, or return). (NOTE: A JUMP to a different privilege level is not allowed.) The first two types of control transfers need no special controls (with respect to privilege protection) beyond those discussed in section 7.4. Inter-level transfers require special consideration to maintain system integrity. The protection hardware must check that: Ž The task is currently allowed to access the destination address. Ž The correct entry address is used. To achieve control transfers, a special descriptor type called a gate is provided to mediate the change in privilege level. Control transfer instructions call the gate rather than transfer directly to a code segment. From the viewpoint of the program, a control transfer to a gate is the same as to another code segment. Gates allow programs to use other programs at more privileged levels in the same manner as a program at the same privilege level. Programmers need never distinguish between programs or subroutines that are more privileged than the current program and those that are not. The system designer may, however, elect to use gates only for control transfers that cross privilege levels. 7.5.1 Gates A gate is a four-word control descriptor used to redirect a control transfer to a different code segment in the same or more privileged level or to a different task. There are four types of gates: call, trap, interrupt, and task gates. The access rights byte distinguishes a gate from a segment descriptor, and determines which type of gate is involved. Figure 7-10 shows the format of a gate descriptor. A key feature of a gate is the re-direction it provides. All four gate types define a new address which transfers control when invoked. This destination address normally cannot be accessed by a program. Loading the selector to a call gate into SS, DS, or ES will cause a general protection fault with an error code identifying the invalid selector. Only the selector portion of an address is used to invoke a gate. The offset is ignored. All that a program need know about the desired function is the selector required to invoke the gate. The 80286 will automatically start the execution at the correct address stored within the gate. A further advantage of a gate is that it provides a fixed address for any program to invoke another program. The calling program's address remains unaltered even if the entry address of the destination program changes. Thus, gates provide a fixed set of entry points that allow a task to access Operating System functions such as simple subroutines, yet the task is prohibited from simply jumping into the middle of the Operating System. Call gates, as described in the next section, are used for control transfers within a task which must either be transparently redirected or which require an increase in privilege level. A call gate normally specifies a subroutine at a greater privilege level, and the called routine returns via a return instruction. Call gates also support delayed binding (resolution of target routine addresses at run-time rather than program-generation-time). Trap and interrupt gates handle interrupt operations that are to be serviced within the current task. Interrupt gates cause interrupts to be disabled; trap gates do not. Trap and interrupt gates both require a return via the interrupt return instruction. Task gates are used to control transfers between tasks and to make use of task state segments for task control and status information. Tasks are discussed in Chapter 8, interrupts in Chapter 9. In the 80286 protection model, each privilege level has its own stack. Therefore, a control transfer (call or return) that changes the privilege level causes a new stack to be invoked. Figure 7-10. Gate Descriptor Format 0 7 0 ‚ƒ +7 € INTEL RESERVED Must be set to 0 for compatibility with the 80386 € +6 Γ‘‘‘˜‘‘‘‘‘‘‘˜‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β +5 € P  DPL  0  0 1 0 1  UNUSED € +4 Γ‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β +3 € TSS SELECTOR € +2 Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β +1 € UNUSED € 0 „… 15 0 Gate Descriptor Fields ‚ΠΠƒ € Name  Value  Description € †ΟΟ‡ €  4  Call Gate. € € TYPE  5  Task Gate. € €  6  Interrupt Gate. € €  7  Trap Gate. € Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β € P  0  Descriptor Contents are not valid. € €  1  Descriptor Contents are valid. € Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β € DPL  0-3  Descriptor Privilege Level. € Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β €  0-31  Number of words to copy from caller's € € WORD COUNT   stack to called procedure's stack. Only € €   used with call gate. € Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β €  16-bit  Selector to the target code segment (Call, € € DESTINATION  selector  Interrupt or Trap Gate). € € SELECTOR   Selector to the target task state segment € €   (Task Gate). € Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β € DESTINATION  16-bit  Entry point within the target code segment. € € OFFSET  offset  € „€€… 7.5.1.1 Call Gates Call gate descriptors are used by call and jump instructions in the same manner as a code segment descriptor. The hardware automatically recognizes that the destination selector refers to a gate descriptor. Then, the operation of the instruction is expanded as determined by the contents of the call gate. A jump instruction can access a call gate only if the target code segment is at the same privilege level. A call instruction uses a call gate for the same or more privileged access. A call gate descriptor may reside in either the GDT or the LDT, but not in the IDT. Figure 7-10 gives the complete layout of a call gate descriptor. A call gate can be referred to by either the long JMP or CALL instructions. From the viewpoint of the program executing a JMP or CALL instruction, the fact that the destination was reached via a call gate and not directly from the destination address of the instruction is not apparent. The following is a description of the protection checks performed while transferring control (with the CALL instruction) through a call gate: Ž Verifying that access to the call gate is allowed. One of the protection features provided by call gates is the access checks made to determine if the call gate may be used (i.e., checking if the privilege level of the calling program is adequate). Ž Determining the destination address and whether a privilege transition is required. This feature makes privilege transitions transparent to the caller. Ž Performing the privilege transition, if required. Verifying access to a call gate is the same for any call gate and is independent of whether a JMP or CALL instruction was used. The rules of privilege used to determine whether a data segment may be accessed are employed to check if a call gate may be jumped-to or called. Thus, privileged subroutines can be hidden from untrusted programs by the absence of a call gate. When an inter-segment CALL or JMP instruction selects a call gate, the gate's privilege and presence will be checked. The gate's DPL (in the access byte) is checked against the EPL (MAX (task CPL, selector RPL)). If EPL > CPL, the program is less privileged than the gate and therefore it may not make a transition. In this case, a general protection fault occurs with an error code identifying the gate. Otherwise, the gate is accessible from the program executing the call, and the control transfer is allowed to continue. After the privilege checks, the descriptor presence is checked. If the present bit of the gate access rights byte is 0 (i.e., the target code segment is not present), not present fault occurs with an error code identifying the gate. The checks indicated in table 7-3 are applied to the contents of the call gate. Violating any of them causes the exception shown. The low order two bits of the error code are zero for these exceptions. Table 7-3. Call Gate Checks Type of Check Fault GP = General Protection, NP = Not-Present Exception Error Code Selector is not Null GP 0 Selector is within Descriptor Table Limit GP Selector id Descriptor is a Code Segment GP Code Segment id Code Segment is Present NP Code Segment id Nonconforming Code Segment DPL > CPL GP Code Segment id ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ NOTE The offset portion of the JMP or CALL destination address which refers to a call gate is always ignored. ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ 7.5.1.2 Intra-Level Transfers Via Call Gate The transfer is Intra-level if the destination code segment is at the same privilege level as CPL. Either the code segment is non-conforming with DPL = CPL, or it is conforming, with DPL Ύ CPL (see section 11.2 for this case). The 32-bit destination address in the gate is loaded into CS:IP. If the IP value is not within the limit of the code segment, a general protection fault occurs with an error code of 0. If a CALL instruction is used, the return address is saved in the normal manner. The only effect of the call gate is to place a different address into CS:IP than that specified in the destination address of the JMP or CALL instruction. This feature is useful for systems which require that a fixed address be provided to programs, even though the entry address for the routine may change due to different functions, software changes, or segment relocation. 7.5.1.3 Inter-Level Control Transfer Via Call Gates If the destination code segment of the call gate is at a different privilege level than the CPL, an inter-level transfer is being requested. However, if the destination code segment DPL > CPL, then a general protection fault occurs with an error code identifying the destination code segment. The gate guarantees that all transitions to a more privileged level will go to a valid entry point rather than possibly into the middle of a procedure (or worse, into the middle of an instruction). See figure 7-11. Calls to more privileged levels may be performed only through call gates. A JMP instruction can never cause a privilege change. Any attempt to use a call gate in this manner will cause a general protection fault with an error code identifying the gate. Returns to more privileged levels are also prohibited. Inter-level transitions due to interrupts use a different gate, as discussed in Chapter 9. The RPL field of the CS selector saved as part of the return address will always identify the caller's CPL. This information is necessary to correctly return to the caller's privilege level during the return instruction. Since the CALL instruction places the CS value on the more privileged stack, and JMP instructions cannot change privilege levels, it is not possible for a program to maliciously place an invalid return address on the caller's stack. Figure 7-11. Call Gate ‚ΠΠƒ € CALL OPCODE  OFFSET  SELECTOR € INSTRUCTION „€€Π…    ˆΠ Πˆ  € CODE   € DESCRIPTOR € SEG.   CALL GATE € TABLES € DESCR.   €  ‰Π€ €ΠΠ‰       ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•  OFFSET    ˆˆ  € € TARGET € ENTER € CODE € € SEGMENT  ‰‰  7.5.1.4 Stack Changes Caused By Call Gates To maintain system integrity, each privilege level has a separate stack. Furthermore, each task normally uses separate stacks from other tasks for each privilege level. These stacks assure sufficient stack space to process calls from less privileged levels. Without them, trusted programs may not work correctly, especially if the calling program does not provide sufficient space on the caller's stack. When a call gate is used to change privilege levels, a new stack is selected as determined by the new CPL. The new stack pointer value is loaded from the Task State Segment (TSS). The privilege level of the new stack data segment must equal the new CPL; if it does not, a task stack fault occurs with the saved machine state pointing at the CALL instruction and the error code identifying the invalid stack selector. The new stack should contain enough space to hold the old SS:SP, the return address, and all parameters and local variables required to process the call. The initial stack pointers for privilege levels 0-2 in the TSS are strictly read only values. They are never changed during the course of execution. The normal technique for passing parameters to a subroutine is to place them onto the stack. To make privilege transitions transparent to the called program, a call gate specifies that parameters are to be copied from the old stack to the new stack. The word count field in a call gate (see figure 7-10) specifies how many words (up to 31) are to be copied from the caller's stack to the new stack. If the word count is zero, no parameters are copied. Before copying the parameters, the new stack is checked to assure that it is large enough to hold the parameters; if it is not, a stack fault occurs with an error code of 0. After the parameters are copied, the return link is on the new stack (i.e., a pointer to the old stack is placed in the new stack). In particular, the return address is pointed at by SS:SP. The call and return example of figure 7-12 illustrate the stack contents after a successful inter-level call. The stack pointer of the caller is saved above the caller's return address as the first two words pushed onto the new stack. The caller's stack can only be saved for calls to procedures at privilege levels 2, 1, and 0. Since level 3 cannot be called by any procedure at any other privilege level, the level 3 stack will never contain links to other stacks. Procedures requiring more than the 31 words for parameters that may be called from another privilege level must use the saved SS:SP link to access all parameters beyond the last word copied. The call gate does not check the values of the words copied onto the new stack. The called procedure should check each parameter for validity. Section 11.3 discusses how the ARPL, VERR, VERW, LSL, and LAR instructions can be used to check pointer values. Figure 7-12. Stack Contents after an Inter-Level Call  ‚ƒ ‚ƒ  € € € OLD SS €   € € Γ‘‘‘‘‘‘‘‘‘‘Β  DIRECTION HIGHER € € € OLD SP €  OF STACK ADDRESSES € € Γ‘‘‘‘‘‘‘‘‘‘Β  GROWTH € € € PARM 3 €  € € Γ‘‘‘‘‘‘‘‘‘‘Β  € € € PARM 2 €  Γ‘‘‘‘‘‘‘‘‘‘Β Γ‘‘‘‘‘‘‘‘‘‘Β  € PARM 3 € € PARM 1 €  Γ‘‘‘‘‘‘‘‘‘‘Β Γ‘‘‘‘‘‘‘‘‘‘Β € PARM 2 € € OLD CS € OLD Γ‘‘‘‘‘‘‘‘‘‘Β NEW Γ‘‘‘‘‘‘‘‘‘‘Β SS:SP € PARM 1 € SS + SP € OLD IP € LOWER ”‘‘‘„… ”‘‘‘‘„… ADDRESSES  OLD STACK NEW STACK  (AT "OUTER" (AT "INNER"  PRIVILEGE PRIVILEGE LEVEL) LEVEL) 7.5.2 Inter-Level Returns An inter-segment return instruction can also change levels, but only toward programs of equal or lesser privilege (when code segment DPL is numerically greater or equal than the CPL). The RPL of the selector popped off the stack by the return instruction identifies the privilege level to resume execution of the calling program. When the RET instruction encounters a saved CS value whose RPL > CPL, an inter-level return occurs. Checks shown in table 7-4 are made during such a return. The old SS:SP value is then adjusted by the number of bytes indicated in the RET instruction and loaded into SS:SP. The new SP value is not checked for validity. If SP is invalid it is not recognized until the first stack operation. The SS:SP value of the returning program is not saved. (Note: this value normally is the same as that saved in the TSS.) The last step in the return is checking the contents of the DS and ES descriptor register. If DS or ES refer to segments whose DPL is greater than the new CPL (excluding conforming code segments), the segment registers are loaded with the null selector. Any subsequent memory reference that attempts to use the segment register containing the null selector will cause a general protection fault. This prevents less privileged code from accessing more privileged data previously accessed by the more privileged program. Table 7-4. Inter-Level Return Checks Type of Check Exception SF = Stack Fault, GP = General Protection Exception, NP = Not-Present Error Code SP is not within Segment Limit SF 0 SP + N + 7 is not in Segment Limit SF 0 RPL of Return CS is Greater than CPL GP Return CS id Return CS Selector is not null GP Return CS id Return CS segment is within Descriptor GP Return CS id Table Limit Return CS Descriptor is a Code Segment GP Return CS id Return CS Segment is Present NP Return CS id DPL of Return Non-Conforming Code GP Return CS id Segment = RPL of CS SS Selector at SP + N + 6 is not Null SF Return SS id SS Selector at SP + N + 6 is within SF Return SS id Descriptor Table Limit SS Descriptor is Writable Data Segment SF Return SS id SS Segment is Present SF Return SS id SS Segment DPL = RPL of CS SF Return SS id Chapter 8 Tasks and State Transitions ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ 8.1 Introduction An 80286 task is a single, sequential thread of execution. Each task can be isolated from all other tasks. There may be many tasks associated with an 80286 CPU, but only one task executes at any time. Switching the CPU from executing one task to executing another can occur as the result of either an interrupt or an inter-task CALL, JMP or IRET. A hardware-recognized data structure defines each task. The 80286 provides a high performance task switch operation with complete isolation between tasks. A full task-switch operation takes only 22 microseconds at 8 MHz (18 microseconds at 10 MHz). High-performance, interrupt-driven, multi-application systems that need the benefits of protection are feasible with the 80286. A performance advantage and system design advantage arise from the 80286 task switch: Ž Faster task switch: A task switch is a single instruction performed by microcode. Such a scheme is 2-3 times faster than an explicit task switch instruction. A fast task switch translates to a significant performance boost for heavily multi-tasked systems over conventional methods. Ž More reliable, flexible systems: The isolation between tasks and the high speed task switch allows interrupts to be handled by separate tasks rather than within the currently interrupted task. This isolation of interrupt handling code from normal programs prevents undesirable interactions between them. The interrupt system can become more flexible since adding an interrupt handler is as safe and easy as adding a new task. Ž Every task is protected from all others via the separation of address spaces described in Chapter 7, including allocation of unique stacks to each active privilege level in each task (unless explicit sharing is planned in advance). If the address spaces of two tasks include no shared data, one task cannot affect the data of another task. Code sharing is always safe since code segments may never be written into. 8.2 Task State Segments and Descriptors Tasks are defined by a special control segment called a Task State Segment (TSS). For each task, there must be an unique TSS. The definition of a task includes its address space and execution state. A task is invoked (made active) by inter-segment jump or call instructions whose destination address refers to a task state segment or a task gate. The Task State Segment (TSS) has a special descriptor. The Task Register within the CPU contains a selector to that descriptor. Each TSS selector value is unique, providing an unambiguous "identifier" for each task. Thus, an operating system can use the value of the TSS selector to uniquely identify the task. A TSS contains 22 words that define the contents of all registers and flags, the initial stacks for privilege levels 0-2, the LDT selector, and a link to the TSS of the previously executing task. Figure 8-1 shows the layout of the TSS. The TSS can not be written into like an ordinary data segment. Each TSS consists of two parts, a static portion and a dynamic portion. The static entries are never changed by the 80286, while the dynamic entries are changed by each task switch out of this task. The static portions of this segment are the task LDT selector and the initial SS:SP stack pointer addresses for levels 0-2. The modifiable or dynamic portion of the task state segment consists of all dynamically-variable and programmer-visible processor registers, including flags, segment registers, and the instruction pointer. It also includes the linkage word used to chain nested invocations of different tasks. The link word provides a history of which tasks invoked others. The link word is important for restarting an interrupted task when the interrupt has been serviced. Placing the back link in the TSS protects the identity of the interrupted task from changes by the interrupt task, since the TSS is not writable by the interrupt task. (In most systems only the operating system has sufficient privilege to create or use a writable data segment "alias" descriptor for the TSS.) The stack pointer entries in the TSS for privilege levels 0-2 are static (i.e., never written during a privilege or task switch). They define the stack to use upon entry to that privilege level. These stack entries are initialized by the operating system when the task is created. If a privilege level is never used, no stack need be allocated for it. When entering a more privileged level, the caller's stack pointer is saved on the stack of the new privilege level, not in the TSS. Leaving the privilege level requires popping the caller's return address and stack pointer off the current stack. The stack pointer at that time will be the same as the initial value loaded from the TSS upon entry to the privilege level. There is only one stack active at any time, the one defined by the SS and SP registers. The only other stacks that may be non-empty are those at outer (less privileged) levels that called the current level. Stacks for inner levels must be empty, since outward (to numerically larger privilege levels) calls from inner levels are not allowed. The location of the stack pointer for an outer privilege level will always be found at the start of the stack of the inner privilege level called by that level. That stack may be the initial stack for this privilege level or an outer level. Look at the start of the stack for this privilege level. The TSS contains the starting stack address for levels 0-2. If the RPL of the saved SS selector is the privilege level required, then the stack pointer has been found. Otherwise, go to the beginning of the stack defined by that value and look at the saved SS:SP value there. Figure 8-1. Task State Segment and TSS Registers   ’‘Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β  € INTEL RESERVED €  Γ‘˜‘‘‘˜‘˜‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘€‘“ TSS  €P ‚Πƒ € P  DESCRIPTION € †Ο‡ € 1  BASE AND LIMIT FIELDS ARE VALID € Γ‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β € 0  SEGMENT IS NOT PRESENT IN MEMORY. € €  BASE AND LIMIT ARE NOT DEFINED € „€… DPL0 TYPE ‚Πƒ €TYPEDESCRIPTION € †Ο‡ € 1 AN AVAILABLE TASK STATE SEGMENT MAY BE USED € € AS THE DESTINATION OF A TASK SWITCH OPERATION.€ Γ‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β € A BUSY TASK STATE SEGMENT CANNOT BE USED AS € € THE DESTINATION OF A TASK SWITCH. € „€…  BASE 23-16 €  DESCRIPTOR ‘— Γ‘™‘™‘™‘™‘™‘™‘™‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β    € BASE 15-0 € – “   Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β   € LIMIT 15-0 €    ”‘Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β‘• CPU ’‘ ‘‘€‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘Ξ ‘‘• ‚Οƒ Έ Έ € TASK REGISTER €  €15 0€ BYTE € ‚ƒ  € ’‘Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β OFFSET € € Γ‘‘ ‘• €   € TASK LDT SELECTOR € 42 Never altered (static) after initialization by O.S. The values as initialized for this task are always valid SS:SP values to use upon entry to that privilege level (0, 1, or 2) from a level of lesser privilege. € „… €  Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β ‘“ € 15 0 €   € DS SELECTOR € 40  € ’‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘“ €  Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β  € PROGRAM INVISIBLE €   € SS SELECTOR € 38  €  15 0  €  Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β  € ‚ƒ “ €   € CS SELECTOR € 36  €  € LIMIT Γ‘“   €  Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β  € ‚‰‘‘‘‘‘‘‘Β  ‘ Ξ‘•  € ES SELECTOR € 34  €  € BASE €    €  Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β  € „Ё…  • €  € DI € 32  €   0   €  Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β  € ”‘‘‘‘ ‘‘ ‘‘ ‘‘ š‘ ‘• €  € SI € 30  „ΟΟ…  Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β     € BP € 28 CURRENT    Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β –TASK    € SP € 26 STATE Changed during task switch.    Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β     € BX € 24     Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β    TASK  € DX € 22   ” STATE — Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β   SEGMENT  € CX € 20    Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β    € AX € 18    Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β    € FLAG WORD € 16    Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β    € IP (ENTRY POINT) € 14    Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β Α   € SS FOR CPL 2 € 12    Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β    € SP FOR CPL 2 € 10    Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β INITIAL   € SS FOR CPL 1 € 8 STACKS   Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β –FOR   € SP FOR CPL 1 € 6 CPL   Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β 0,1,2 Never altered (static) after initialization by O.S. The values as initialized for this task are always valid SS:SP values to use upon entry to that privilege level (0, 1, or 2) from a level of lesser privilege.   € SS FOR CPL 0 € 4    Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β    € SP FOR CPL 0 € 2    Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β ‘•   € BACK LINK SELECTOR TO TSS € 0 ‘‘‘‘‘ ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘”‘Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β € €   8.2.1 Task State Segment Descriptors A special descriptor is used for task state segments. This descriptor must be accessible at all times; therefore, it can appear only in the GDT. The access byte distinguishes TSS descriptors from data or code segment descriptors. When bits 0 through 4 of the access byte are 00001 or 00011, the descriptor is for a TSS. The complete layout of a task state segment descriptor is shown in figure 8-2. Like a data segment, the descriptor contains a base address and limit field. The limit must be at least 002BH (43) to contain the minimum amount of information required for a TSS. An invalid task exception will occur if an attempt is made to switch to a task whose TSS descriptor limit is less than 43. The error code will identify the bad TSS. The P-bit (Present) flag indicates whether this descriptor contains currently valid information: 1 means yes, 0 no. A task switch that attempts to reference a not-present TSS causes a not-present exception code identifying the task state segment selector. The descriptor privilege level (DPL) controls use of the TSS by JMP or CALL instructions. By the same reasoning as that for call gates, DPL can prevent a program from calling the TSS and thereby cause a task switch. Section 8.3 discusses privilege considerations during a task switch in greater detail. Bit 4 is always 0 since TSS is a control segment descriptor. Control segments cannot be accessed by SS, DS, or ES. Any attempt to load those segment registers with a selector that refers to a control segment causes general protection trap. This rule prevents the program from improperly changing the contents of a control segment. TSS descriptors can have two states: idle and busy. Bit 1 of the access byte distinguishes them. The distinction is necessary since tasks are not re-entrant; a busy TSS may not be invoked. Figure 8-2. TSS Descriptor 7 0 7 0 ‚Πƒ +7€ INTEL RESERVED Must be set to 0 for compatibility with 80836 €+6 Γ‘‘‘˜‘‘‘‘‘‘‘˜‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β +5€ P  DPL  0  0 0 B  1  TSB BASE 23-16 €+4 Γ‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β +3€ TSS BASE 15-0 €+2 €‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘€ +1€ TSS LIMIT € 0 „… 15 0 B=1 MEANS TASK IS BUSY AND NOT AVAILABLE 8.3 Task Switching A task switch may occur in one of four ways: 1. The destination selector of a long JMP or CALL instruction refers to a TSS descriptor. The offset portion of the destination address is ignored. 2. An IRET instruction is executed when the NT bit in the flag word = 1. The new task TSS selector is in the back link field of the current TSS. 3. The destination selector of a long JMP or CALL instruction refers to a task gate. The offset portion of the destination address is ignored. The new task TSS selector is in the gate. (See section 8.5 for more information on task gates.) 4. An interrupt occurs. This interrupt's vector refers to a task gate in the interrupt descriptor table. The new task TSS selector is in the gate. See section 9.4 for more information on interrupt tasks. No new instructions are required for a task switch operation. The standard 8086 JMP, CALL, IRET, or interrupt operations perform this function. The distinction between the standard instruction and a task switch is made either by the type of descriptor referenced (for CALL, JMP, or INT) or by the NT bit (for IRET) in flag word. Using the CALL or INT instruction to switch tasks implies a return is expected from the called task. The JMP and IRET instructions imply no return is expected from the new task. When NT=1, the IRET instruction causes a return to the task that called the current one via CALL or INT instruction. Access to TSS and task gate descriptors is restricted by the rules of privilege level. The data access rules are used, thereby allowing task switches to be restricted to programs of sufficient privilege. Address space separation does not apply to TSS descriptors since they must be in the GDT. The access rules for interrupts are discussed in section 9.4. The task switch operation consists of the following eight steps: 1. Validate the requested task switch. For a task switch requested via a JMP, CALL, or an INT instruction, check that the current task is allowed to switch to the requested task. The DPL of the gate or the TSS descriptor for the requested task must be greater than or equal to both the CPL and the RPL of the requesting task. If it is not, the General Protection fault (#13) will occur with an error code identifying the descriptor (i.e., the gate selector if the task switch is requested via a task gate, or the selector for the TSS if the task switch is requested via a TSS descriptor). These checks are not performed if a task switch occurs due to an IRET instruction. 2. Check that the new TSS is present and that the new task is available (i.e. not Busy). A Not Present exception (#11) is signaled if the new TSS descriptor is marked 'Not Present' (P = 0). The General Protection exception (#13) is raised if the new TSS is marked 'Busy'. The task switch operation actually begins now and a detailed verification of the new TSS is carried out. Conditions which may disqualify the new TSS are listed in table 8-1 along with the exception raised and the error code pushed on the stack for each case. These tests are performed at different points during the course of the following remaining steps of the task switch operation. 3. Mark the new task to be BUSY by setting the 'BUSY' bit in the new TSS descriptor to 1. 4. Save the dynamic portion of the old TSS and load TR with the selector, base and limit for the new TSS. Set all CPU registers to corresponding values from the new TSS except DS, ES, CS, SS, and LDT. 5. If nesting tasks, set the Nested Task (NT) flag in the new TSS to 1. Also set the Task Switched flag (TS) of the CPU flag register to 1. 6. Validate the LDT selector and the LDT descriptor of the new TSS. Load the LDT cache (LDTR) with the LDT descriptor. 7. Validate the SS, CS, DS, and ES fields of the new TSS and load these values in their respective caches (i.e., SS, CS, DS, and ES registers). 8. Validate the IP field of the new TSS and then start executing the new task from CS:IP. A more detailed explanation of steps 3-5 is given in Appendix B (80286 Instruction Set) under a pseudo procedure 'SWITCH_TASKS'. Notice how the exceptions described in table 8-1 may actually occur during a task switch. Similarly the exceptions that may occur during steps 1-2, and step 8 are explained in greater detail in the pseudo code description of the 286 instructions CALL, JMP, INT, and IRET in Appendix B. This information can be very helpful when debugging any protected mode code. Note that the state of the outgoing task is always saved. If execution of that task is resumed, it will start after the instruction that caused the task switch. The values of the registers will be the same as that when the task stopped running. Any task switch sets the Task Switched (TS) bit in the Machine Status Word (MSW). This flag is used when processor extensions such as the 80287 Numeric Processor Extension are present. The TS bit signals that the context of the processor extension may not belong to the current 80286 task. Chapter 11 discusses the TS bit and processor extensions in more detail. Validity tests on a selector ensure that the selector is in the proper table (i.e., the LDT selector refers to GDT), lies within the bounds of the table, and refers to the proper type of descriptor (i.e., the LDT selector refers to the LDT descriptor). Note that between steps 3 and 4 in table 8-1, all the registers of the new task are loaded. Several protection rule violations may exist in the new segment register contents. If an exception occurs in the context of the new task due to checks performed on the newly loaded descriptors, the DS and ES segments may not be accessible even though the segment registers contain non-zero values. These selector values must be saved for later reuse. When the exception handler reloads these segment registers, another protection exception may occur unless the exception handler pre-examines them and fixes any potential problems. A task switch allows flexibility in the privilege level of the outgoing and incoming tasks. The privilege level at which execution resumes in the incoming task is not restricted by the privilege level of the outgoing task. This is reasonable, since both tasks are isolated from each other with separate address spaces and machine states. The privilege rules prevent improper access to a TSS. The only interaction between the tasks is to the extent that one started the other and the incoming task may restart the outgoing task by executing an IRET instruction. Table 8-1. Checks Made during a Task Switch Test Exception NP = Not-Present Exception GP = General Protection Fault SF = Stack Fault Error Code 1 Incoming TSS descriptor NP Incoming TSS selector is present 2 Incoming TSS is idle G Incoming TSS selector 3 Limit of incoming TSS Invalid TSS Incoming TSS selector greater than 43 4 LDT selector of incoming Invalid TSS LDT selector TSS is valid 5 LDT of incoming TSS Invalid TSS LDT selector is present 6 CS selector is valid Invalid TSS Code segment selector 7 Code segment is present NP Code segment selector 8 Code segment DPL matches Invalid TSS Code segment selector CS RPL 9 Stack segment is valid SF Stack segment selector 10 Stack segment is writable GP Stack segment selector data segment 11 Stack segment is present SF Stack segment selector 12 Stack segment DPL = CPL SF Stack segment selector 13 DS/ES selectors are valid GP Segment selector 14 DS/ES segments are readable GP Segment selector 15 DS/ES segments are present NP Segment selector 16 DS/ES segment DPL  CPL if GP Segment not conform 8.4 Task Linking The TSS has a field called "back link" which contains the selector of the TSS of a task that should be restarted when the current task completes. The back link field of an interrupt-initiated task is automatically written with the TSS selector of the interrupted task. A task switch initiated by a CALL instruction also points the back link at the outgoing task's TSS. Such task nesting is indicated to programs via the Nested Task (NT) bit in the flag word of the incoming task. Task nesting is necessary for interrupt functions to be processed as separate tasks. The interrupt function is thereby isolated from all other tasks in the system. To restart the interrupted task, the interrupt handler executes an IRET instruction much in the same manner as an 8086 interrupt handler. The IRET instruction will then cause a task switch to the interrupted task. Completion of a task occurs when the IRET instruction is executed with the NT bit in the flag word set. The NT bit is automatically set/reset by task switch operations as appropriate. Executing an IRET instruction with NT cleared causes the normal 8086 interrupt return function to be performed, and no task switch occurs. Executing IRET with NT set causes a task switch to the task defined by the back link field of the current TSS. The selector value is fetched and verified as pointing to a valid, accessible TSS. The normal task switch operation described in section 8.3 then occurs. After the task switch is complete, the outgoing task is now idle and considered ready to process another interrupt. Table 8-2 shows how the busy bit, NT bit, and link word of the incoming and outgoing task are affected by task switch operations caused by JMP, CALL, or IRET instructions. Violation of any of the busy bit requirements shown in table 8-2 causes a general protection fault with the saved machine state appearing as if the instruction had not executed. The error code identifies the selector of the TSS with the busy bit. A bus lock is applied during the testing and setting of the TSS descriptor busy bit to ensure that two processors do not invoke the same task at the same time. See also section 11.4 for other multi-processor considerations. The linking order of tasks may need to be changed to restart an interrupted task before the task that interrupted it completes. To remove a task from the list, trusted operating system software must change the backlink field in the TSS of the interrupting task first, then clear the busy bit in the TSS descriptor of the task removed from the list. When trusted software deletes the link from one task to another, it should place a value in the backlink field, which will pass control to that trusted software when the task attempts to resume execution of another task via IRET. Table 8-2. Effect of a Task Switch on BUSY and NT Bits and the Link Word JMP CALL/INT IRET Affected Field Instruction Instruction Instruction Effect Effect Effect Busy bit of incoming Set, must be Set, must be 0 Unchanged, task TSS descriptor 0 before before must be set Busy bit of outgoing Cleared Unchanged (will Cleared tasl TSS descriptor already be 1) NT bit in incoming task Cleared Set Unchanged flag word NT bit in outgoing task Unchanged Unchanged Cleared flag word Back link in incoming Unchanged Set to outgoing Unchanged task TSS task TSS selector Back link of outgoing Unchanged Unchanged Unchanged tasl TSS 8.5 Task Gates A task may be invoked by several different events. Task gates are provided to support this need. Task gates are used in the same way as call and interrupt gates. The ultimate effect of jumping to or calling a task gate is the same as jumping to or calling directly to the TSS in the task gate. Figure 8-3 depicts the layout of a task gate. A task gate is identified by the access byte field in bits 0 through 4 being 00101. The gate provides an extra level of indirection between the destination address and the TSS selector value. The offset portion of the JMP or CALL destination address is ignored. Gate use provides flexibility in controlling access to tasks. Task gates can appear in the GDT, IDT, or LDT. The TSS descriptors for all tasks must be kept in the GDT. They are normally placed at level 0 to prevent any task from improperly invoking another task. Task gates placed in the LDT allow private access to selected tasks with full privilege control. The data segment access rules apply to accessing a task gate via JMP, CALL, or INT instructions. The effective privilege level (EPL) of the destination selector must be numerically less than or equal to the DPL of the task gate descriptor. Any violation of this requirement causes a general protection fault with an error code identifying the task gate involved. Once access to the task gate has been verified, the TSS selector from the gate is read. The RPL of the TSS selector is ignored. From this point, all the checks and actions performed for a JMP or CALL to a TSS after access has been verified are performed (see section 8.4). Figure 8-4 illustrates an example of a task switch through a task gate. Figure 8-3. Task Gate Descriptor 7 0 7 0 ‚ƒ +7€ INTEL RESERVED Must be set to 0 for compatibility with 80386 €+6 Γ‘‘‘˜‘‘‘‘‘‘‘˜‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β +5€ P  DPL  O  O 1 O  1  UNUSED €+4 Γ‘‘‘™‘‘‘‘‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β +3€ TSS SELECTOR €+2 €‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘€ +1€ UNUSED € 0 „… 15 0 Figure 8-4. Task Switch Through a Task Gate TASK A TASK B ‚ƒ ‚ƒ ‚ƒ € € € € € € € € € € Έ Έ € € Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β € € € €TASK’€LDT DESCRIPTORΓ‘‘‘„… € € B—Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β‘“ LDT ‚Πƒ Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β ”€TSS DESCRIPTORΓ‘“ € SELECTOR€€ TASK GATE €‘‘‘‘Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β  ‚ƒ „€… Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β € € ”‘Β LDT SELECTOR € Έ Έ € €  Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β € € € €  € € „…‘“ € €  € € LDT  € €  € € ”‘‘Ξ‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β  € € ‚ƒ‘‘‘‘€LDT DESCRIPTOR€“ € € € LDT SELECTOR € Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘”‘Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β €TSS DESCRIPTOR€™“ € BACK LINK € € € ’‘‘Ξ‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β‘‘‘„… € €  € €  TSS € €  € € ”TASK „…‘• „… A TSS GDT Chapter 9 Interrupts and Exceptions ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Interrupts and exceptions are special cases of control transfer within a program. An interrupt occurs as a result of an event that is independent of the currently executing program, while exceptions are a direct result of the program currently being executed. Interrupts may be external or internal. External interrupts are generated by either the INTR or NMI input pins. Internal interrupts are caused by the INT instruction. Exceptions occur when an instruction cannot be completed normally. Although their causes differ, interrupts and exceptions use the same control transfer techniques and privilege rules; therefore, in the following discussions the term interrupt will also apply to exceptions. The program used to service an interrupt may execute in the context of the task that caused the interrupt (i.e., used the same TSS, LDT, stacks, etc.) or may be a separate task. The choice depends on the function to be performed and the level of isolation required. 9.1 Interrupt Descriptor Table Many different events may cause an interrupt. To allow the reason for an interrupt to be easily identified, each interrupt source is given a number called the interrupt vector. Up to 256 different interrupt vectors (numbers) are possible. See figure 9-1. A table is used to define the handler for each interrupt vector. The Interrupt Descriptor Table (IDT) defines the interrupt handlers for up to 256 different interrupts. The IDT is in physical memory, pointed to by the contents of the on-chip IDT register that contains a 24-bit base and a 16-bit limit. The IDTR is normally loaded with the LIDT instruction by code that executes at privilege level 0 during system initialization. The IDT may be located anywhere in the physical address space of the 80286. Each IDT entry is a 4-word gate descriptor that contains a pointer to the handler. The three types of gates permitted in the IDT are interrupt gates, trap gates (discussed in section 9.3), and task gates (discussed in section 9.5). Interrupt and task gates process interrupts in the same task, while task gates cause a task switch. Any other descriptor type in the IDT will cause an exception if it is referenced by an interrupt. The IDT need not contain all 256 entries. A 16-bit limit register allows less than the full number of entries. Unused entries may be signaled by placing a zero in the access rights byte. If an attempt is made to access an entry outside the table limit, or if the wrong descriptor type is found, a general protection fault occurs with an error code pushed on the stack identifying the invalid interrupt vector (see figure 9-2). Exception error codes that refer to an IDT entry can be identified by bit 1 of the error code that will be set. Bit 0 of the error code is 1 if the interrupt was caused by an event external to the program (i.e., an external interrupt, a single step, a processor extension error, or a processor extension not present). Interrupts 0-31 are reserved for use by Intel. Some of the interrupts are used for instruction exceptions. The IDT limit must be at least 255 (32 * 8 - 1) to accommodate the minimum number of interrupts. The remaining 224 interrupts are available to the user. Figure 9-1. Interrupt Descriptor Table Definition MEMORY   € € THE IDT MAY ’‘†‡‘“ CONTAIN  € GATE FOR €  INTERRUPT  € INTERRUPT #n €  GATES, TRAPS  †‡  OR TASK GATES  € GATE FOR €  ONLY.  €INTERRUPT #n-1 €   †‡   € ¨ €  INTERRUPT ’‘‘— € ¨ € –‘ DESCRIPTOR   € ¨ €  TABLE (IDT) CPU   †‡  ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“   € GATE FOR €   15 0    € INTERRUPT #1 €   ‚ƒ    †‡   €IDT LIMITΓ‘‘š‘‘•  € GATE FOR €  IDTR  ‚π‘‘‘‘‘‘‘‘‘Β  ”‘€ INTERRUPT #0 €   € IDT BASE Γ‘‘š‘‘‘‘‘‘‘†‡‘•  „…  € €  23 0    ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘• Figure 9-2. IDT Selector Error Code 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 ‚ΠΠΠΠƒ €     E € € 0 0 0 0 0  IDT VECTOR  0  1  X € €     T € „€€€€Π… ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•  1 An even external to the program caused the exception (i.e. external interrupt, single step, processor extension error) 0 An exception occurred while processing an instruction at CS:IP saved on stack 9.2 Hardware Initiated Interrupts Hardware-initiated interrupts are caused by some external event that activates either the INTR or NMI input pins of the processor. Events that use the INTR input are classified as maskable interrupts. Events that use the NMI input are classified as non-maskable interrupts. All 224 user-defined interrupt sources share the INTR input, but each has the ability to use a separate interrupt handler. An 8-bit vector supplied by the interrupt controller identifies which interrupt is being signaled. To read the interrupt id, the processor performs the interrupt acknowledge bus sequence. Maskable interrupts (from the INTR input) can be inhibited by software by setting the interrupt flag bit (IF) to 0 in the flag word. The IF bit does not inhibit exceptions or interrupts caused by the INT instruction. The IF bit also does not inhibit processor extension interrupts. The type of gate placed into the IDT for the interrupt vector will control whether other maskable interrupts remain enabled or not during the servicing of that interrupt. The flag word that was saved on the stack reflects the maskable interrupt enable status of the processor prior to the interrupt. The procedure servicing a maskable interrupt can also prevent further maskable interrupts during its work by resetting the IF flag. Non-maskable interrupts are caused by the NMI input. They have a higher priority than the maskable interrupts (meaning that in case of simultaneous requests, the non-maskable interrupt will be serviced first). A non-maskable interrupt has a fixed vector (#2) and therefore does not require an interrupt acknowledge sequence on the bus. A typical use of an NMI is to invoke a procedure to handle a power failure or some other critical hardware exception. A procedure servicing an NMI will not be further interrupted by other non-maskable interrupt requests until an IRET instruction is executed. A further NMI request is remembered by the hardware and will be serviced after the first IRET instruction. Only one NMI request can be remembered. To prevent a maskable interrupt from interrupting the NMI interrupt handler, the IF flag should be cleared either by using an interrupt gate in the IDT or by setting IF = 0 in the flag word of the task involved. 9.3 Software Initiated Interrupts Software initiated interrupts occur explicitly as interrupt instructions or may arise as the result of an exceptional condition that prevents the continuation of program execution. Software interrupts are not maskable. Two interrupt instructions exist which explicitly cause an interrupt: INT n and INT 3. The first allows specification of any interrupt vector; the second implies interrupt vector 3 (Breakpoint). Other instructions like INTO, BOUND, DIV, and IDIV may cause an interrupt, depending on the overflow flag or values of the operands. These instructions have predefined vectors associated with them in the first 32 interrupts reserved by Intel. A whole class of interrupts called exceptions are intended to detect faults or programming errors (in the use of operands or privilege levels). Exceptions cannot be masked. They also have fixed vectors within the first 32 interrupts. Many of these exceptions pass an error code on the stack, which is not the case with the other interrupt types discussed in section 9.2. Section 9.5 discusses these error codes as well as the priority among interrupts that can occur simultaneously. 9.4 Interrupt Gates and Trap Gates Interrupt gates and trap gates are special types of descriptors that may only appear in the interrupt descriptor table. The difference between a trap and an interrupt gate is whether the interrupt enable flag is to be cleared or not. An interrupt gate specifies a procedure that enters with interrupts disabled (i.e., with the interrupt enable flag cleared); entry via a trap gate leaves the interrupt enable status unchanged. The NT flag is always cleared (after the old NT state is saved on the stack) when an interrupt uses these gates. Interrupts that have either gate in the associated IDT entry will be processed in the current task. Interrupts and trap gates have the same structure as the call gates discussed in section 7.5.1. The selector and entry point for a code segment to handle the interrupt or exception is contained in the gate. See figure 9-3. The access byte contains the Present bit, the descriptor privilege level, and the type identifier. Bits 0-4 of the access byte have a value of 00110 for interrupt gates, 00111 for trap gates. Byte 5 of the descriptor is not used by either of these gates; it is used only by the call gate, which uses it as the parameter word-count. Trap and interrupt gates allow a privilege level transition to occur when passing control to a non-conforming code segment. Like a call gate, the DPL of the target code segment selected determines the new CPL. The DPL of the new non-conforming code segment must be numerically less than or equal to CPL. No privilege transition occurs if the new code segment is conforming. If the DPL of the conforming code segment is greater than the CPL, a general protection exception will occur. As with all descriptors, these gates in the IDT carry a privilege level. The DPL controls access to interrupts with the INT n and INT 3 instructions. For access, the CPL of the program must be less than or equal to the gate DPL. If the CPL is not, a general protection exception will result with an error code identifying the selected IDT gate. For exceptions and external interrupts, the CPL of the program is ignored while accessing the IDT. Interrupts using a trap or an interrupt gate are handled in the same manner as an 8086 interrupt. The flags and return address of the interrupted program are saved on the stack of the interrupt handler. To return to the interrupted program, the interrupt handler executes an IRET instruction. If an increase in privilege is required for handling the interrupt, a new stack will be loaded from the TSS. The stack pointer of the old privilege level will also be saved on the new stack in the same manner as a call gate. Figure 9-4 shows the stack contents after an exception with an error code (with and without a privilege level change). If an interrupt or trap gate is used to handle an exception that passes an error code, the error code will be pushed onto the new stack after the return address (as shown in figure 9-4). If a task gate is used, the error code is pushed onto the stack of the new task. The return address is saved in the old TSS. If an interrupt gate is used to handle an interrupt, it is assumed that the selected code segment has sufficient privilege to re-enable interrupts. The IRET instruction will not re-enable interrupts if CPL is numerically greater than IOPL. Table 9-1 shows the checks performed during an interrupt operation that uses an interrupt or trap gate. EXT equals 1 when an event external to the program is involved; 0 otherwise. External events are maskable or non-maskable interrupts, single step interrupt, processor extension segment overrun interrupt, numeric processor not-present exception or numeric processor error. The EXT bit signals that the interrupt or exception is not related to the instruction at CS:IP. Each error code has bit 1 set to indicate an IDT entry is involved. When the interrupt has been serviced, the service routine returns control via an IRET instruction to the routine that was interrupted. If an error code was passed, the exception handler must remove the error code from the stack before executing IRET. The NT flag is cleared when an interrupt occurs which uses an interrupt or trap gate. Executing IRET with NT=0 causes the normal interrupt return function. Executing IRET with NT=1 causes a task switch (see section 8.4 for more details). Like the RET instruction, IRET is restricted to return to a level of equal or lesser privilege unless a task switch occurs. The IRET instruction works like the inter-segment RET instruction except that the flag word is popped and no stack pointer update for parameters is performed since no parameters are on the stack. See section 7.5.2 for information on inter-level returns. To distinguish an inter-level IRET, the new CPL (which is the RPL of the return address CS selector) is compared with the current CPL. If they are the same, the IP and flags are popped and execution continues. An inter-level return via IRET has all the same checks as shown in table 7-4. The only difference is the extra word on the stack for the old flag word. Interrupt gates are typically associated with high-priority hardware interrupts for automatically disabling interrupts upon their invocation. Trap gates are typically software-invoked since they do not disable the maskable hardware interrupts. However, low-priority interrupts (e.g., a timer) are often invoked via a trap gate to allow other devices of higher priority to interrupt the handler of that lower priority interrupt. Table 9-2 illustrates how the interrupt enable flag and interrupt type interact with the type of gate used. Table 9-1. Trap and Interrupt Gate Checks Check Exception GP = General Protection Exception NP = Not Present Exception SF = Stack Fault Error Code Interrupt vector GP IDT entry * 8 + 2 + EXT is in IDT limit Trap, Interrupt, or GP IDT entry * 8 + 2 + EXT Task Gate in IDT Entry If INT instruction, GP IDT entry * 8 + 2 + EXT gate DPL  CPL P bit of gate is set NP IDT entry * 8 + 2 + EXT Code segment selector GP CS selector * 8 + EXT is in descriptor table limit CS selector refers GP CS selector * 8 + EXT to a code segment If code segment is GP CS selector * 8 + EXT non-conforming, Code Segment DPL Ύ CPL If code segment is TS SS selector * 8 + EXT non-conforming, and DPL < CPL and if SS selector in TSS is in descriptor table limit If code segment is TS SS selector * 8 + EXT non-conforming, and DPL < CPL and if SS is a writable data segment If code segment is TS Stack segment selector + EXT non-conforming, and DPL < CPL and code segment DPL = stack segment DPL If code segment is SF Stack segment selector + EXT non-conforming, and DPL < CPL and if SS is present If code segment is SF SS selector + EXT non-conforming, and DPL < CPL and if there is enough space for 5 words on the stack (or 6 if error code is required) If code segment is GP Code segment selector + EXT conforming, then DPL ΎCPL If code segment NP Code segment selector + EXT is not present If IP is not within GP 0 + EXT the limit of code segment Table 9-2. Interrupt and Gate Interactions Type of Type of Further Further Further Further software Interrupt Gate NMIs? INTRs? Exceptions? Interrupts? NMI Trap No Yes Yes Yes NMI Interrupt No No Yes Yes INTR Trap Yes Yes Yes Yes INTR Interrupt Yes No Yes Yes Software Trap Yes Yes Yes Yes Software Interrupt Yes No Yes Yes Exception Trap Yes Yes Yes Yes Exception Interrupt Yes No Yes Yes Figure 9-3. Trap/Interrupt Gate Descriptors ‚Πƒ +7€ INTEL RESERVED Must be set to 0 for compatibility with IAPX 386 €+6 Γ‘‘‘˜‘‘‘‘‘‘‘˜‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β +5€ P  DP2  0  0 1 1 T  UNUSED €+4 Γ‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β +3€ INTERRUPT CODE SEGMENT SELECTOR €+2 €‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘€ +1€ INTERRUPT CODE OFFSET € 0 „… T = 1 FOR TRAP GATE T = 0 FOR INTERRUPT GATE Figure 9-4. Stack Layout after an Exception with an Error Code OLD SP‘‘‘‘‘‚ƒ NO PRIVILEGE TRANSITION € OLD FLAGS € Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β € OLD CS € Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β € OLD IP € Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β € ERROR CODE € SP‘‘‘‘‘Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β € € € € Έ Έ € € SS‘‘‘‘‘„… SP FROM TSS‘ ‘ ‘‚ƒ WITH PRIVILEGE TRANSITION € OLD SS € Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β € OLD SP € Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β € OLD FLAGS € Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β € OLD CS € Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β € OLD IP € Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β € ERROR CODE € SP‘‘‘‘‘Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β € € € € Έ Έ € € SP FROM TSS‘‘‘‘‘„… STACK SEGMENT 9.5 Task Gates and Interrupt Tasks The 80286 allows interrupts to directly cause a task switch. When an interrupt vector selects an entry in the IDT which is a task gate, a task switch occurs. The format of a task gate is described in section 8.5. If a task gate is used to handle an exception that passes an error code, the error code will be pushed onto the new task's stack. A task gate offers two advantages over interrupt gates: 1. It automatically saves all of the processor registers as part of the task-switch operation, whereas an interrupt gate saves only the flag register and CS:IP. 2. The new task is completely isolated from the task that was interrupted. Address spaces are isolated and the interrupt-handling task is unaffected by the privilege level of the interrupted task. An interrupt task switch works like any other task switch once the TSS selector is fetched from the task gate. Like a trap or an interrupt gate, privilege and presence rules are applied to accessing a task gate during an interrupt. Interrupts that cause a task switch set the NT bit in the flags of the new task. The TSS selector of the interrupted task is saved in the back link field of the new TSS. The interrupting task executes IRET to perform a task switch to return to the interrupted task because NT was previously set. The interrupt task state is saved in its TSS before returning control to the task that was interrupted; NT is restored to its original value in the interrupted task. Since the interrupt handler state after executing IRET is saved, a re-entry of the interrupt service task will result in the execution of the instruction that follows IRET. Therefore, when the next interrupt occurs, the machine state will be the same as that when the IRET instruction was executed. Note that an interrupt task resumes execution each time it is re-invoked, whereas an interrupt procedure starts executing at the beginning of the procedure each time. The interrupted task restarts execution at the point of interruption because interrupts occur before the execution of an instruction. When an interrupt task is used, the task must be concerned with avoiding further interrupts while it is operating. A general protection exception will occur if a task gate referring to a busy TSS is used while processing an interrupt. If subsequent interrupts can occur while the task is executing, the IF bit in the flag word (saved in the TSS) must be zero. 9.5.1 Scheduling Considerations A software-scheduled operating system must be designed to handle the fact that interrupts can come along in the middle of scheduled tasks and cause a task switch to other tasks. The interrupt-scheduled tasks may call the operating system and eventually the scheduler, which needs to recognize that the task that just called it is not the one the operating system last scheduled. If the Task Register (TR) does not contain the TSS selector of the last scheduled task, an interrupt initiated task switch has occurred. More than one task may have been interrupt-scheduled since the scheduler last ran. The scheduler must find via the backlink fields in each TSS all tasks that have been interrupted. The scheduler can clear those links and reset the busy bit in the TSS descriptors, putting them back in the scheduling queue for a new analysis of execution priorities. Unless the interrupted tasks are placed back in the scheduling queue, they would have to await a later restart via the task that interrupted them. To locate tasks that have been interrupt-scheduled, the scheduler looks into the current task's TSS backlink (word one of the TSS), which points at the interrupted task. If that task was not the last task scheduled, then it's backlink field in the TSS also points to an interrupted task. The backlink field of each interrupt-scheduled task should be set by the scheduler to point to a scheduling task that will reschedule the highest priority task when the interrupt-scheduled task executes IRET. 9.5.2 Deciding Between Task, Trap, and Interrupt Gates Interrupts and exceptions can be handled with either a trap/interrupt gate or a task gate. The advantages of a task gate are all the registers are saved and a new set is loaded with full isolation between the interrupted task and the interrupt handler. The advantages of a trap/interrupt gate are faster response to an interrupt for simple operations and easy access to pointers in the context of the interrupted task. All interrupt handlers use IRET to resume the interrupted program. Trap/interrupt gates require that the interrupt handler be able to execute at the same or greater privilege level than the interrupted program. If any program executing at level 0 can be interrupted through a trap/task gate, the interrupt handler must also execute at level 0 to avoid general protection exception. All code, data, and stack segment descriptors must be in the GDT to allow access from any task. But, placing all system interrupt handlers at privilege level 0 may be in consistent with maintaining the integrity of level 0 programs. Some exceptions require the use of a task gate. The invalid task state segment exception (#10) can arise from errors in the original TSS as well as in the target TSS. Handling the exception within the same task could lead to recursive interrupts or other undesirable effects that are difficult to trace. The double fault exception (#8) should also use a task gate to prevent shutdown from another protection violation occurring during the servicing of the exception. 9.6 Protection Exceptions and Reserved Vectors A protection violation will cause an exception, i.e., a non-maskable interrupt. Such a fault can be handled by the task that caused it if an interrupt or trap gate is used, or by a different task if a task gate is used (in the IDT). Protection exceptions can be classified into program errors or implicit requests for service. The latter include stack overflow and not-present faults. Examples of program errors include attempting to write into a read-only segment, or violating segment limits. Requests for service may use different interrupt vectors, but many diverse types of protection violation use the same general protection fault vector. Table 9-3 shows the reserved exceptions and interrupts. Interrupts 0-31 are reserved by Intel. When simultaneous external interrupt requests occur, they are processed in the fixed order shown in table 9-4. For each interrupt serviced, the machine state is saved. The new CS:IP is loaded from the gate or TSS. If other interrupts remain enabled, they are processed before the first instruction of the current interrupt handler, i.e., the last interrupt processed is serviced first. All but two exceptions are restartable after the exceptional condition is removed. The two non-restartable exceptions are the processor extension segment overrun and writing into read only segments with XCHG, ADC, SBB, RCL, and RCR instructions. The return address normally points to the failing instruction, including all leading prefixes. The instruction and data addresses for the processor extension segment overrun are contained in the processor extension status registers. Interrupt handlers for most exceptions receive an error code that identifies the selector involved, or a 0 in bits 15-3 of the error code field if there is no selector involved. The error code is pushed last, after the return address, on the stack that will be active when the trap handler begins execution. This ensures that the handler will not have to access another stack segment to find the error code. The following sections describe the exceptions in greater detail. Table 9-3. Reserved Exceptions and Interrupts Vector Description Restartable Code on Number Error Stack 0 Divide Error Exception Yes No 1 Single Step Interrupt Yes No 2 NMI Interrupt Yes No 3 Breakpoint Interrupt Yes No 4 INTO Detected Overflow Exception Yes No 5 BOUND Range Exceeded Exception Yes No 6 Invalid Opcode Exception Yes No 7 Processor Extension Not Available Exception Yes No 8 Double Exception Detected No Yes (Always 0) 9 Processor Extension Segment Overrun Interrupt No No 10 Invalid Task State Segment Yes Yes 11 Segment Not Present Yes Yes 12 Stack Segment Overrun or Not Present Yes Yes 13 General Protection Yes Except for writes into read-only segments (see section 9.6) Yes Table 9-4. Interrupt Processing Order Order Interrupt 1 Instruction exception 2 Single step 3 NMI 4 Processor extension segment overrun 5 INTR 9.6.1 Invalid OP-Code (Interrupt 6) When an invalid opcode is detected by the execution unit, interrupt 6 is invoked. (It is not detected until an attempt is made to execute it, i.e., prefetching an invalid opcode does not cause this exception.) The saved CS:IP will point to the invalid opcode or any leading prefixes; no error code is pushed on the stack. The exception can be handled within the same task, and is restartable. This exception will occur for all cases of an invalid operand. Examples include an inter-segment jump referencing a register operand, or an LES instruction with a register source operand. 9.6.2 Double Fault (Interrupt 8) If two separate faults occur during a single instruction, end if the first fault is any of #0, #10, #11, #12, and #13, exception 8 (Double Fault) occurs (e.g., a general protection fault in level 3 is followed by a not-present fault due to a segment not-present). If another protection violation occurs during the processing of exception 8, the 80286 enters shutdown, during which time no further instructions or exceptions are processed. Either NMI or RESET can force the CPU out of shutdown. An NMI input can bring the CPU out of shutdown if no errors occur while processing the NMI interrupt; otherwise, shutdown can only be exited via the RESET input. NMI causes the CPU to remain in protected mode, and RESET causes it to exit protected mode. Shutdown is signaled externally via a HALT bus operation with A1 LOW. A task gate must be used for the double fault handler to assure a proper task state to respond to the exception. The back link field in the current TSS will identify the TSS of the task causing the exception. The saved address will point at the instruction that was being executed (or was ready to execute) when the error was detected. The error code will be null. The "double fault" exception does not occur when detecting a new exception while trying to invoke handlers for the following exceptions: 1, 2, 3, 4, 5, 6, 7, 9, and 16. 9.6.3 Processor Extension Segment Overrun (Interrupt 9) Interrupt 9 signals that the processor extension (such as the 80287 numerics processor) has overrun the limit of a segment while attempting to read/write the second or subsequent words of an operand. The interrupt is generated by the processor extension data channel within the 80286 during the limit test performed on each transfer of data between memory and the processor extension. This interrupt can be handled in the same task but is not restartable. As with all external interrupts, Interrupt 9 is an asynchronous demand caused by the processor extension referencing something outside a segment boundary. Since Interrupt 9 can occur any time after the processor extension is started, the 80286 does not save any information that identifies what particular operation had been initiated in the processor extension. The processor extension maintains special registers that identify the last instruction it executed and the address of the desired operand. After this interrupt occurs, no WAIT or escape instruction, except FNINIT, can be executed until the interrupt condition is cleared or the processor extension is reset. The interrupt signals that the processor extension is requesting an invalid data transfer. The processor extension will always be busy when waiting on data. Deadlock results if the CPU executes an instruction that causes it to wait for the processor extension before resetting the processor extension. Deadlock means the CPU is waiting for the processor extension to become idle while the processor extension waits for the CPU to service its data request. The FNINIT instruction is guaranteed to reset the processor extension without causing deadlock. After the interrupt is cleared, this restriction is lifted. It is then possible to read the instruction and operand address via FSTENV or FSAVE, causing the segment overrun in the processor extension's special registers. The task interrupted by interrupt 9 is not necessarily the task that executed the ESC instruction that caused the interrupt. The operating system should keep track of which task last used the NPX (see section 11.4). If the interrupted task did not execute the ESC instruction, it can be restarted. The task that executed the ESC instruction cannot. 9.6.4 Invalid Task State Segment (Interrupt 10) Interrupt 10 is invoked if during a task switch the new TSS pointed to by the task gate is invalid. The EXT bit indicates whether the exception was caused by an event outside the control of the program. A TSS is considered invalid in the cases shown in table 9-5. Once the existence of the new TSS is verified, the task switch is considered complete, with the backlink set to the old task if necessary. All errors are handled in the context of the new task. Exception 10 must be handled through a task gate to insure a proper TSS to process it. The handler must reset the busy bit in the new TSS. 9.6.5 Not Present (Interrupt 11) Exception 11 occurs when an attempt is made to load a not-present segment or to use a control descriptor that is marked not-present. (If, however, the missing segment is an LDT that is needed in a task switch, exception 10 occurs.) This exception is fully restartable. Any segment load instruction can cause this exception. Interrupt 11 is always processed in the context of the task in which it occurs. The error code has the form shown in Table 9-5. The EXT bit will be set if an event external to the program caused an interrupt that subsequently referenced a not-present segment. Bit 1 will be set if the error code refers to an IDT entry, e.g., an INT instruction referencing a not-present gate. The upper 14 bits are the upper 14 bits of the segment selector involved. During a task switch, when a not-present exception occurs, the ES and DS segment registers may not be usable for referencing memory (the selector values are loaded before the descriptors are checked). The not-present handler should not rely on being able to use the values found in ES, SS, and DS without causing another exception. This is because the task switch itself may have changed the values in the registers. The exception occurs in the new task and the return pointer points to the first instruction of the new task. Caution: the loading of the DS or ES descriptors may not have been completed. The exception II handler should ensure that the DS and ES descriptors have been properly loaded before the execution of the first instruction of the new task. Table 9-5. Conditions That Invalidate the TSS Reason Error Code The limit in the TSS descriptor is less than 43 TSS id + EXT Invalid LDT selector or LDT not present LDT id + EXT Stack segment selector is null SS id + EXT Stack segment selector is outside table limit SS id + EXT Stack segment is not a writable segment SS id + EXT Stack segment DPL does not match new CPL SS id + EXT Stack segment selector RPL <> ECPL SS id + EXT Code segment selector is outside table limit CS id + EXT Code segment selector does not refer to code segment CS id + EXT Non-conforming code segment DPL <> ECPL CS id + EXT Conforming code segment DPL > CPL CS id + EXT DS or ES segment selector is outside table limits ES/DS id + EXT DS or ES are not readable segments ES/DS id + EXT 9.6.6 Stack Fault (Interrupt 12) Stack underflow or overflow causes exception 12, as does a not-present stack segment referenced during an inter-task or inter-level transition. This exception is fully restartable. A limit violation of the current stack results in an error code of 0. The EXT bit of the error code tells whether an interrupt external to the program caused the exception. Any instruction that loads a selector to SS (e.g., POP SS, task switch) can cause this exception. This exception must use a task gate if there is a possibility that any level 0 stack may not be present. When a stack fault occurs, the ES and DS segment registers may not be usable for referencing memory. During a task switch, the selector values are loaded before the descriptors are checked. The stack fault handler should check the saved values of SS, CS, DS, and ES to be sure that they refer to present segments before restoring them. 9.6.7 General Protection Fault (Interrupt 13) If a protection violation occurs which is not covered in the preceding paragraphs, it is classed as Interrupt 13, a general protection fault. The error code is zero for limit violations, write to read-only segment violations, and accesses relative to DS or ES when they are zero or refer to a segment at a greater privilege level than CPL. Other access violations (e.g., a wrong descriptor type) push a non-zero error code that identifies the selector used on the stack. Error codes with bit 0 cleared and bits 15-2 non-zero indicate a restartable condition. Bit 1 of the error code identifies whether the selector is in the IDT or LDT/GDT. If bit 1 = 0 then bit 2 separates LDT from GDT. Bit 0 (EXT) indicates whether the exception was caused by the program or an event external to it (i.e., single stepping, an external interrupt, a processor extension not-present or a segment overrun). If bit 0 is set, the selector typically has nothing to do with the instruction that was interrupted. The selector refers instead to some step of servicing an interrupt that failed. When bit 0 of the error code is set, the interrupted program can be restarted, except for processor extension segment overrun exceptions (see section 9.6.3). The exception with the bit 0 of the errorcode = 1 indicates some interrupt has been lost due to a fault in the descriptor pointed to by the error code. A non-zero error code with bit 0 cleared may be an operand of the interrupted instruction, an operand from a gate referenced by the instruction, or a field from the invalid TSS. During a task switch, when a general protection exception occurs, the ES and DS segment registers may not be usable for referencing memory (the selector vaues are loaded before the descriptors are checked). The general protection handler should not rely on being able to use the values found in ES, SS, and DS without causing another exception. This is because the task switch itself may have changed the values in the registers. The exception occurs in the new task and the return pointer points to the first instruction of the new task. Caution: the loading of the DS or ES descriptors may not have been completed. The exception 13 handler should ensure that the DS and ES descriptors have been properly loaded before the execution of the first instruction of the new task. In Real Address Mode, Interrupt 13 will occur if software attempts to read or write a 16-bit word at segment offset 0FFFFH. 9.7 Additional Exceptions and Interrupts Interrupts 0, 5, and 1 have not yet been discussed. Interrupt 0 is the divide-error exception, Interrupt 5 the bound-range exceeded exceptions, and Interrupt 1 the single step interrupt. The divide-error or bound-range exceptions make it appear as if that instruction had never executed: the registers are restored and the instruction can be restarted. The divide-error exception occurs during a DIV or an IDIV instruction when the quotient will be too large to be representable, or when the divisor is zero. Interrupt 5 occurs when a value exceeds the limit set for it. A program can use the BOUND instruction to check a signed array index against signed limits defined in a two-word block of memory. The block can be located just before the array to simplify addressing. The block's first word specifies the array's lower limit, the second word specifies the array's upper limit, and a register specifies the array index to be tested. 9.7.1 Single Step Interrupt (Interrupt 1) Interrupt 1 allows programs to execute one instruction at a time. This single-stepping is controlled by the TF bit in the flag word. Once this bit is set, an internal single step interrupt will occur after the next instruction has been executed. The interrupt saves the flags and return address on the stack, clears the TF bit, and uses an internally supplied vector of 1 to transfer control to the service routine via the IDT. The IRET instruction or a task switch must be used to set the TF bit and to transfer control to the next instruction to be single stepped. If TF=1 in a TSS and that task is invoked, it will execute the first instruction and then be interrupted. The single-step flag is normally not cleared by privilege changes inside a task. INT instructions, however, do clear TF. Therefore, software debuggers that single-step code must recognize and emulate INT n or INT 0 rather than executing them directly. System software should check the current execution privilege level after any single step interrupt to see whether single stepping should continue. The interrupt priorities in hardware guarantee that if an external interrupt occurs, single stepping stops. When both an external interrupt and a single step interrupt occur together, the single step interrupt is processed first. This clears the TF bit. After saving the return address or switching tasks, the external interrupt input is examined before the first instruction of the single step handler executes. If the external interrupt is still pending, it is then serviced. The external interrupt handler is not single-stepped. Therefore, to single step an interrupt handler, just single step an interrupt instruction that refers to the interrupt handler. Chapter 10 System Control and Initialization ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Special flags, registers, and instructions provide contol of the critical processes and interaction in 80286 operations. The flag register includes 3 bits that represent the current I/O privilege level (IOPL: 2 bits) and the nested task bit (NT). Four additional registers support the virtual addressing and memory protection features, one points to the current Task State Segment and the other three point to the memory-based descriptor tables: GDT, LDT, and IDT. These flags and registers are discussed in the next section. The machine status word, (which indicates processor configuration and status) and the instructions that load and store it are discussed in section 10.2.1. Similar instructions pertaining to the other registers are the subject of sections 10.2 and 10.3. A detailed description of initialization states and processes, which appears in section 10.4, is supplemented by the extensive example in Appendix A. Instructions that validate descriptors and pointers are covered in section 11.3. 10.1 System Flags and Registers The IOPL flag (bits 12 and 13 of the flags word) controls access to I/O operations and interrupt control instructions. These two bits represent the maximum privilege level (highest numerical CPL) at which the task is permitted to perform I/O instructions. Alteration of the IOPL flags is restricted to programs at level 0 or to a task switch. IRET uses the NT flag to select the proper return: if NT=0, the normal return within a task is performed. As discussed in Chapter 8, the nested task flag (bit 14 of flags) is set when a task initiates a task switch via a CALL or INT instruction. The old and new task state segments are marked busy and the backlink field of the new TSS is set to the old TSS selector. An interrupt that does not cause a task switch will clear NT after the old NT state is saved. To prevent a program from causing an illegal task switch by setting NT and then executing IRET, a zero selector should be placed in the backlink field of the TSS. An illegal task switch using IRET will then cause exception 13. The instructions POPF and IRET can also set or clear NT when flags are restored from the stack. POPF and IRET can also change the interrupt enable flag. If CPL Ύ IOPL, then the Interrupt Flag (IF) can be changed by POPF and IRET. Otherwise, the state of the IF bit in the new flag word is ignored by these instructions. Note that the CLI and STI instructions are valid only when CPL Ύ IOPL; otherwise exception 13 occurs. 10.1.1 Descriptor Table Registers The three descriptor tables used for all memory accesses are based at addresses supplied by (stored in) three registers: the global descriptor table register (GDTR), the interrupt descriptor table register (IDTR), and the local descriptor table register (LDTR). Each register contains a 24-bit base field and a 16-bit limit field. The base field gives the real memory address of the beginning of the table; the limit field tells the maximum offset permitted in accessing table entries. See figures 10-1, 10-2, and 10-3. The LDTR also contains a selector field that identifies the descriptor for that table. LDT descriptors must reside in the GDT. The task register (TR) points to the task state segment for the currently active task. It is similar to a segment register, with selector, base, and limit fields, of which only the selector field is readable under normal circumstances. Each such selector serves as a unique identifier for its task. The uses of the TR are described in Chapter 8. The instructions controlling these special registers are described in the next section. Figure 10-1. Local and Global Descriptor Table Definition MEMORY   ’‘˜‘‘‘Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β‘“  Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β  CPU   Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β  ‚ƒ  € ¨ €  € €   € ¨ € –‘ GDT € 15 0 €  € ¨ €  € ‚ƒ €   Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β  € 23 €LDT LIMITΓ‘‘‘Ξ‘• Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β  € ‚π‘‘‘‘‘‘‘‘‘Β €  Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β  GDTR € € GDT BASE Γ‘‘‘Ξ‘‘‘‘‘‘‘Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β‘• € „… € € € € € € € Γ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘Β € € € € € LDT{1} € € 15 0 € ’‘˜‘‘‘Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β‘“ € ‚ƒ €  Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β  € € LDT € €   Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β  € € SELECTOR € €  € ¨ €  € „… €   € ¨ € –‘ CURRENT LDT €’‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘“€  € ¨ €  € 15 0 €   Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β  € ‚ƒ €  Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β  € 23 €LDT LIMITΓ‘‘šΞ‘•  Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β  € ‚π‘‘‘‘‘‘‘‘‘Β € ’‘‘‘‘Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β‘• LDTR € € LDT BASE Γ‘‘šΓ‘‘• € € € „… € € € € PROGRAM INVISIBLE € € € €”‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘ ‘‘•€ € LDT{n} € „… Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β € ¨ € € ¨ € € ¨ € Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β   Figure 10-2. Interrupt Descriptor Table Definition MEMORY   € € ’‘‘‘˜‘†‡‘“  € GATE FOR €    € INTERRUPT #n €   †‡    € GATE FOR €   €INTERRUPT #n-1 €    †‡   € ¨ €  INTERRUPT   € ¨ € –‘ DESCRIPTOR  € ¨ €  TABLE (IDT) CPU   †‡  ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“  € GATE FOR €   15 0    € INTERRUPT #1 €   ‚ƒ   †‡   €IDT LIMITΓ‘‘š‘•  € GATE FOR €   ‚π‘‘‘‘‘‘‘‘‘Β  € INTERRUPT #0 €  IDTR  € IDT BASE Γ‘‘š‘‘‘‘‘™‘†‡‘•  „…  € €  23 0    ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘• Figure 10-3. Data Type for Global Descriptor Table and Interrupt Descriptor Table 7 0 7 0 ‚Πƒ +5€ INTEL RESERVED Must be set to 0 for compatibility with the 80386  BASE{23-16} €+4 Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β +3€ BASE{15-0} €+2 Γ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Β +1€ LIMIT{15-0} € 0 „€… 0 10.2 System Control Instructions The instructions that load the GDTR and IDTR from memory can only be executed in real address mode or at privilege level 0; otherwise exception 13 occurs. The store instructions for GDTR and IDTR may be executed at any privilege level. The four instructions are LIDT, LGDT, SIDT, and SGDT. The instructions move 3 words between the indicated descriptor table register and the effective real memory address supplied (see figure 10-3). The format of the 3 words is: a 2-byte limit, a 3-byte real base address, followed by an unused byte. These instructions are normally used during system initialization. The LLDT instruction loads the LDT registers from a descriptor in the GDT. LLDT uses a selector operand to that descriptor rather than referencing the descriptor directly. LLDT is only executable at privilege level 0; otherwise exception 13 occurs. LLDT is normally required only during system initialization because the processor automatically exchanges the LDTR contents as part of the task-switch operation. Executing an LLDT instruction does not automatically update the TSS or the register caches. To properly change the LDT of the currently running task so that the change holds across task switches, you must perform, in order, the following three steps: 1. Store the new LDT selector into the appropriate word of TSS. 2. Load the new LDT selector into LDTR. 3. Reload the DS and ES registers if they refer to LDT-based descriptors. Note that the current code segment and stack segment descriptors should reside in the GDT or be copied to the same location in the new LDT. SLDT (store LDT) can be executed at any privilege level. SLDT stores the local descriptor table selector from the program visible portion of the LDTR register. Task Register loading or storing is again similar to that of the LDT. The LTR instruction, operating only at level 0, loads the LTR at initialization time with a selector for the initial TSS. LTR does NOT cause a task switch; it just changes the current TSS. Note that the busy bit of the old TSS descriptor is not changed while the busy bit of the new TSS selector must be zero and will be set by LTR. The LDT and any segment registers referring to the old LDT should be reloaded. STR, which permits the storing of TR contents into memory, can be executed at any privilege level. LTR is not usually needed after initialization because the TR is managed by the task-switch operation. 10.2.1 Machine Status Word The Machine Status Word (MSW) indicates the 80286 configuration and status. It is not part of a task's state. The MSW word is loaded by the LMSW instruction executed in real address mode or at privilege level 0 only, or is stored by the SMSW instruction executing at any privilege level. MSW is a 16-bit register, the lower four bits of which are used by the 80286. These bits have the meanings shown in table 10-1. Bits 15-4 of the MSW will be used by the 80386. 80286 software should not change these bits. If the bits are changed by the 286 software, compatibility with the 80386 will be destroyed. The TS flag is set under hardware control and reset under software control. Once the TS flag is set, the next instruction using a processor extension causes a processor extension not-present exception (#7). This feature allows software to test whether the current processor extension state belongs to the current task as discussed in section 11.4. If the current processor extension state belongs to a different task, the software can save the state of any processor extension with the state of the task that uses it. Thus, the TS bit protects a task from processor extension errors that result from the actions of a previous task. The CLTS instruction is used to reset the TS flag after the exception handler has set up the proper processor extension state. The CLTS instruction can be executed at privilege level 0 only. The EM flag indicates a processor extension function is to be emulated by software. If EM=1 and MP=0, all ESCAPE instructions will be trapped via the processor extension not-present exception (#7). MP flag tells whether a processor extension is present. If MP=1 and TS=1, escape and wait instructions will cause exception 7. If ESC instructions are to be used, either the MP or the EM bit must be set, but not both. The PE flag indicates that the 80286 is in the protected virtual address mode. Once the PE flag is set, it can be cleared only by a reset, which then puts the system in real address mode emulating the 8086. Table 10-2 shows the recommended usage of the MSW. Other encodings of these bits are not recommended. Table 10-1. MSW Bit Functions Bit Position Name Function 0 PE Protected mode enable places the 80286 into protected mode and cannot be cleared except by RESET. 1 MP Monitor processor extension allows WAIT instructions to cause a processor extension not-present exception (number 7) if TS is also set. 2 EM Emulate processor extension causes a processor extension not-present exception (number 7) on ESC instructions to allow a processor extension to be emulated. 3 TS Task switched indicates the next instruction using a processor extension will cause exception 7, allowing software to test whether the current processor extension context belongs to the current task. Table 10-2. Recommended MSW Encodings for Processor Extension Control TS MP EM Recommended Use Instructions Causing Exception 0 0 0 Initial encoding after RESET. 80286 operation is identical to 8086, 8088. Use this encoding only if no ESC instructions are to be executed. None 0 0 1 No processor extension is available. Software will emulate its function. Wait instructions do not cause exception 7. ESC 1 0 1 No processor extension is available. Software will emulate its function. The current processor extension context may belong to another task. ESC 0 1 0 A processor extension exists. WAIT (if TS=1) 1 1 0 A processor extension exists. The current processor extension context may belong to another task. The exception on WAIT allows software to test for an error pending from a previous processor extension operation. ESC or WAIT (if TS=1) 10.2.2 Other Instructions Instructions that verify or adjust access rights, segment limits, or privilege levels can be used to avoid exceptions or faults that are correctable. Section 10.3 describes such instructions. 10.3 Privileged and Trusted Instructions Instructions that execute only at CPL=0 are called "privileged." An attempt to execute the privileged instructions at any other privilege level causes a general protection exception (#13) with an error code of zero. The privileged instructions manipulate descriptor tables or system registers. Incorrect use of these instructions can produce unrecoverable conditions. Some of these instructions (LGDT, LLDT, and LTR) are discussed in section 10.2. Other privileged instructions are: Ž LIDT‘‘Load interrupt descriptor table register Ž LMSW‘‘Load machine status word Ž CLTS‘‘Clear task switch flag Ž HALT‘‘Halt processor execution Ž POPF (POP flags) or IRET can change the IF value only if the user is operating at a trusted privilege level. POPF does not change IOPL except at Level 0. "Trusted" instructions are restricted to execution at a privilege level of CPL  IOPL. For each task, the operating system defines a privilege level below which these instructions cannot be used. Most of these instructions deal with input/output or interrupt management. The IOPL field in the flag word that holds the privilege level limit can be changed only when CPL=0. The trusted instructions are: Ž Input/Output‘‘Block I/O, Input, and Output: IN, INW, OUT, OUTW, INSB, INSW, OUTSB, OUTSW Ž Interrupts‘‘Enable Interrupts, Disable Interrupts: STI, CLI Ž Other‘‘Lock Prefix 10.4 Initialization Whenever the 80286 is initialized or reset, certain registers are set to predefined values. All additional desired initialization must be performed by user software. (See Appendix A for an example of a 286 initialization routine.) RESET forces the 80286 to terminate all execution and local bus activity; no instruction or bus action will occur as long as RESET is active. Execution in real address mode begins after RESET becomes inactive and an internal processing interval (3-4 clocks) occurs. The initial state at reset is: FLAGS = 0002 MSW = FFF0H IP = FFF0H CS Selector = F000H CS.base = FF0000H CS.limit = FFFFH CS Selector = 0000H CS.base = 000000H CS.limit = FFFFH ES Selector = 0000H ES.base = 000000H ES.limit = FFFFH IDT base = 000000H IDT.limit = 03FFH Two fixed areas of memory are reserved: the system initialization area and the interrupt table area. The system initialization area begins at FFFFF0H (through FFFFFFH) and the interrupt table area begins at 000000H (through 0003FFH). The interrupt table area is not reserved. At this point, segment registers are valid and protection bits are set to 0. The 80286 begins operation in real address mode, with PE=0. Maskable interrupts are disabled, and no processor extension is assumed or emulated (EM=MP=0). DS, ES, and SS are initialized at reset to allow access to the first 64K of memory (exactly as in the 8086). The CS:IP combination specifies a starting address of FFFF0H. For real address mode, the four most significant bits are not used, providing the same FFF0H address as the 8086 reset location. Use of (or upgrade to) the protected mode can be supported by a bootstrap loader at the high end of the address space. As mentioned in Chapter 5, location FFF0H ordinarily contains a JMP instruction whose target is the actual beginning of a system initialization or restart program. After RESET, CS points to the top 64K bytes in the 16-Mbyte physical address space. Reloading CS register by a control transfer to a different code segment in real address mode will put zeros in the upper 4 bits. Since the initial IP is FFF0H, all of the upper 64K bytes of address space may be used for initialization. Sections 10.4.1 and 10.4.2 describe the steps needed to initialize the 80286 in the real address mode and the protected mode, respectively. 10.4.1 Real Address Mode 1. Allocate a stack. 2. Load programs and data into memory from secondary storage. 3. Initialize external devices and the Interrupt Vector Table. 4. Set registers and MSW bits to desired values. 5. Set FLAG bits to desired values‘‘including the IF bit to enable interrupts‘‘after insuring that a valid interrupt handler exists for each possible interrupt. 6. Execute (usually via an inter-segment JMP to the main system program). 10.4.2 Protected Mode The full 80286 virtual address mode initialization procedure requires additional steps to operate correctly: 1. Load programs and associated descriptor tables. 2. Load valid GDT and IDT descriptor tables, setting the GDTR and IDTR to their correct value. 3. Set the PE bit to enter protected mode. 4. Execute an intra-segment JMP to clear the processor queues. 5. Load or construct a valid task state segment for the initial task to be executed in protected mode. 6. Load the LDTR selector from the task's GDT or 0000H (null) if an LDT is not needed. 7. Set the stack pointer (SS, SP) to a valid location in a valid stack segment. 8. Mark all items not in memory as not-present. 9. Set FLAGS and MSW bits to correct values for the desired system configuation. 10. Initialize external devices. 11. Ensure that a valid interrupt handler exists for each possible interrupt. 12. Enable interrupts. 13. Execute. The example in Appendix A shows the steps necessary to load all the required tables and registers that permit execution of the first task of a protected mode system. The program in Appendix A assumes that Intel development tools have been used to construct a prototype GDT, IDT, LDT, TSS, and all the data segments necessary to start up that first task. Typically, these items are stored on EPROM; on most systems it is necessary to copy them all into RAM to get going. Otherwise, the 80286 will attempt to write into the EPROM to set the accessed or busy bits. The example in Appendix A also illustrates the ability to allocate unused entries in descriptor tables to grow the tables dynamically during execution. Using suitable naming conventions, the builder can allocate alias data segments that are larger than the prototype EPROM version. The code in the example will zero out the extra entries to permit later dynamic usage. Chapter 11 Advanced Topics ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ This chapter describes some of the advanced topics as virtual memory management, restartable instructions, special segment attributes, and the validation of descriptors and pointers. 11.1 Virtual Memory Management When access to a segment is requested and the access byte in its descriptor indicates the segment is not present in real memory, the not-present fault occurs (exception 11, or 12 for stacks). The handler for this fault can be set up to bring the absent segment into real memory (swapping or overwriting another segment if necessary), or to terminate execution of the requesting program if this is not possible. The accessed bit (bit 0) of the access byte is provided in both executable and data segment descriptors to support segment usage profiling. Whenever the descriptor is accessed by the 80286 hardware, the A-bit will be set in memory. This applies to selector test instructions (described below) as well as to the loading of a segment register. The reading of the access byte and the restoration of it with the A-bit set is an indivisible operation, i.e., it is performed as a read-modify-write with bus lock. If an operating system develops a profile of segment usage over time, it can recognize segments of low or zero access and choose among these candidates for replacement. When a not-present segment is brought into real memory, the task that requested access to it can continue its execution because all instructions that load a segment register are restartable. Not-present exceptions occur only on segment register load operations, gate accesses, and task switches. The saved instruction pointer refers to the first byte of the violating instruction. All other aspects of the saved machine state are exactly as they were before execution of the violating instruction began. After the fault handler clears up the fault condition and performs an IRET, the program continues to execute. The only external indication of a segment swap is the additional execution time. 11.2 Special Segment Attributes 11.2.1 Conforming Code Segments Code segments intended for use at potentially different privilege levels need an attribute that permits them to emulate the privilege level of the calling task. Such segments are termed "conforming" segments. Conforming segments are also useful for interrupt-driven error routines that need only be as privileged as the routine that caused the error. A conforming code segment has bit 2 of its access byte set to 1. This means it can be referenced by a CALL or JMP instruction in a task of equal or lesser privilege, i.e., CPL of the task is numerically greater than or equal to DPL of this segment. CPL does not change when executing the conforming code segment. A conforming segment continues to use the stack from the CPL. This is the only case in which the DPL of a code segment can be numerically less than the CPL. If bit 2 is a 0, the segment is not conforming and can be referenced only by a task of CPL = DPL. Inter-segment Returns that refer to conforming code segments use the RPL field of the code selector of the return address to determine the new CPL. The RPL becomes the new CPL if the conforming code segment DPL Ύ RPL. If a conforming segment is readable, it can be read from any privilege level without restriction. This is the only exception to the protection rules. This allows constants to be stored with conforming code. For example, a read-only look-up table can be embedded in a conforming code segment that can be used to convert system-wide logical ID's into character strings that represent those logical entities. 11.2.2 Expand-Down Data Segments If bit 2 in the access byte of a data segment is 1, the segment is an expand-down segment. All the offsets that reference such a segment must be strictly greater than the segment limit, as opposed to normal data segments (bit 2 = 0) where all offsets must be less than or equal to the segment limit. Figure 11-1 shows an expand-down segment. The size of the expand down segment can be changed by changing either the base or the limit. An expand down segment with Limit = 0 will have a size of 2^(16)-1 bytes. With a limit value of FFFFH, the expand down segment will have a size of 0 bytes. In an expand down segment, the base + offset value should always be greater than the base + limit value. Therefore, a full size segment (2^(16) bytes) can only be obtained by using an expand up segment. The operating system should check the Expand-Down bit when a protection fault indicates that the limit of a data segment has been reached. If the Expand-Down bit is not set, the operating system should increase the segment limit; if it is set, the limit should be lowered. This supplies more room in either case (assuming the segment is not write-protected, i.e., that bit 1 is not 0). In some cases, if the operating system can ascertain that there is not enough room to expand the data segment to meet the need that caused the fault, it can move the data segment to a region of memory where there is enough room. See figure 11-2. Figure 11-1. Expand-Down Segment € € € € € € BASE + FFFEH ‘‘‘‘Γ‘‘‘‘‘‘‘‘‘‘‘‘‘Β‘“ €œœœœœœœœœœœœœ€  €œœœœœœœœœœœœœ€  €œœœœœœœœœœœœœ€  €œœœœœœœœœœœœœ€  BASE + OFFSET ‘‘‘‘€œœœœœœœœœœœœœ€ –‘ EXPAND DOWN >BASE + LIMIT €œœœœœœœœœœœœœ€  SEGMENT €œœœœœœœœœœœœœ€  €œœœœœœœœœœœœœ€  €œœœœœœœœœœœœœ€  BASE + LIMIT ‘‘‘‘Γ‘‘‘‘‘‘‘‘‘‘‘‘‘Β‘• € € € € € € € € ‘‘‘‘€‘‘ ‘‘ ‘‘ ‘‘ ‘€ € € Figure 11-2. Dynamic Segment Relocation and Expansion of Segment Limit €œœœœœœœœœœœœœ€ €œœœœœœœœœœœœœ€ €œœœœœœœœœœœœœ€ €œœœœœœœœœœœœœ€ €œœœœœœœœœœœœœ€ BASE + 10000H‘‘‘Γ‘‘‘‘‘‘‘‘‘‘‘‘‘Β €œœœœœœœœœœœœœ€ € € € € € STACK € € SEG. B € € € € € € € BASE + 10000H‘‘‘Γ‘‘‘‘‘‘‘‘‘‘‘‘‘Β NEW BASE‘‘‘Γ‘‘‘‘‘‘‘‘‘‘‘‘‘Β € € + NEW LIMIT € SEG. B € € STACK € € € € € NEW BASE‘‘‘€œœœœœœœœœœœœœ€ € € €œœœœœœœœœœœœœ€ OLD BASE‘‘‘Γ‘‘‘‘‘‘‘‘‘‘‘‘‘Β €œœœœœœœœœœœœœ€ + OLD LIMIT € € € € € SEG. A € € SEG. A € € € € € OLD BASE‘‘‘€œœœœœœœœœœœœœ€ €œœœœœœœœœœœœœ€ €œœœœœœœœœœœœœ€ €œœœœœœœœœœœœœ€ €œœœœœœœœœœœœœ€ €œœœœœœœœœœœœœ€ €œœœœœœœœœœœœœ€ €œœœœœœœœœœœœœ€ 11.3 Pointer Validation Pointer validation is an important part of locating programming errors. Pointer validation is necessary for maintaining isolation between the privilege levels. Pointer validation consists of the following steps: 1. Check if the supplier of the pointer is entitled to access the segment. 2. Check if the segment type is appropriate to its intended use. 3. Check if the pointer violates the segment limit. The 80286 hardware automatically performs checks 2 and 3 during instruction execution, while software must assist in performing the first check. This point is discussed in section 11.3.2. Software can explicitly perform steps 2 and 3 to check for potential violations (rather than causing an exception). The unprivileged instructions LSL, LAR, VERR, and VERW are provided for this purpose. The load access rights (LAR) instruction obtains the access rights byte of a descriptor pointed to by the selector used in the instruction. If that selector is visible at the CPL, the instruction loads the access byte into the specified destination register as the higher byte (the low byte is zero) and the zero flag is set. Once loaded, the access bits can be tested. System segments such as a task state segment or a descriptor table cannot be read or modified. This instruction is used to verify that a pointer refers to a segment of the proper privilege level and type. If the RPL or CPL is greater than DPL, or the selector is outside the table limit, no access value is returned and the zero flag is cleared. Conforming code segments may be accessed from any RPL or CPL. Additional parameter checking can be performed via the load segment limit (LSL) instruction. If the descriptor denoted by the given selector (in memory or a register) is visible at the CPL, LSL loads the specified register with a word that consists of the limit field of that descriptor. This can only be done for segments, task state segments, and local descriptor tables (i.e., words from control descriptors are inaccessible). Interpreting the limit is a function of the segment type. For example, downward expandable data segments treat the limit differently than code segments do. For both LAR and LSL, the zero flag (ZF) is set if the loading was performed; otherwise, the zero flag is cleared. Both instructions are undefined in real address mode, causing an invalid opcode exception (interrupt #6). 11.3.1 Descriptor Validation The 80286 has two instructions, VERR and VERW, which determine whether a selector points to a segment that can be read or written at the current privilege level. Neither instruction causes a protection fault if the result is negative. VERR verifies a segment for reading and loads ZF with 1 if that segment is readable from the current privilege level. The validation process checks that: 1) the selector points to a descriptor within the bounds of the GDT or LDT, 2) it denotes a segment descriptor (as opposed to a control descriptor), and 3) the segment is readable and of appropriate privilege level. The privilege check for data segments and non-conforming code segments is that the DPL must be numerically greater than or equal to both the CPL and the selector's RPL. Conforming segments are not checked for privilege level. VERW provides the same capability as VERR for verifying writability. Like the VERR instruction, VERW loads ZF if the result of the writability check is positive. The instruction checks that the descriptor is within bounds, is a segment descriptor, is writable, and that its DPL is numerically greater than or equal to both the CPL and the selector's RPL. Code segments are never writable, conforming or not. 11.3.2 Pointer Integrity: RPL and the "Trojan Horse Problem" The Requested Privilege Level (RPL) feature can prevent inappropriate use of pointers that could corrupt the operation of more privileged code or data from a less privileged level. A common example is a file system procedure, FREAD (file_id, nybytes, buffer-ptr). This hypothetical procedure reads data from a file into a buffer, overwriting whatever is there. Normally, FREAD would be available at the user level, supplying only pointers to the file system procedures and data located and operating at a privileged level. Normally, such a procedure prevents user-level procedures from directly changing the file tables. However, in the absence of a standard protocol for checking pointer validity, a user-level procedure could supply a pointer into the file tables in place of its buffer pointer, causing the FREAD procedure to corrupt them unwittingly. By using the RPL, you can avoid such problems. The RPL field allows a privilege attribute to be assigned to a selector. This privilege attribute would normally indicate the privilege level of the code which generated the selector. The 80286 hardware will automatically check the RPL of any selector loaded into a segment register or a control register to see if the RPL allows access. To guard against invalid pointers, the called procedure need only ensure that all selectors passed to it have an RPL at least as high (numerically) as the original caller's CPL. This indicates that the selectors were not more trusted than their supplier. If one of the selectors is used to access a segment that the caller would not be able to access directly, i.e., the RPL is numerically greater than the DPL, then a protection fault will result when loaded into a segment or control register. The caller's CPL is available in the CS selector that was pushed on the stack as the return address. A special instruction, ARPL, can be used to appropriately adjust the RPL field of the pointer. ARPL (Adjust RPL field of selector instruction) adjusts the RPL field of a selector to become the larger of its original value and the value of the RPL field in a specified register. The latter is normally loaded from the caller's CS register which can be found on the stack. If the adjustment changes the selector's RPL, ZF is set; otherwise, the zero flag is cleared. 11.4 NPX Context Switching The context of a processor extension (such as the 80287 numerics processor) is not changed by the task switch operation. A processor extension context need only be changed when a different task attempts to use the processor extension (which still contains the context of a previous task). The 80286 detects the first use of a processor extension after a task switch by causing the processor extension not-present exception (#7) if the TS bit is set. The interrupt handler may then decide whether a context change is necessary. The 286 services numeric errors only when it executes wait or escape instructions because the processor extension is running independently. Therefore, the numerics error from one task may not be recorded until the 286 is running a different task. If the 286 task has changed, it makes sense to defer handling that error until the original task is restored. For example, interrupt handlers that use the NPX should not have their timing upset by a numeric error interrupt that pertains to some earlier process. It is of little value to service someone else's error. If the task switch bit is set (bit 3 of MSW) when the CPU begins to execute a wait or escape instruction, the processor-extension not-present exception results (#7). The handler for this interrupt must know who currently "owns" the NPX, i.e., the handler must know the last task to issue a command to the NPX. If the owner is the same as the current task, then it was merely interrupted and the interrupt handler has since returned; the handler for interrupt 7 simply clears the TS bit, restores the working registers, and returns (restoring interrupts if enabled). If the recorded owner is different from the current task, the handler must first save the existing NPX context in the save area of the old task. It can then re-establish the correct NPX context from the current task's save area. The code example in figure 11-3 relies on the convention that each TSS entry in the GDT is followed by an alias entry for a data segment that points to the same physical region of memory that contains the TSS. The alias segment also contains an area for saving the NPX context, the kernel stack, and certain kernel data. That is, the first 44 bytes in that segment are the 286 context, followed by 94 bytes for the processor extension context, followed in some cases by the kernel stack and kernel private data areas. The implied convention is that the stack segment selector points to this data segment alias so that whenever there is an interrupt at level zero and SS is automatically loaded, all of the above information is immediately addressable. It is assumed that the program example knows about only one data segment that points to a global data area in which it can find the one word NPX owner to begin the processing described. The specific operations needed, and shown in the figure, are listed in table 11-1. Table 11-1. NPX Context Switching Step Operation Lines (Figure 11-3) 1. Save the working registers 28, 29 2. Set up address for kernel work area 30, 31 3. Get current task ID from Task Register 32 4. Clear Task Switch flag to allow NPX work 34 5. Inhibit interrupts 35 6. Compare owner with current task ID 37 If same owner: 7a. Restore working registers 48, 49 7b. and return 50 If owner is not current task: 8a. Use owner ID to save old context in its TSS 42, 43, 44 8b. Restore context of current task; 45 restore working registers; 46 and return 52 Figure 11-3. Example of NPX Context Switching ASSEMBLER INVOKED BY: ASM286,86 :FS:SWNPX.A86 LOC OBJ LINE SOURCE 1 + 1 $title('Switch the NPX Context on First Use After a Task Switch') 2 3 name switch_npx_context 4 5 public switch_NPX_context 6 extrn last_npx_task:word 7 ; 8 ; This interrupt handler will switch the NPX context if a new task 9 ; is attempting to use the NPX context of another task after a task 10 ; switch. If the NPX context belongs to the current task, nothing happens. 11 ; 12 ; A trap gate should be placed in IDT entry 7 referring to this routine. 13 ; The DPL of the gate should be 0 to prevent spoofing. The code segment 14 ; must be at privilege level 0. 15 ; 16 ; The kernel stack is assumed to overlay the TSS and the NPX save area 17 ; is placed at the end of the TSS area. 18 ; 19 ; A global word variable LAST_NPX_TASK identifies the TSS selector of 20 ; the last task to use the NPX. 21 ; 002C 22 npx_save_area equ word ptr 44 ; Offset of NPX save area in TSS 23 + 1 $eject ¨¨¨¨ 24 kernal_code segment er public 25 0000 26 switch_npx_context proc far wc(0) 27 0000 50 28 push ax ; Save working registers 0001 1E 29 push ds 0002 B8¨¨¨¨ E 30 mov ax,seg last_npx_task ; Get address of id of last NPX task 0005 8ED8 31 mov ds,ax 0007 0F00C8 32 str ax ; Get id of this task 000A 24FC 33 and al,not 3 ; Remove RPL field 000C 0F06 34 clts ; Clear task switched flag 000E FA 35 cli ; No interrupts allowed! 36 ; 37 ; Last_npx_word cannot change due to other interrupts after this point. 38 ; 000F 3B060000 E 39 cmp ax,ds:last_npx_task ; See if same task 0013 7412 40 je same_task 41 0015 87060000 E 42 xchg ax,ds:last_npx_task ; Set new task id and get old one 0019 050800 43 add ax,8 ; Go to TSS alias 001C 8ED8 44 mov ds,ax ; Address TSS of previous NPX task 001E DD362C00 45 fsave ds:npx_save_area ; Save old NPX state 0022 36DD262C00 46 frstor ss:npx_save_area ; Get current NPX state 0027 47 same_task: 0027 1F 48 pop ds ; Return to interrupted program 0028 58 49 pop ax 0029 CF 50 iret 51 52 switch_npx_context endp 53 - - - - 54 kernel_code ends *** WARNING #160, LINE #54, SEGMENT CONTAINS PRIVILEGED INSTRUCTIONS 55 end 11.5 Multiprocessor Condiderations As mentioned in Chapter 8, a bus lock is applied during the testing and setting of the task busy bit to ensure that two processors do not invoke the same task at the same time. However, protection traps and conflicting use of dynamically varying segments or descriptors must be addressed by an inter-processor synchronization protocol. The protocol can use the indivisible semaphore operation of the base instruction set. Coordination of interrupt and trap vectoring must also be addressed when multiple concurrent processors are operating. The interrupt bus cycles are locked so no interleaving occurs on those cycles. Descriptor caching is locked so that a descriptor reference cannot be altered while it is being fetched. When a program changes a descriptor that is shared with other processors, it should broadcast this fact to the other processors. This broadcasting can be done with an inter-processor interrupt. The handler for this interrupt must ensure that the segment registers, the LDTR and the TR, are re-loaded. This happens automatically if the interrupt is serviced by a task switch. Modification of descriptors of shared segments in multi-processor systems may require that the on-chip descriptors also be updated. For example, one processor may attempt to mark the descriptor of a shared segment as not-present while another is using it. Software has to ensure that the descriptors in the segment register caches are updated with the new information. The segment register caches can be updated by a re-entrant procedure that is invoked by an inter-processor interrupt. The handler must ensure that the segment registers, the LDTR and the TR, are re-loaded. This happens automatically if the interrupt is serviced by a task switch. 11.6 Shutdown Shutdown occurs when a severe error condition prevents further processing. Shutdown is very similar to HLT in that the 80286 stops executing instructions. The 80286 externally signals shutdown as a Halt bus cycle with A1=0. The NMI or RESET input will force the 80286 out of shutdown. The INTR input is ignored during shutdown. Appendix A 80286 System Initialization ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ $title('Switch the 80286 from Real Address Mode to Protected Mode') name switch 80286_modes public idt_desc,gdt_desc ; ; Switch the 80286 from real address mode into protected mode. ; The initial EPROM GDT, IDT, TSS, and LDT (if any) constructed by BLD286 ; will be copied from EPROM into RAM. The RAM areas are defined by data ; segments allocated as fixed entries in the GDT. The CPU registers for ; GDT, IDT, TSS, and LDT will be set to point at the RAM-based ; segments. The base fields in the RAM-based GDT will also be updated to ; point at the RAM-based segments. ; ; This code is used by adding it to the list of object modules given ; to BLD286. BLD286 must then be told to place the setment ; init_code at address FFFE10H. Execution of the mode switch code begins ; after RESET. This happens because the mode switch code will start at ; physical address FFFFF0H, which is the power up address. This code then ; sets up RAM copies of the EPROM-based segments before jumping to the ; initial tsk placed at a fixed GDT entry. After the jump, the CPU ; executes in the state of the first task defined by BLD286. ; ; This code will not use any of the EPROM-based tables directly. ; Such use would result in the 80286 writing into EPROM to set ; the A bit. Any use of a GDT or TSS will always be in the RAM copy. ; The limit and size of the EPROM-based GDT and IDT must be stored at ; the public symbols idt_desc and gdt_desc. The location commands of BLD286 ; provide this function. ; ; Interrupts are disabled during this mode switching code. Full error ; checking is made of the EPROM-based GDT, IDT, TSS, and LDT to assure ; they are valid before copying them to RAM. If any of the RAM-based ; aslias segments are smaller than the EPROM segments they are to hold, ; halt or shutdown will occur. In general, any exception or NMI will ; cause shutdown to occur until the first task is invoked. ; ; If the RAM segment is larger than the EPROM segment, the RAM segment ; will be expanded with zeros. If the initial TSS specifies an LDT, ; the LDT will also be copied into ldt_alias with zero fill if needed. ; The IPROM-based or RAM-based GDT, IDT, TSS, and LDT segments may be located ; anywhere in physical memory. ; ; ; Define layout of a descriptor. ; desc struc limit dw 0 ; Offset of last byte in segment base_low dw 0 ; Low 16 bits of 24-bit address base_high db 0 ; High 8 bits of 24-bit address access db 0 ; Access rights byte res dw 0 ; Reserved word desc ends ; ; Define the fixed GDT selector values for the descriptors that ; define the EPROM-based tables. BLD286 must be instructed to place the ; appropriate descriptors into the GDT. ; gdt_alias equ 1*size desc ; GDT(1) is data segment in RAM for GDT idt_alias equ 2*size desc ; GDT(2) is data segment in RAM for IDT start_TSS_alias equ 3*size desc ; GDT(3) is data segment in RAM for TSS start_task equ 4*size desc ; GDT(4) is TSS for starting task start_LDT_alias equ 5*size desc ; GDT(5) is data segment in RAM for LDT ; ; Define machine status word bit positions. ; PE equ 1 ; Protection enable MP equ 2 ; Monitor processor extension EM equ 4 ; Emulate processor extension ; ; Define particular values of descriptor access rights byte. ; DT_ACCESS equ 82H ; Access byte value for an LDT DS_ACCESS equ 92H ; Access byte value for data segment ; which is grow up, at level 0, writeable TSS_ACCESS equ 81H ; Access byte value for an idle TSS DPL equ 60H ; Privilege level field of access rights ACCESSED equ 1 ; Define accessed bit TI equ 4 ; Position of TI bit TSS_SIZE equ 44 ; Size of a TSS LDT_OFFSET equ 42 ; Position of LDT in TSS TIRPL_MASK equ size desc-1 ; TI and RPL field mask ; ; Pass control from the power-up address to the mode switch code. ; The segment containing this code must be at physical address FFFE10H ; to place the JMP instruction at physical address FFFFF0H. The base ; address is chosen according to the size of this segment. ; init_code segment er cs_offset equ 0FE10H ; Low 16 bits of starting address org 0FFF0H-cs_offset; Start at address FFFFF0H jmp reset_startup ; Do not change CS! ; ; Define the template for a temporary GDT used to locate the initial ; GDT and stack. This data will be copied to location 0. ; This space is also used for a temporary stack and finally serves ; as the TSS written into when entering the initial TSS. ; org 0 ; Place remaining code below power_up initial_gdt desc <> ; Filler and null IDT descriptor gdt_desc desc <> ; Descriptor for EPROM GDT idt_desc desc <> ; Descriptor for EPROM IDT temp_desc desc <> ; Temporary descriptor ; ; Define a descriptor that will point the GDT at location 0. ; This descriptor will also be loaded into SS to define the initial ; protected mode stack segment. ; temp_stack desc ; ; Define the TSS descriptor used to allow the task switch to the ; first task to overwrite this region of memory. The TSS will overlay ; the initial GDT and stack at location 0. ; save_tss desc ; ; Define the initial stack space and filler for the end of the TSS. ; dw 8 dup (0) end_gdt label word start_pointer label dword dw 0,start_task ; Pointer to initial task ; ; Define template for the task definition list. ; task_entry struc ; Define layout of task description TSS_sel dw ? ; Selector for TSS TSS_alias dw ? ; Data segment alias for TSS LDT_alias dw ? ; Data segment alias for LDT if any task_entry ends task_list task_entry dw 0 ; Terminate list reset_startup: cli ; No interrupts allowed! cld ; Use autoincrement mode xor di,di ; Point ES:DI at physical address 000000H mov ds,di mov es,di mov ss,di ; Set stack at end of reserved area mov sp,end_gdt-initial_gdt ; ; ; Form an adjustment factor from the real CS base of FF0000H to the ; segment base address assumed by ASM286. Any data reference mode ; into CS must add an indexing term [BP] to compensate for the difference ; between the offset generated by ASM286 and the offset required from ; the base of FF0000H. ; start proc ; The value of IP at run time will not be ; the same as the one used by ASM286! call start1 ; Get true offset of start1 start1: pop bp sub bp, offset start1 ; Subtract ASM286 offset of start1 ; leaving adjustment factor in BP lidt initial_gdt[bp] ; Setup null IDT to force shutdown ; on any protection error or interrupt ; ; Copy the EPROM-based temporary GDT into RAM. ; lea si,initial_gdt[bp] ; Setup pointer to temporary GDT ; template in EPROM mov cs,(end_gdt-initial_gdt)/2 ; Set length rep movs es:word ptr [di],cs:[si]; Put into reserved RAM area ; ; Look for 80287 processor extension. Assume all ones will be read ; if an 80287 is not present. ; fninit ; Initialize 80287 if present mov bx,EM ; Assume no 80287 fstsw ax ; Look at status of 80287 or al,al ; No errors should be present jnz set_mode ; Jump if no 80287 fsetpm ; Put 80287 into protected mode mov bx,MP ; ; Switch to protected mode and setup a stack, GDT, and LDT. ; set_mode; smsw ax ; Get current MSW or ax,PE ; Set PE bit or ax,bx ; Set NPX status flags lmsw ax ; nter protected mode! jmp $+2 ; Clear queue of instructions decoded ; while in Real Address Mode ; CPL is now 0, CS still points at ; FFFE10 in physical memory lgdt temp_stack[bp] ; Use initial GDT in RAM area mov ax,temp_stack-initial_gdt ; Setup SS with valid protected mode mov ss,ax ; selector to the RAM GDT and stack xor ax,ax ; Set the current LDT to null lidt ax ; Any references to it will cause ; an exception causing shutdown mov ax,save_tss-initial_gdt ; Set initial TSS into the low RAM ltr ax ; The task switch needs a valid TSS ; ; Copy the EPROM-based GDT into the RAM data segment alias. ; First the descriptor for the RAM data segment must be copied into ; the temporary GDT. ; mov ax,gdt_desc[bp].limit ; Get size of GDT cmp ax,6*size desc-1 ; Be sure the last entry expected by ; this code is inside the GDT jb bad_gdt ; Jump if GDT is not big enough mov bx,gdt_desc-initial_gdt ; Form selector to EPROM GDT mov si,gdt_alias ; Get selector of GDT alias call copy_EPROM_dt ; Copy into EPROM mov si,idt_alias ; Get selector of IDT alias mov bx,ldt_desc-initial_gdt ; Indicate EPROM IDT call copy_EPROM_dt mov ax,gdt_desc-initial_gdt ; Setup addressing into EPROM GDT mov ds,ax mov bx,gdt_alias ; Get GDT alias data segment selector lgdt [bx] ; Set GDT to RAM GDT ; SS and TR remain in low RAM ; ; Copy all task's TSS and LDT segments into RAM ; lea bx,task_list[bp] ; Define list of tasks to setup copy_task_loop: call copy_tasks ; Copy them into RAM add bx,size task_entry ; Go to next entry mov ax,cs:[bx].tss_sel ; See if there is another entry or ax,ax jnz copy_task_loop ; ; With TSS, GDT, and LDT set, startup the initial task! ; mov bx,gdt_alias ; Point DS at GDT mov ds,bx mov bx,idt_alias ; Get IDT alias data segment selector lidt [bx] ; Start the first task! jmp start_pointer[bp] ; The low RAM area is overwritten with ; the current CPU context bad_gdt: ; Wait here if GDT is not big enough hlt astart endp ; ; Copy the TSS and LDT for the task pointed at by CS:BX. ; If the task has an LDT it will also be copied down. ; BX and BP are transparent. ; bad_tss: hlt ; Halt here if TSS is invalid copy_tasks proc mov si,gdt_alias ; Get addressability to GDT mov ds,si mov si,cs:[bx].tss_alias ; Get selector for TSS alias mov es,si ; Point ES at alias data segment lsl ax,si ; Get length of TSS alias mov si,cs:[bx].tss_sel ; Get TSS selector lar dx,si ; Get alias access rights jnz bad_tss ; Jump if invalid reference mov dl,dh ; Save TSS descriptor access byte and dh,not DPL ; Ignore privilege cmp dh,TSS_ACCESS ; See if TSS jnz bad_tss ; Jump if not lsl cs,si ; Get length of EPROM based TSS cmp cs,TSS_SIZE-1 ; Verify it is of proper size jb bad_tss ; Jump if it is not big enough ; ; Setup for moving the EPROM-based TSS to RAM ; DS points at GDT ; mov [si].access,DS_ACCESS ; Make TSS into data segment mov ds,si ; Point DS at EPROM TSS call copy_with_fill ; Copy DS segment to ES with zero fill ; CX has copy count, AX-CX fill count ; ; Set the GDT TSS limit and base address to the RAM values ; mov ax,gdt_alias ; Restore GDT addressing mov ds,ax mov es,ax mov di,cs:[bx].tss_sel ; Get TSS selector mov si,cs:[bx].tss_alias ; Get RAM alias selector movsw ; Copy limit movsw ; Copy low 16 bits of adress lodsw ; Get high 8 bits of address mov ah,dl ; Mark as TSS descriptor stosw ; Fill in high address and access bytes movsw ; Copy reserved word ; ; See if a valid LDT is specified for the startup task ; If so then copy the EPROM version into the RAM alias. ; mov ds,cs:[bx].tss_alias ; Address TSS to get LDT mov si,ds:word ptr LDT_OFFSET and si,not TIRPL_MASK ; Ignore TI and RPL jz no_ldt ; Skip this if no LDT used push si ; Save LDT selector lar dx,si ; Test descriptor jnz bad_ldt ; Jump if invalid selector mov dl,dh ; Save LDT descriptor access byte and dh,not DPL ; Ignore privilege cmp dh, DT_ACCESS ; Be sure it is an LDT descriptor jne bad_ldt ; Jump if invalid mov es:[si].access,DS_ACCESS ; Mark LDT as data segment mov ds,si ; Point DS at EPROM LDT lsl ax,si ; Get LDT limit call test_dt_limit ; Verify it is valid mov cx,ax ; Save for later ; ; Examine the LDT alias segment and, if good, copy to RAM ; mov si,cs:[bx].ldt_alias ; Get ldt alias selector mov es,si ; Point ES at alias segment lsl ax,si ; Get length of alias segmewnt call test_dt_limit ; Verify it is valid call copy_with_fill ; Copy LDT into RAM alias segment ; ; Set the LDT limit and base address to the RAM copy of the LDT. ; mov si,cs:[bx].ldt_alias ; Restore LDT alias selector pop di ; Restore LDT selector mov ax,gdt_alias ; Restore GDT addressing mov ds,ax mov es,ax movsw ; Move the RAM LDT limit movsw ; Move the low 16 bits across lodsw ; Get the high 8 bits mov ah,dl ; Set high address and access rights stosw ; Copy reserved word movsw no_ldt: ret ; All done bad_ldt: hit ; Halt here if LDT is invalid copy_tasks endp ; ; Test the descriptor table size in AX to verify that it is an ; even number of descriptors in length. ; test_dt_limit proc push ax ; Save length end al,7 ; Look at low order bits cmp al,7 ; Must be all ones pop ax ; Restore length jne bad_dt_limit; ret ; All OK bad_dt_limit: hit: ; Die! test_dt_limit endp ; ; Copy the EPROM DT at selector BX in the temporary GDT to the alias ; data segment at selector SI. Any improper descriptors or limits ; will cause shutdown! ; copy_EPROM_dt proc mov ax,ss ; Point ES:DI at temporary descriptor mov es,ax mov es:[bx].access,DS_ACCESS ; Mark descriptor as a data segment mov es:[bx].res,0 ; Clear reserved word lsl ax,bx ; Get limit of EPROM DT mov cx,ax ; Save for later call test_dt_limit ; Verify it is a proper limit mov di,gdt_desc-initial_gdt ; Address EPROM GDT in DS mov ds,di mov di,temp_desc-initial_gdt ; Get selector for temporary descriptor push di ; Save offset for later use as selector lodsw ; Get alias segment size call test_dt_limit ; Verify it is an even multiple of ; descriptors in length stosw ; Put length into temporary movsw ; Copy remaining entries into temporary movsw movsw pop es ; ES now points at the GDT alias area mov ds,bx ; DS now points at EPROM DT as data ; Copy segment ot alias with zero fill ; CX is copy count, AX-CX is fill count ; Fall into copy_with_fill copy_EPROM_dt endp ; ; Copy the segment at DS to the segment at ES for length CX. ; Fill th end with AX-CX zeros.s Use word operations for speed but ; allow odd byte operations. ; copy_with_fill proc xor si,si ; Start at beginning of segments xor di,di sub ax,cx ; Form fill count add cs,1 ; Convert laimit to count rcr cs,1 ; Allow full 64K move rep movsw ; Copy DT into alias area xchg ax,cx ; Get fill count and zero AX jnc even_copy ; Jump if even byte count on copy movsb ; Copy odd byte or cx,cx jz exit_copy ; Exit if no fill stosb ; Even out the segment offset dec cx ; Adjust remaining fill count even_copy: shr cx,1 ; Form word count on fill rep stosw ; Clear unused words at end jnc exit_copy ; Exit if no odd byte remains stosb ; Clear last odd byte exit_copy: ret copy_with_fill endp init_code ends end $B Appendix B The 80286 Instruction Set ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ This section presents the 80286 instruction set using Intel's ASM286 notation. All possible operand types are shown. Instructions are organized alphabetically according to generic operations. Within each operation, many different instructions are possible depending on the operand. The pages are presented in a standardized format, the elements of which are described in the following paragraphs. Opcode This column gives the complete object code produced for each form of the instruction. Where possible, the codes are given as hexadecimal bytes, presented in the order in which they will appear in memory. Several shorthand conventions are used for the parts of instructions which specify operands. These conventions are as follows: /n: (n is a digit from 0 through 7) A ModRM byte, plus a possible immediate and displacement field follow the opcode. See figure B-1 for the encoding of the fields. The digit n is the value of the REG field of the ModRM byte. To obtain the possible hexadecimal values for /n, refer to column n of table B-1. Each row gives a possible value for the effective address operand to the instruction. The entry at the end of the row indicates whether the effective address operand is a register or memory; if memory, the entry indicates what kind of indexing and/or displacement is used. Entries with D8 or D16 signify that a one-byte or two-byte displacement quantity immediately follows the ModRM and optional immediate field bytes. The signed displacement is added to the effective address offset. /r: A ModRM byte that contains both a register operand and an effective address operand, followed by a possible immediate and displacement field. See figure B-2 for the encoding of the fields. The ModRM byte could be any value appearing in table B-1. The column determines which register operand was selected; the row determines the form of effective address. If the row entry mentions D8 or D16, then a one-byte or two-byte displacement follows, as described in the previous paragraph. cb: A one-byte signed displacement in the range of -128 to +127 follows the opcode. The displacement is sign-extended to 16 bits, and added modulo 65536 to the offset of the instruction FOLLOWING this instruction to obtain the new IP value. cw: A two-byte displacement is added modulo 65536 to the offset of the instruction FOLLOWING this instruction to obtain the new IP value. cd: A two-word pointer which will be the new CS:IP value. The offset is given first, followed by the selector. db: An immediate byte operand to the instruction which follows the opcode and ModRM bytes. The opcode determines if it is a signed value. dw: An immediate word operand to the instruction which follows the opcode and ModRM bytes. All words are given in the 80286 with the low-order byte first. +rb: A register code from 0 through 7 which is added to the hexadecimal byte given at the left of the plus sign to form a single opcode byte. The codes are: AL=0, CL=1, DL=2, BL=3, AH=4, CH=5, DH=6, and BH=7. +rw: A register code from 0 through 7 which is added to the hexadecimal byte given at the left of the plus sign to form a single opcode byte. The codes are: AX=0, CX=1, DX=2, BX=3, SP=4, BP=5, SI=6, and DI=7. Table B-1. ModRM Values Rb = AL CL DL BL AH CH DH BH Rw = AX CX DX BX SP BP SI DI REG = 0 1 2 3 4 5 6 7 ModRM values Effective address 00 08 10 18 20 28 30 38 [BX + SI] 01 09 11 19 21 29 31 39 [BX + DI] 02 0A 12 1A 22 2A 32 3A [BP + SI] 03 0B 13 1B 23 2B 33 3B [BP + DI] mod=00 04 0C 14 1C 24 2C 34 3C [SI] 05 0D 15 1D 25 2D 35 3D [DI] 06 0E 16 1E 26 2E 36 3E D16 (simple var) 07 0F 17 1F 27 2F 37 3F [BX] 40 48 50 58 60 68 70 78 [BX + SI] + D8 D8 denotes an 8-bit displacement following the ModRM byte that is sign-extended and added to the index. 41 49 51 59 61 69 71 79 [BX + DI] + D8 42 4A 52 5A 62 6A 72 7A [BP + SI] + D8 43 4B 53 5B 63 6B 73 7B [BP + DI] + D8 mod=01 44 4C 54 5C 64 6C 74 7C [SI] + D8 45 4D 55 5D 65 6D 75 7D [DI] + D8 46 4E 56 5E 66 6E 76 7E [BP] + D8 Default segment register is SS for effective addresses containing a BP index; DS is for other memory effective addresses. 47 4F 57 5F 67 6F 77 7F [BX] + D8 80 88 90 98 A0 A8 B0 B8 [BX + SI] + D16 D16 denotes the 16-bit displacement following the ModRM byte that is added to the index. 81 89 91 99 A1 A9 B1 B9 [BX + DI] + D16 82 8A 92 9A A2 AA B2 BA [BP +SI] + D16 83 8B 93 9B A3 AB B3 BB [BP + DI] + D16 mod=10 84 8C 94 9C A4 AC B4 BC [SI] + D16 85 8D 95 9D A5 AD B5 BD [DI] + D16 86 8E 96 9E A6 AE B6 BE [BP] + D16 Default segment register is SS for effective addresses containing a BP index; DS is for other memory effective addresses. 87 8F 97 9F A7 AF B7 BF [BX] + D16 C0 C8 D0 D8 E0 E8 F0 F8 Ew=AX Eb=AL C1 C9 D1 D9 E1 E9 F1 F9 Ew=CX Eb=CL C2 CA D2 DA E2 EA F2 FA Ew=DX Eb=DL C3 CB D3 DB E3 EB F3 FB Ew=BX Eb=BL mod=11 C4 CC D4 DC E4 EC F4 FC Ew=SP Eb=AH C5 CD D5 DD E5 ED F5 FD Ew=BP Eb=CH C6 CE D6 DE E6 EE F6 FE Ew=SI Eb=DH C7 CF D7 DF E7 EF F7 FF Ew=DI Eb=BH Figure B-1. /n Instruction Byte Format pp/n Instruction Byte Format ‚ΠΠΠΠΠΠƒ € mod n  r/m  imm. low Opcode indicates presence and size of immediate field.  imm. high Opcode indicates presence and size of immediate field.  disp-low  disp-high € „€€€€€€… 7 6 5 4 3 2 1 0 7 0 7 0 7 0 7 0 "mod" Field Bit Assignments ‚Πƒ € mod  Displacement € †Ο‡ € 00 DISP = 0 Except if mod = 00 and r/m = 110 then EA = disp-high:disp-low., disp-low and disp-high are absent € € 01 DISP = disp-low sign-extended to 16-bit, disp-high is absent € € 10 DISP = disp-high: disp-low € € 11 r/m is treated as a "reg" field € „€… "r/m" Field Bit Assignments ‚Πƒ € r/m  Operand Address € †Ο‡ € 000  (BX) + (SI) + DISP € € 001  (BX) + (DI) + DISP € € 010  (BP) + (SI) + DISP € € 011  (BP) + (DI) + DISP € € 100  (SI) + DISP € € 101  (DI) + DISP € € 110  (BP) + DISP Except if mod = 00 and r/m = 110 then EA = disp-high:disp-low. € € 111  (BX) + DISP € „€… DISP follows 2nd byte of instruction (before data if required). Figure B-2. /r Instruction Byte Format /r Instruction Byte Format ‚ΠΠΠΠΠΠƒ € mod r  r/m  imm. low Opcode indicates presence and size of immediate field.  imm. high Opcode indicates presence and size of immediate field.  disp-low  disp-high € „€€€€€€… 7 6 5 4 3 2 1 0 7 0 7 0 7 0 7 0 "mod" Field Bit Assignments ‚Πƒ € mod  Displacement € †Ο‡ € 00 DISP = 0 Except if mod = 00 and r/m = 110 then EA = disp-high:disp-low., disp-low and disp-high are absent € € 01 DISP = disp-low sign-extended to 16-bit, disp-high is absent € € 10 DISP = disp-high: disp-low € € 11 r/m is treated as a "reg" field € „€… "r" Field Bit Assignments ‚ΠΠƒ € 16-Bit (w = 1)  6-Bit (w = 0)  Segment € †ΟΟ‡ € 000 AX  000 AL  00 ES € € 001 CX  001 CL  01 CS € € 010 DX  010 DL  10 SS € € 011 BX  011 BL  11 DS € € 100 SP  100 AH  € € 101 BP  101 CH  € € 110 SI  110 DH  € € 111 DI  111 BH  € „€€… "r/m" Field Bit Assignments ‚Πƒ € r/m  Operand Address € †Ο‡ € 000  (BX) + (SI) + DISP € € 001  (BX) + (DI) + DISP € € 010  (BP) + (SI) + DISP € € 011  (BP) + (DI) + DISP € € 100  (SI) + DISP € € 101  (DI) + DISP € € 110  (BP) + DISP Except if mod = 00 and r/m = 110 then EA = disp-high:disp-low. € € 111  (BX) + DISP € „€… DISP follows 2nd byte of instruction (before data if required). Instruction This column gives the instruction mnemonic and possible operands. The type of operand used will determine the opcode and operand encodings. The following entries list the type of operand which can be encoded in the format shown in the instruction column. The Intel convention is to place the destination operand as the left hand operand. Source-only operands follow the destination operand. In many cases, the same instruction can be encoded several ways. It is recommended that you use the shortest encoding. The short encodings are provided to save memory space. cb: a destination instruction offset in the range of 128 bytes before the end of this instruction to 127 bytes after the end of this instruction. cw: a destination offset within the same code segment as this instruction. Some instructions allow a short form of destination offset. See cb type for more information. cd: a destination address, typically in a different code segment from this instruction. Using the cd: address form with call instructions saves the code segment selector. db: a signed value between -128 and +127 inclusive which is an operand of the instruction. For instructions in which the db is to be combined in some way with a word operand, the immediate value is sign-extended to form a word. The upper byte of the word is filled with the topmost bit of the immediate value. dw: an immediate word value which is an operand of the instruction. eb: a byte-sized operand. This is either a byte register or a (possibly indexed) byte memory variable. Either operand location may be encoded in the ModRM field. Any memory addressing mode may be used. ed: a memory-based pointer operand. Any memory addressing mode may be used. Use of a register addressing mode will cause exception 6. ew: a word-sized operand. This is either a word register or a (possibly indexed) word memory variable. Either operand location may be encoded in the ModRM field. Any memory addressing mode may be used. m: a memory location. Operands in registers do not have a memory address. Any memory addressing mode may be used. Use of a register addressing mode will cause exception 6. mb: a memory-based byte-sized operand. Any memory addressing mode may be used. mw: a memory-based word operand. Any memory addressing mode may be used. rb: one of the byte registers AL, CL, DL, BL, AH, CH, DH, or BH; rb has the value 0,1,2,3,4,5,6, and 7, respectively. rw: one of the word registers AX, CX, DX, BX, SP, BP, SI, or DI; rw has the value 0,1,2,3,4,5,6, and 7, respectively. xb: a simple byte memory variable without a base or index register. MOV instructions between AL and memory have this optimized form if no indexing is required. xw: a simple word memory variable without a base or index register. MOV instructions between AX and memory have this optimized form if no indexing is required. Clocks This column gives the number of clock cycles that this form of the instruction takes to execute. The amount of time for each clock cycle is computed by dividing one microsecond by the number of MHz at which the 80286 is running. For example, a 10-MHz 80286 (with the CLK pin connected to a 20-MHz crystal) takes 100 nanoseconds for each clock cycle. Add one clock to instructions that use the base plus index plus displacement form of addressing. Add two clocks for each 16-bit memory based operand reference located on an odd physical address. Add one clock for each wait state added to each memory read. Wait states inserted in memory writes or instruction fetches do not necessarily increase execution time. The clock counts establish the maximum execution rate of the 80286. With no delays in bus cycles, the actual clock count of an 80286 program will average 5-10% more than the calculated clock count due to instruction sequences that execute faster than they can be fetched from memory. Some instruction forms give two clock counts, one unlabelled and one labelled. These counts indicate that the instruction has two different clock times for two different circumstances. Following are the circumstances for each possible label: mem: The instruction has an operand that can either be a register or a memory variable. The unlabelled time is for the register; the mem time is for the memory variable. Also, one additional clock cycle is taken for indexed memory variables for which all three possible indices (base register, index register, and displacement) must be added. noj: The instruction involves a conditional jump or interrupt. The unlabelled time holds when the jump is made; the noj time holds when the jump is not made. pm: If the instruction takes more time to execute when the 80286 is in Protected Mode. The unlabelled time is for Real Address Mode; the pm time is for Protected Mode. Description This is a concise description of the operation performed for this form of the instruction. More details are given in the "Operation" section that appears later in this chapter. Flags Modified This is a list of the flags that are set to a meaningful value by the instruction. If a flag is always set to the same value by the instruction, the value is given ("=0" or "=1") after the flag name. Flags Undefined This is a list of the flags that have an undefined (meaningless) setting after the instruction is executed. All flags not mentioned under "Flags Modified" or "Flags Undefined" are unchanged by the instruction. Operation This section fully describes the operation performed by the instruction. For some of the more complicated instructions, suggested usage is also indicated. Protected Mode Exceptions The possible exceptions involved with this instruction when running under the 80286 Protected Mode are listed below. These exceptions are abbreviated with a pound sign (#) followed by two capital letters and an optional error code in parenthesis. For example, #GP(0) denotes the general protection exception with an error code of zero. The next section describes all of the 80286 exceptions and the machine state upon entry to the exception. If you are an applications programmer, consult the documentation provided with your operating system to determine what actions are taken by the system when exceptions occur. Real Address Mode Exceptions Since less error checking is performed by the 80286 when it is in Real Address Mode, there are fewer exceptions in this mode. One exception that is possible in many instructions is #GP(0). Exception 13 is generated whenever a word operand is accessed from effective address 0FFFFH in a segment. This happens because the second byte of the word is considered located at location 10000H, not at location 0, and thus exceeds the segment's addressability limit. Protection Exceptions In parallel with the execution of instructions, the protected-mode 80286 checks all memory references for validity of addressing and type of access. Violation of the memory protection rules built into the processor will cause a transfer of program control to one of the interrupt procedures described in this section. The interrupts have dedicated positions within the Interrupt Descriptor Table, which is shown in table B-2. The interrupts are referenced within the instruction set pages by a pound sign (#) followed by a two-letter mnemonic and the optional error code in parenthesis. Table B-2. Protection Exceptions of the 80286 Abbreviation Interrupt Number Description #UD 6 Undefined Opcode #NM 7 No Math Unit Available #DF 8 Double Fault #MP 9 Math Unit Protection Fault #TS 10 Invalid Task State Segment #NP 11 Not Present #SS 12 Stack Fault #GP 13 General Protection #MF 16 Math Fault Error Codes Some exceptions cause the 80286 to pass a 16-bit error code to the interrupt procedure. When this happens, the error code is the last item pushed onto the stack before control is tranferred to the interrupt procedure. If stacks were switched as a result of the interrupt (causing a privilege change or task switch), the error code appears on the interrupt procedure's stack, not on the stack of the task that was interrupted. The error code generally contains the selector of the segment that caused the protection violation. The RPL field (bottom two bits) of the error code does not, however, contain the privilege level. Instead, it contains the following information: Ž Bit 0 contains the value 1 if the exception was detected during an interrupt caused by an event external to the program (i.e., an external interrupt, a single step, a processor extension not-present exception, or a processor extension segment overrun). Bit 0 is 0 if the exception was detected while processing the regular instruction stream, even if the instruction stream is part of an external interrupt handling procedure or task. If bit 0 is set, the instruction pointed to by the saved CS:IP address is not responsible for the error. The current task can be restarted unless this is exception 9. Ž Bit 1 is 1 if the selector points to the Interrupt Descriptor Table. In this case, bit 2 can be ignored, and bits 3-10 contain the index into the IDT. Ž Bit 1 is 0 if the selector points to the Global or Local Descriptor Tables. In this case, bits 2-15 have their usual selector interpretation: bit 2 selects the table (1=Local, 0=Global), and bits 3-15 are the index into the table. In some cases the 80286 chooses to pass an error code with no information in it. In these cases, all 16 bits of the error code are zero. The existence and type of error codes are described under each of the following individual exceptions. #DF 8 Double Fault (Zero Error Code) This exception is generated when a second exception is detected while the processor is attempting to transfer control to the handler for an exception. For instance, it is generated if the code segment containing the exception handler is marked not present. It is also generated if invoking the exception handler causes a stack overflow. This exception is not generated during the execution of an exeception handler. Faults detected within the instruction stream are handled by regular exceptions. The error code is normally zero. The saved CS:IP will point at the instruction that was attempting to execute when the double fault occurred. Since the error code is normally zero, no information on the source of the exception is available. Restart is not possible. The "double fault" exception does not occur when detecting a new exception while trying to invoke handlers for the following exceptions: 1, 2, 3, 4, 5, 6, 7, 9, and 16. If another exception is detected while attempting to perform the double fault exception, the 80286 will enter shutdown (see section 11.5). #GP 13 General Protection (Selector or Zero Error Code) This exception is generated for all protection violations not covered by the other exceptions in this section. Examples of this include: 1. An attempt to address a memory location by using an offset that exceeds the limit for the segment involved. 2. An attempt to jump to a data segment. 3. An attempt to load SS with a selector for a read-only segment. 4. An attempt to write to a read-only segment. 5. Exceeding the maximum instruction length of 10 bytes. If #GP occurred while loading a descriptor, the error code passed contains the selector involved. Otherwise, the error code is zero. If the error code is not zero, the instruction can be restarted if the erroneous condition is rectified. If the error code is zero either a limit violation, a write protect violation, or an illegal use of invalid segment register occurred. An invalid segment register contains the values 0-3. A write protect fault on ADC, SBB, RCL, RCR, or XCHG is not restartable. #MF 16 Math Fault (No Error Code) This exception is generated when the numeric processor extension (the 80287) detects an error signalled by the ERROR input pin leading from the 80287 to the 80286. The ERROR pin is tested at the beginning of most floating point instructions, and when a WAIT instruction is executed with the EM bit of the Machine Status Word set to 0 (i.e., no emulation of the math unit). The floating point instructions that do not cause the ERROR pin to be tested are FNCLEX, FNINIT, FSETPM, FNSTCW, FNSTSW, FNSAVE, and FNSTENV. If the handler corrects the error condition causing the exception, the floating point instruction that caused #MF can be restarted. This is not accomplished by IRET, however, since the fault occurs at the floating point instruction that follows the offending instruction. Before restarting the numeric instruction, the handler must obtain from the 80287 the address of the offending instruction and the address of the optional numeric operand. #MP 9 Math Unit Protection Fault (No Error Code) This exception is generated if the numeric operand is larger than one word and has the second or subsequent words outside the segment's limit. Not all math addressing errors cause exception 9. If the effective address of an ESCAPE instruction is not in the segment's limit, or if a write is attempted on a read-only segment, or if a one-word operand violates a segment limit, exception 13 will occur. The #MP exception occurs during the execution of the numeric instruction by the 80287. Thus, the 80286 may be in an unrelated instruction stream at the time. Exception 9 may occur in a task unrelated to the task that executed the ESC instruction. The operating system should keep track of which task last used the NPX (see section 11.4). The offending floating point instruction cannot be restarted; the task which attempted to execute the offending numeric instruction must be aborted. However, if exception 9 interrupted another task, the interrupted task may be restarted. The exception 9 handler must execute FNINIT before executing any ESCAPE or WAIT instruction. #NM 7 No Math Unit Available (No Error Code) This exception occurs when any floating point instruction is executed while the EM bit or the TS bit of the Machine Status Word is 1. It also occurs when a WAIT instruction is encountered and both the MP and TS bits of the Machine Status Word are 1. Depending on the setting of the MSW bits that caused this exception, the exception handler could provide emulation of the 80287, or it could perform a context switch of the math processor to prepare it for use by another task. The instruction causing #NM can be restarted if the handler performs a numeric context switch. If the handler provided emulation of the math unit, it should advance the return pointer beyond the floating point instruction that caused NM. #NP 11 Not Present (Selector Error Code) This exception occurs when CS, DS, ES, or the Task Register is loaded with a descriptor that is marked not present but is otherwise valid. It can occur in an LLDT instruction, but the #NP exception will not occur if the processor attempts to load the LDT register during a task switch. A not-present LDT encountered during a task switch causes the #TS exception. The error code passed is the selector of the descriptor that is marked not present. Typically, the Not Present exception handler is used to implement a virtual memory system. The operating system can swap inactive memory segments to a mass-storage device such as a disk. Applications programs need not be told about this; the next time they attempt to access the swapped-out memory segment, the Not Present handler will be invoked, the segment will be brought back into memory, and the offending instruction within the applications program will be restarted. If #NP is detected on loading CS, DS, or ES in a task switch, the exception occurs in the new task, and the IRET from the exception handler jumps directly to the next instruction in the new task. The Not Present exception handler must contain special code to complete the loading of segment registers when #NP is detected in loading the CS or DS registers in a task switch and a trap or interrupt gate was used. The DS and ES registers have been loaded but their descriptors have not been loaded. Any memory reference using the segment register may cause exception 13. The #NP exception handler should execute code such as the following to ensure full loading of the segment registers: MOV AX,DS MOV DS,AX MOV AX,ES MOV ES,AX #SS 12 Stack Fault (Selector or Zero Error Code) This exception is generated when a limit violation is detected in addressing through the SS register. It can occur on stack-oriented instructions such as PUSH or POP, as well as other types of memory references using SS such as MOV AX,[BP+28]. It also can occur on an ENTER instruction when there is not enough space on the stack for the indicated local variable space, even if the stack exception is not triggered by pushing BP or copying the display stack. A stack exception can therefore indicate a stack overflow, a stack underflow or a wild offset. The error code will be zero. #SS is also generated on an attempt to load SS with a descriptor that is marked not present but is otherwise valid. This can occur in a task switch, an inter-level call, an inter-level return, a move to the SS instruction or a pop to the SS instruction. The error code will be non-zero. #SS is never generated when addressing through the DS or ES registers even if the offending register points to the same segment as the SS register. The #SS exception handler must contain special code to complete the loading of segment registers. The DS and ES registers will not be fully loaded if a not-present condition is detected while loading the SS register. Therefore, the #SS exception handler should execute code such as the following to insure full loading of the segment registers: MOV AX,DS MOV DS,AX MOV AX,ES MOV ES,AX Generally, the instruction causing #SS can be restarted, but there is one special case when it cannot: when a PUSHA or POPA instruction attempts to wrap around the 64K boundary of a stack segment. This condition is identified by the value of the saved SP, which can be either 0000H, 0001H, 0FFFEH, or 0FFFFH. #TS 10 Invalid Task State Segment (Selector Error Code) This exception is generated during a task switch when the new task state segment is invalid, that is, when a task state segment is too small; when the LDT indicated in a TSS is invalid or not present; when the SS, CS, DS, or ES indicated in a TSS are invalid (task switch); when the back link in a TSS is invalid (inter-task IRET). #TS is not generated when the SS, CS, DS, or ES back link or privileged stack selectors point to a descriptor that is not present but otherwise is valid. #NP is generated in these cases. The error code passed to the exception handler contains the selector of the offending segment, which can either be the Task State Segment itself, or a selector found within the Task State Segment. The instruction causing #TS can be restarted. #TS must be handled through a task gate. The exception handler must reset the busy bit in the new TSS. #UD 6 Undefined Opcode (No Error Code) This exception is generated when an invalid operation code is detected in the instruction stream. Following are the cases in which #UD can occur: 1. The first byte of an instruction is completely invalid (e.g., 64H). 2. The first byte indicates a 2-byte opcode and the second byte is invalid (e.g., 0FH followed by 0FFH). 3. An invalid register is used with an otherwise valid opcode (e.g., MOV CS,AX). 4. An invalid opcode extension is given in the REG field of the ModRM byte (e.g., 0F6H /1). 5. A register operand is given in an instruction that requires a memory operand (e.g., LGDT AX). Since the offending opcode will always be invalid, it cannot be restarted. However, the #UD handler might be coded to implement an extension of the 80286 instruction set. In that case, the handler could advance the return pointer beyond the extended instruction and return control to the program after the extended instruction is emulated. Any such extensions may be incompatible with the 80386. Privilege Level and Task Switching on the 80286 The 80286 supports many of the functions necessary to implement a protected, multi-tasking operating system in hardware. This support is provided not by additional instructions, but by extension of the semantics of 8086/8088 instructions that change the value of CS:IP. Whenever the 80286 performs an inter-segment jump, call, interrupt, or return, it consults the Access Rights (AR) byte found in the descriptor table entry of the selector associated with the new CS value. The AR byte determines whether the long jump being made is through a gate, or is a task switch, or is a simple long jump to the same privilege level. Table B-3 lists the possible values of the AR byte. The "privilege" headings at the top of the table give the Descriptor Privilege Level, which is referred to as the DPL within the instruction descriptions. Each of the CALL, INT, IRET, JMP, and RET instructions contains on its instruction set pages a listing of the access rights checking and actions taken to implement the instruction. Instructions involving task switches contain the symbol SWITCH_TASKS, which is an abbreviation for the following list of checks and actions: SWITCH_TASKS: Locked set AR byte of new TSS descriptor to Busy TSS (Bit 1 = 1) Current TSS cache must be valid with limit  41 else #TS (error code will be new TSS, but back link points at old TSS) Save machine state in current TSS If nesting tasks, set the new TSS link to the current TSS selector Any exception will be in new context Else set the AR byte of current TSS descriptor to Available TSS (Bit 1 = 0) Set the current TR to selector, base and limit of new TSS New TSS limit  43 else #TS (new TSS) Set all machine registers to values from new TSS without loading descriptors for DS, ES, CS, SS, LDT Clear valid flags for LDT, SS, CS, DS, ES (not valid yet) If nesting tasks, set the Nested Task flag to 1 Set the Task Switched flag to 1 LDT from the new TSS must be within GDT talbe limits else #TS(LDT) AR byte from LDT descriptor must specifiy LDT segment else #TS(LDT) AR byte from LDT descriptor must indicate PRESENT else #TS(LDT) Load LDT cache with new LDT descriptor and set valid bit Set CPL to the RPL of the CS selector in the new TSS If new stack selector is null #TS(SS) SS selector must be within its descriptor table limits else #TS(SS) SS selector RPL must be equal to CPL else #TS(SS) DPL of SS descriptor must equal to CPL else #TS(SS) SS descriptor AR byte must indicate writable data segment else #TS(SS) SS descriptor AR byte must indicate PRESENT else #TS(SS) Load SS cache with new stack segment and set valid bit New CS selector must not be null else #TS(SS) CS selector must be within its descriptor table limits else #TS(SS) CS descriptor AR byte must indicate code segment else #TS(SS) If non-conforming then DPL must equal CPL else #TS(SS) If conforming then DPL must be Ύ CPL else #TS(SS) CS descriptor AR byte must indicate PRESENT else #TS(SS) Load CS cache with new code segment descriptor and set valid bit For DS and ES: If new selector is not null then perform following checks: Index must be within its descriptor table limits else #TS(segment selector) AR byte must indicate data or readable code else #TS(segment selector) If data or non-conforming code then: DPL must be  CPL else #TS(SS) DPL must be  RPL else #TS(SS) AR byte must indicate PRESENT else #TS(SS) Load cache with new segment descriptor and set valid bit Table B-3. Hexadecimal Values for the Access Rights Byte Not present, Present, Descriptor Type privilege= privilege= 0 1 2 3 0 1 2 3 00 20 40 60 80 A0 C0 E0 Illegal 01 21 41 61 81 A1 C1 E1 Available Task State Segment 02 22 42 62 82 A2 C2 E2 Local Descriptor Table Segment 03 23 43 63 83 A3 C3 E3 Busy Task State Segment 04 24 44 64 84 A4 C4 E4 Call Gate 05 25 45 65 85 A5 C5 E5 Task Gate 06 26 46 66 86 A6 C6 E6 Interrupt Gate 07 27 47 67 87 A7 C7 E7 Trap Gate 08 28 48 68 88 A8 C8 E8 Illegal 09 29 49 69 89 A9 C9 E9 Illegal 0A 2A 4A 6A 8A AA CA EA Illegal 0B 2B 4B 6B 8B AB CB EB Illegal 0C 2C 4C 6C 8C AC CC EC Illegal 0D 2D 4D 6D 8D AD CD ED Illegal 0E 2E 4E 6E 8E AE CE EE Illegal 0F 2F 4F 6F 8F AF CF EF Illegal 10 30 50 70 90 B0 D0 F0 Expand-up, read only, ignored Data Segment 11 31 51 71 91 B1 D1 F1 Expand-up, read only, accessed Data Segment 12 32 52 72 92 B2 D2 F2 Expand-up, writable, ignored Data Segment 13 33 53 73 93 B3 D3 F3 Expand-up, writable, accessed Data Segment 14 34 54 74 94 B4 D4 F4 Expand-down, read only, ignored Data Segment 15 35 55 75 95 B5 D5 F5 Expand-down, read only, accessed Data Segment 16 36 56 76 96 B6 D6 F6 Expand-down, writable, ignored Data Segment 17 37 57 77 97 B7 D7 F7 Expand-down, writable, accessed Data Segment 18 38 58 78 98 B8 D8 F8 Non-conform, no read, ignored Code Segment 19 39 59 79 99 B9 D9 F9 Non-conform, no read, accessed Code Segment 1A 3A 5A 7A 9A BA DA FA Non-conform, readable, ignored Code Segment 1B 3B 5B 7B 9B BB DB FB Non-conform, readable, accessed Code Segment 1C 3C 5C 7C 9C BC DC FC Conforming, no read, ignored Code Segment 1D 3D 5D 7D 9D BD DD FD Conforming, no read, accessed Code Segment 1E 3E 5E 7E 9E BE DE FE Conforming, readable, ignored Code Segment 1F 3F 5F 7F 9F BF DF FF Conforming, readable, accessed Code Segment AAA‘‘ASCII Adjust AL After Addition Opcode Instruction Clocks Description 37 AAA 3 ASCII adjust AL after addition Flags Mofified Auxiliary carry, carry Flags Undefined Overflow, sign, zero, parity Operation AAA should be executed only after an ADD instruction which leaves a byte result in the AL register. The lower nibbles of the operands to the ADD instruction should be in the range 0 through 9 (BCD digits). In this case, the AAA instruction will adjust AL to contain the correct decimal digit result. If the addition produced a decimal carry, the AH register is incremented, and the carry and auxiliary carry flags are set to 1. If there was no decimal carry, the carry and auxiliary carry flags are set to 0, and AH is unchanged. In any case, AL is left with its top nibble set to 0. To convert AL to an ASCII result, you can follow the AAA instruction with OR AL,30H. The precise definition of AAA is as follows: if the lower 4 bits of AL are greater than nine, or if the auxiliary carry flag is 1, then increment AL by 6, AH by 1, and set the carry and auxiliary carry flags. Otherwise, reset the carry and auxiliary carry flags. In any case, conclude the AAA operation by setting the upper four bits of AL to zero. Protected Mode Exceptions None Real Address Mode Exceptions None AAD‘‘ASCII Adjust AX Before Division Opcode Instruction Clocks Description D5 0A AAD 14 ASCII adjust AX before division Flags Modified Sign, zero, parity Flags Undefined Overflow, auxiliary carry, carry Operation AAD is used to prepare two unpacked BCD digits (least significant in AL, most significant in AH) for a division operation which will yield an unpacked result. This is accomplished by setting AL to AL + (10 * AH), and then setting AH to 0. This leaves AX equal to the binary equivalent of the original unpacked 2-digit number. Protected Mode Exceptions None Real Address Mode Exceptions None AAM‘‘ASCII Adjust AX After Multiply Opcode Instruction Clocks Description D4 0A AAM 16 ASCII adjust AX after multiply Flags Modified Sign, zero, parity Flags Undefined Overflow, auxiliary carry, carry Operation AAM should be used only after executing a MUL instruction between two unpacked BCD digits, leaving the result in the AX register. Since the result is less than one hundred, it is contained entirely in the AL register. AAM unpacks the AL result by dividing AL by ten, leaving the quotient (most significant digit) in AH, and the remainder (least significant digit) in AL. Protected Mode Exceptions None Real Address Mode Exceptions None AAS‘‘ASCII Adjust AL After Subtraction Opcode Instruction Clocks Description 3F AAS 3 ASCII adjust AL after subtraction Flags Modified Auxiliary carry, carry Flags Undefined Overflow, sign, zero, parity Operation AAS should be executed only after a subtraction instruction which left the byte result in the AL register. The lower nibbles of the operands to the SUB instruction should have been in the range 0 through 9 (BCD digits). In this case, the AAS instruction will adjust AL to contain the correct decimal digit result. If the subtraction produced a decimal carry, the AH register is decremented, and the carry and auxiliary carry flags are set to 1. If there was no decimal carry, the carry and auxiliary carry flags are set to 0, and AH is unchanged. In any case, AL is left with its top nibble set to 0. To convert AL to an ASCII result, you can follow the AAS instruction with OR AL,30H. The precise definition of AAS is as follows: if the lower four bits of AL are greater than 9, or if the auxiliary carry flag is 1, then decrement AL by 6, AH by 1, and set the carry and auxiliary carry flags. Otherwise, reset the carry and auxiliary carry flags. In any case, conclude the AAS operation by setting the upper four bits of AL to zero. Protected Mode Exceptions None Real Address Mode Exceptions None ADC/ADD‘‘Integer Addition Opcode Instruction Clocks Description 10 /r ADC eb,rb 2,mem=7 Add with carry byte register into EA byte 11 /r ADC ew,rw 2,mem=7 Add with carry word register into EA word 12 /r ADC rb,eb 2,mem=7 Add with carry EA byte into byte register 13 /r ADC rw,ew 2,mem=7 Add with carry EA word into word register 14 db ADC AL,db 3 Add with carry immediate byte into AL 15 dw ADC AX,dw 3 Add with carry immediate word into AX 80 /2 db ADC eb,db 3,mem=7 Add with carry immediate byte into EA byte 81 /2 dw ADC ew,dw 3,mem=7 Add with carry immediate word into EA word 83 /2 db ADC ew,db 3,mem=7 Add with carry immediate byte into EA word 00 /r ADD eb,rb 2,mem=7 Add byte register into EA byte 01 /r ADD ew,rw 2,mem=7 Add word register into EA word 02 /r ADD rb,eb 2,mem=7 Add EA byte into byte register 03 /r ADD rw,ew 2,mem=7 Add EA word into word register 04 db ADD AL,db 3 Add immediate byte into AL 05 dw ADD AX,dw 3 Add immediate word into AX 80 /0 db ADD eb,db 3,mem=7 Add immediate byte into EA byte 81 /0 dw ADD ew,dw 3,mem=7 Add immediate word into EA word 83 /0 db ADD ew,db 3,mem=7 Add immediate byte into EA word Flags Modified Overflow, sign, zero, auxiliary carry, parity, carry Flags Undefined None Operation ADD and ADC perform an integer addition on the two operands. The ADC instruction also adds in the initial state of the carry flag. The result of the addition goes to the first operand. ADC is usually executed as part of a multi-byte or multi-word addition operation. When a byte immediate value is added to a word operand, the immediate value is first sign-extended. Protected Mode Exceptions #GP(0) if the result is in a non-writable segment. #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 13 for a word operand at offset 0FFFFH. AND‘‘Logical AND Opcode Instruction Clocks Description 20 /r AND eb,rb 2,mem=7 Logical-AND byte register into EA byte 21 /r AND ew,rw 2,mem=7 Logical-AND word register into EA word 22 /r AND rb,eb 2,mem=7 Logical-AND EA byte into byte register 23 /r AND rw,ew 2,mem=7 Logical-AND EA word into word register 24 db AND AL,db 3 Logical-AND immediate byte into AL 25 dw AND AX,dw 3 Logical-AND immediate word into AX 80 /4 db AND eb,db 3,mem=7 Logical-AND immediate byte into EA byte 81 /4 dw AND ew,dw 3,mem=7 Logical-AND immediate word into EA word Flags Modified Overflow=0, sign, zero, parity, carry=0 Flags Undefined Auxiliary carry Operation Each bit of the result is a 1 if both corresponding bits of the operands were 1; it is 0 otherwise. Protected Mode Exceptions #GP(0) if the result is in a non-writable segment. #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 13 for a word operand at offset 0FFFFH. ARPL‘‘Adjust RPL Field of Selector Opcode Instruction Clocks Description 63 /r ARPL ew,rw 10,mem=11 Adjust RPL of EA word not less than RPL of rw Flags Modified Zero Flags Undefined None Operation The ARPL instruction has two operands. The first operand is a 16-bit memory variable or word register that contains the value of a selector. The second operand is a word register. If the RPL field (bottom two bits) of the first operand is less than the RPL field of the second operand, then the zero flag is set to 1 and the RPL field of the first operand is increased to match the second RPL. Otherwise, the zero flag is set to 0 and no change is made to the first operand. ARPL appears in operating systems software, not in applications programs. It is used to guarantee that a selector parameter to a subroutine does not request more privilege than the caller was entitled to. The second operand used by ARPL would normally be a register that contains the CS selector value of the caller. Protected Mode Exceptions #GP(0) if the result is in a non-writable segment. #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 6. ARPL is not recognized in Real Address mode. BOUND‘‘Check Array Index Against Bounds Opcode Instruction Clocks Description 62 /r BOUND rw,md noj=13 INT 5 if rw not within bounds Flags Modified None Flags Undefined None Operation BOUND is used to ensure that a signed array index is within the limits defined by a two-word block of memory. The first operand (a register) must be greater than or equal to the first word in memory, and less than or equal to the second word in memory. If the register is not within the bounds, an INTERRUPT 5 occurs. The two-word block might typically be found just before the array itself and therefore would be accessible at a constant offset of -4 from the array, simplifying the addressing. Protected Mode Exceptions INTERRUPT 5 if the bounds test fails, as described above. #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. The second operand must be a memory operand, not a register. If the BOUND instruction is executed with a ModRM byte representing a register second operand, then fault #UD will occur. Real Address Mode Exceptions INTERRUPT 5 if the bounds test fails, as described above. Interrupt 13 for a second operand at offset 0FFFDH or higher. Interrupt 6 if the second operand is a register, as described in the paragraph above. CALL‘‘Call Procedure Opcode Instruction Clocks Add one clock for each byte in the next instruction executed. Description E8 cw CALL cw 7 Call near, offset relative to next instruction FF /2 CALL ew 7,mem=11 Call near, offset absolute at EA word 9A cd CALL cd 13,pm=26 Call inter-segment, immediate 4-byte address 9A cd CALL cd 41 Call gate, same privilege 9A cd CALL cd 82 Call gate, more privilege, no parameters 9A cd CALL cd 86+4X Call gate, more privilege, X parameters 9A cd CALL cd 177 Call via Task State Segment 9A cd CALL cd 182 Call via task gate FF /3 CALL ed 16,mem=29 Call inter-segment, address at EA doubleword FF /3 CALL ed 44 Call gate, same privilege FF /3 CALL ed 83 Call gate, more privilege, no parameters FF /3 CALL ed 90+4X Call gate, more privilege, X parameters FF /3 CALL ed 180 Call via Task State Segment FF /3 CALL ed 185 Call via task gate Flags Modified None, except when a task switch occurs Flags Undefined None Operation The CALL instruction causes the procedure named in the operand to be executed. When the procedure is complete (a return instruction is executed within the procedure), execution continues at the instruction that follows the CALL instruction. The CALL cw form of the instruction adds modulo 65536 (the 2-byte operand) to the offset of the instruction following the CALL and sets IP to the resulting offset. The 2-byte offset of the instruction that follows the CALL is pushed onto the stack. It will be popped by a near RET instruction within the procedure. The CS register is not changed by this form. The CALL ew form of the instruction is the same as CALL cw except that the operand specifies a memory location from which the absolute 2-byte offset for the procedure is fetched. The CALL cd form of the instruction uses the 4-byte operand as a pointer to the procedure called. The CALL ed form fetches the long pointer from the memory location specified. Both long pointer forms consult the AR byte in the descriptor indexed by the selector part of the long pointer. The AR byte can indicate one of the following descriptor types: 1. Code Segment‘‘The access rights are checked, the return pointer is pushed onto the stack, and the procedure is jumped to. 2. Call Gate‘‘The offset part of the pointer is ignored. Instead, the entire address of the procedure is taken from the call gate descriptor entry. If the routine being entered is more privileged, then a new stack (both SS and SP) is loaded from the task state segment for the new privilege level, and parameters determined by the wordcount field of the call gate are copied from the old stack to the new stack. 3. Task Gate‘‘The current task's context is saved in its Task State Segment (TSS), and the TSS named in the task-gate is used to load the new context. The selector for the outgoing task (from TR) is stored into the new TSS's link field, and the new task's Nested Task flag is set. The outgoing task is left marked busy, the new TSS is marked busy, and execution resumes at the point at which the new task was last suspended. 4. Task State Segment‘‘The current task is suspended and the new task initiated as in 3 above except that there is no intervening gate. For long calls involving no task switch, the return link is the pointer of the instruction that follows the CALL, i.e., the caller's CS and updated IP. Task switches invoked by CALLs are linked by storing the outgoing task's TSS selector in the incoming TSS's link field and setting the Nested Task flag in the new task. Nested tasks must be terminated by an IRET. IRET releases the nested task and follows the back link to the calling task if the NT flag is set. A precise list of the protection checks made and the actions taken is given by the following list: CALL FAR: If indirect then check access of EA doubleword #GP(0) if limit violation New CS selector must not be null else #GP(0) Check that new CS selector index is within its descriptor table limits; else #GP (new CS selector) Examine AR byte of selected descriptor for various legal values: CALL CONFORMING CODE SEGMENT: DPL must be Ύ CPL else #GP (code segment selector) Segment must be PRESENT else #NP (code segment selector) Stack must be big enough for return address else #SS(0) IP must be in code segment limit else #GP(0) Load code segment descriptor into CS cache Load CS with new code segment selector Load IP with new offset CALL NONCONFORMING CODE SEGMENT: RPL must be Ύ CPL else #GP (code segment selector) DPL must be = CPL else #GP (code segment selector) Segment must be PRESENT else #NP (code segment selector) Stack must be big enough for return address else #SS(0) IP must be in code segment limit else #GP(0) Load code segment descriptor into CS cache Load CS with new code segment selector Set RPL of CS to CPL Load IP with new offset CALL TO CALL GATE: Call gate DPL must be  CPL else #GP (call gate selector) Call gate DPL must be  RPL else #GP (call gate selector) Call gate must be PRESENT else #NP (call gate selector) Examine code segment selector in call gate descriptor: Selector must not be null else #GP(0) Selector must be within its descriptor table limits else #GP (code segment selector) AR byte of selected descriptor must indicate code segment else #GP (code segment selector) DPL of selected descriptor must be Ύ CPL else #GP(code segment selector) If non-conforming code segment and DPL < CPL then CALL GATE TO MORE PRIVILEGE: Get new SS selector for new privilege level from TSS Check selector and descriptor for new SS: Selector must not be null else #TS(0) Selector index must be within its descriptor table limits else #TS (SS selector) Selector's RPL must equal DPL of code segment else #TS (SS selector) Stack segment DPL must equal DPL of code segment else #TS (SS selector) Descriptor must indicate writable data segment else #TS (SS selector) Segment PRESENT else #SS (SS selector) New stack must have room for parameters plus 8 bytes else #SS(0) IP must be in code segment limit else #GP(0) Load new SS:SP value from TSS Load new CS:IP value from gate Load CS descriptor Load SS descriptor Push long pointer of old stack onto new stack Get word count from call gate, mask to 5 bits Copy parameters from old stack onto new stack Push return address onto new stack Set CPL to stack segment DPL Set RPL of CS to CPL Else CALL GATE TO SAME PRIVILEGE: Stack must have room for 4-byte return address else #SS(0) IP must be in code segment limit else #GP(0) Load CS:IP from gate Push return address onto stack Load code segment descriptor into CS-cache Set RPL of CS to CPL CALL TASK GATE: Task gate DPL must be  CPL else #GP (gate selector) Task gate DPL must be  RPL else #GP (gate selector) Task Gate must be PRESENT else #NP (gate selector) Examine selector to TSS, given in Task Gate descriptor: Must specify global in the local/global bit else #GP (TSS selector) Index must be within GDT limits else #GP (TSS selector) TSS descriptor AR byte must specify available TSS (bottom bits 00001) else #GP (TSS selector) Task State Segment must be PRESENT else #NP (TSS selector) SWITCH_TASKS with nesting to TSS IP must be in code segment limit else #GP(0) TASK STATE SEGMENT: TSS DPL must be  CPL else #GP (TSS selector) TSS DPL must be  RPL else #GP (TSS selector) TSS descriptor AR byte must specify available TSS else #GP (TSS selector) Task State Segment must be PRESENT else #NP (TSS selector) SWITCH_TASKS with nesting to TSS IP must be in code segment limit else #GP(0) ELSE #GP (code segment selector) Protected Mode Exceptions FAR calls: #GP, #NP, #SS, and #TS, as indicated in the list above. NEAR direct calls: #GP(0) if procedure location is beyond the code segment limits. NEAR indirect CALL: #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. #GP if the indirect offset obtained is beyond the code segment limits. Real Address Mode Exceptions Interrupt 13 for a word operand at offset 0FFFFH. CBW‘‘Convert Byte into Word Opcode Instruction Clocks Description 98 CBW 2 Convert byte into word (AH = top bit of AL) Flags Modified None Flags Undefined None Operation CBW converts the signed byte in AL to a signed word in AX. It does so by extending the top bit of AL into all of the bits of AH. Protected Mode Exceptions None Real Address Mode Exceptions None CLC‘‘Clear Carry Flag Opcode Instruction Clocks Description F8 CLC 2 Clear carry flag Flags Modified Carry=0 Flags Undefined None Operation CLC sets the carry flag to zero. No other flags or registers are affected. Protected Mode Exceptions None Real Address Mode Exceptions None CLD‘‘Clear Direction Flag Opcode Instruction Clocks Description FC CLD 2 Clear direction flag, SI and DI will increment Flags Modified Direction=0 Flags Undefined None Operation CLD clears the direction flag. No other flags or registers are affected. After CLD is executed, string operations will increment the index registers (SI and/or DI) that they use. Protected Mode Exceptions None Real Address Mode Exceptions None CLI‘‘Clear Interrupt Flag Opcode Instruction Clocks Description FA CLI 3 Clear interrupt flag; interrupts disabled Flags Modified Interrupt=0 Flags Undefined None Operation CLI clears the interrupt enable flag if the current privilege level is at least as privileged as IOPL. No other flags are affected. External interrupts will not be recognized at the end of the CLI instruction or thereafter until the interrupt flag is set. Protected Mode Exceptions #GP(0) if the current privilege level is bigger (has less privilege) than the IOPL in the flags register. IOPL specifies the least privileged level at which I/O may be performed. Real Address Mode Exceptions None CLTS‘‘Clear Task Switched Flag Opcode Instruction Clocks Description 0F 06 CLTS 2 Clear task switched flag Flags Modified Task switched=0 Flags Undefined None Operation CLTS clears the task switched flag in the Machine Status Word. This flag is set by the 80286 every time a task switch occurs. The TS flag is used to manage processor extensions as follows: every execution of a WAIT or an ESC instruction will be trapped if the MP flag of MSW is set and the task switched flag is set. Thus, if a processor extension is present and a task switch has been made since the last ESC instruction was begun, the processor extension's context must be saved before a new instruction can be issued. The fault routine will save the context and reset the task switched flag or place the task requesting the processor extension into a queue until the current processor extension instruction is completed. CLTS appears in operating systems software, not in applications programs. It is a privileged instruction that can only be executed at level 0. Protected Mode Exceptions #GP(0) if CLTS is executed with a current privilege level other than 0. Real Address Mode Exceptions None (valid in REAL ADDRESS MODE to allow power-up initialization for Protected Mode) CMC‘‘Complement Carry Flag Opcode Instruction Clocks Description F5 CMC 2 Complement carry flag Flags Modified Carry Flags Undefined None Operation CMC reverses the setting of the carry flag. No other flags are affected. Protected Mode Exceptions None Real Address Mode Exceptions None CMP‘‘Compare Two Operands Opcode Instruction Clocks Description 3C db CMP AL,db 3 Compare immediate byte from AL 3D dw CMP AX,dw 3 Compare immediate word from AX 80 /7 db CMP eb,db 3,mem=6 Compare immediate byte from EA byte 38 /r CMP eb,rb 2,mem=7 Compare byte register from EA byte 83 /7 db CMP ew,db 3,mem=6 Compare immediate byte from EA word 81 /7 dw CMP ew,dw 3,mem=6 Compare immediate word from EA word 39 /r CMP ew,rw 2,mem=7 Compare word register from EA word 3A /r CMP rb,eb 2,mem=6 Compare EA byte from byte register 3B /r CMP rw,ew 2,mem=6 Compare EA word from word register Flags Modified Overflow, sign, zero, auxiliary carry, parity, carry Flags Undefined None Operation CMP subtracts the second operand from the first operand, but it does not place the result anywhere. Only the flags are changed by this instruction. CMP is usually followed by a conditional jump instruction. See the "Jcond" instructions in this chapter for the list of signed and unsigned flag tests provided by the 80286. If a word operand is compared to an immediate byte value, the byte value is first sign-extended. Protected Mode Exceptions #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 13 for a word operand at offset 0FFFFH. CMPS/CMPSB/CMPSW‘‘Compare string operands Opcode Instruction Clocks Description A6 CMPS mb,mb 8 Compare bytes ES:[DI] from [SI] A6 CMPSB 8 Compare bytes ES:[DI] from DS:[SI] A7 CMPSW 8 Compare words ES:[DI] from DS:[SI] Flags Modified Overflow, sign, zero, auxiliary carry, parity, carry Flags Undefined None Operation CMPS compares the byte or word pointed to by SI with the byte or word pointed to by DI by performing the subtraction [SI] - [DI]. The result is not placed anywhere; only the flags reflect the result of the subtraction. The types of the operands to CMPS determine whether bytes or words are compared. The segment addressability of the first (SI) operand determines whether a segment override byte will be produced or whether the default segment register DS is used. The second (DI) operand must be addressible from the ES register; no segment override is possible. After the comparison is made, both SI and DI are automatically advanced. If the direction flag is 0 (CLD was executed), the registers increment; if the direction flag is 1 (STD was executed), the registers decrement. The registers increment or decrement by 1 if a byte was moved; by 2 if a word was moved. CMPS cn be preceded by the REPE or REPNE prefix for block comparison of CX bytes or words. Refer to the REP instruction for details of this operation. Protected Mode Exceptions #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 13 for a word operand at offset 0FFFFH. CWD‘‘Convert Word to Doubleword Opcode Instruction Clocks Description 99 CWD 2 Convert word to doubleword (DX:AX = AX) Flags Modified None Flags Undefined None Operation CWD converts the signed word in AX to a signed doubleword in DX:AX. It does so by extending the top bit of AX into all the bits of DX. Protected Mode Exceptions None Real Address Mode Exceptions None DAA‘‘Decimal Adjust AL After Addition Opcode Instruction Clocks Description 27 DAA 3 Decimal adjust AL after addition Flags Modified Sign, zero, auxiliary carry, parity, carry Flags Undefined Overflow Operation DAA should be executed only after an ADD instruction which leaves a two-BCD-digit byte result in the AL register. The ADD operands should consist of two packed BCD digits. In this case, the DAA instruction will adjust AL to contain the correct two-digit packed decimal result. The precise definition of DAA is as follows: 1. If the lower 4 bits of AL are greater than nine, or if the auxiliary carry flag is 1, then increment AL by 6, and set the auxiliary carry flag. Otherwise, reset the auxiliary carry flag. 2. If AL is now greater than 9FH, or if the carry flag is set, then increment AL by 60H, and set the carry flag. Otherwise, clear the carry flag. Protected Mode Exceptions None Real Address Mode Exceptions None DAS‘‘Decimal Adjust AL After Subtraction Opcode Instruction Clocks Description 2F DAS 3 Decimal adjust AL after subtraction Flags Modified Sign, zero, auxiliary carry, parity, carry Flags Undefined Overflow Operation DAS should be executed only after a subtraction instruction which leaves a two-BCD-digit byte result in the AL register. The operands should consist of two packed BCD digits. In this case, the DAS instruction will adjust AL to contain the correct packed two-digit decimal result. The precise definition of DAS is as follows: 1. If the lower four bits of AL are greater than 9, or if the auxiliary carry flag is 1, then decrement AL by 6, and set the auxiliary carry flag. Otherwise, reset the auxiliary carry flag. 2. If AL is now greater than 9FH, or if the carry flag is set, then decrement AL by 60H, and set the carry flag. Otherwise, clear the carry flag. Protected Mode Exceptions None Real Address Mode Exceptions None DEC‘‘Decrement by 1 Opcode Instruction Clocks Description FE /1 DEC eb 2,mem=7 Decrement EA byte by 1 FF /1 DEC ew 2,mem=7 Decrement EA word by 1 48+ rw DEC rw 2 Decrement word register by 1 Flags Modified Overflow, sign, zero, auxiliary carry, parity Flags Undefined None Operation 1 is subtracted from the operand. Note that the carry flag is not changed by this instruction. If you want the carry flag set, use the SUB instruction with a second operand of 1. Protected Mode Exceptions #GP(0) if the operand is in a non-writable segment. #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 13 for a word operand at offset 0FFFFH. DIV‘‘Unsigned Divide Opcode Instruction Clocks Description F6 /6 DIV eb 14,mem=17 Unsigned divide AX by EA byte F7 /6 DIV ew 22,mem=25 Unsigned divide DX:AX by EA word Flags Modified None Flags Undefined Overflow, sign, zero, auxiliary carry, parity, carry Operation DIV performs an unsigned divide. The dividend is implicit; only the divisor is given as an operand. If the source operand is a BYTE operand, divide AX by the byte. The quotient is stored in AL, and the remainder is stored in AH. If the source operand is a WORD operand, divide DX:AX by the word. The high-order 16 bits of the dividend are kept in DX. The quotient is stored in AX, and the remainder is stored in DX. Non-integral quotients are truncated towards 0. The remainder is always less than the dividend. Protected Mode Exceptions Interrupt 0 if the quotient is too big to fit in the designated register (AL or AX), or if the divisor is zero. #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 0 if the quotient is too big to fit in the designated register (AL or AX), or if the divisor is zero. Interrupt 13 for a word operand at offset 0FFFFH. ENTER‘‘Make Stack Frame for Procedure Parameters Opcode Instruction Clocks Description C8 dw 00 ENTER dw,0 11 Make stack frame for procedure parameters C8 dw 01 ENTER dw,1 15 Make stack frame for procedure parameters C8 dw db ENTER dw,db 12+4db Make stack frame for procedure parameters Flags Modified None Flags Undefined None Operation ENTER is used to create the stack frame required by most block-structured high-level languages. The first operand specifies how many bytes of dynamic storage are to be allocated on the stack for the routine being entered. The second operand gives the lexical nesting level of the routine within the high-level-language source code. It determines how many stack frame pointers are copied into the new stack frame from the preceding frame. BP is used as the current stack frame pointer. If the second operand is 0, ENTER pushes BP, sets BP to SP, and subtracts the first operand from SP. For example, a procedure with 12 bytes of local variables would have an ENTER 12,0 instruction at its entry point and a LEAVE instruction before every RET. The 12 local bytes would be addressed as negative offsets from [BP]. See also section 4.2. The formal definition of the ENTER instruction for all cases is given by the following listing. LEVEL denotes the value of the second operand. LEVEL:=LEVEL MOD 32 Push BP Set a temporary value FRAME_PTR := SP If LEVEL > 0 then Repeat (LEVEL-1) times: BP := BP - 2 Push the word pointed to by BP End repeat Push FRAME_PTR End if BP := FRAME-PTR SP := SP - first operand Protected Mode Exceptions #SS(0) if SP were to go outside of the stack limit within any part of the instruction execution. Real Address Mode Exceptions None HLT‘‘Halt Opcode Instruction Clocks Description F4 HLT 2 Halt Flags Modified None Flags Undefined None Operation Successful execution of HLT causes the 80286 to cease executing instructions and to enter a HALT state. Execution resumes only upon receipt of an enabled interrupt or a reset. If an interrupt is used to resume program execution after HLT, the saved CS:IP value will point to the instruction that follows HLT. Protected Mode Exceptions HLT is a privileged instruction. #GP(0) if the current privilege level is not 0. Real Address Mode Exceptions None IDIV‘‘Signed Divide Opcode Instruction Clocks Description F6 /7 IDIV eb 17,mem=20 Signed divide AX by EA byte (AL=Quo,AH=Rem) F7 /7 IDIV ew 25,mem=28 Signed divide DX:AX by EA word (AX=Quo,DX=Rem) Flags Modified None Flags Undefined Overflow, sign, zero, auxiliary carry, parity, carry Operation IDIV performs a signed divide. The dividend is implicit; only the divisor is given as an operand. If the source operand is a BYTE operand, divide AX by the byte. The quotient is stored in AL, and the remainder is stored in AH. If the source operand is a WORD operand, divide DX:AX by the word. The high-order 16 bits of the dividend are in DX. The quotient is stored in AX, and the remainder is stored in DX. Non-integral quotients are truncated towards 0. The remainder has the same sign as the dividend and always has less magnitude than the dividend. Protected Mode Exceptions Interrupt 0 if the quotient is too big to fit in the designated register (AL or AX), or if the divisor is 0. #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 0 if the quotient is too big to fit in the designated register (AL or AX), or if the divisor is 0. Interrupt 13 for a word operand at offset 0FFFFH. IMUL‘‘Signed Multiply Opcode Instruction Clocks Description F6 /5 IMUL eb 13,mem=16 Signed multiply (AX = AL * EA byte) F7 /5 IMUL ew 21,mem=24 Signed multiply (DXAX = AX * EA word) 6B /r db IMUL rw,db 21,mem=24 Signed multiply imm. byte into word reg. 69 /r dw IMUL rw,ew,dw 21,mem=24 Signed multiply (rw = EA word * imm. word) 6B /r db IMUL rw,ew,db 21,mem=24 Signed multiply (rw = EA word * imm. byte) Flags Modified Overflow, carry Flags Undefined Sign, zero, auxiliary carry, parity Operation IMUL performs signed multiplication. If IMUL has a single byte source operand, then the source is multiplied by AL and the 16-bit signed result is left in AX. Carry and overflow are set to 0 if AH is a sign extension of AL; they are set to 1 otherwise. If IMUL has a single word source operand, then the source operand is multiplied by AX and the 32-bit signed result is left in DX:AX. DX contains the high-order 16 bits of the product. Carry and overflow are set to 0 if DX is a sign extension of AX; they are set to 1 otherwise. If IMUL has three operands, then the second operand (an effective address word) is multiplied by the third operand (an immediate word), and the 16 bits of the result are placed in the first operand (a word register). Carry and overflow are set to 0 if the result fits in a signed word (between -32768 and +32767, inclusive); they are set to 1 otherwise. The low 16 bits of the product of a 16-bit signed multiply are the same as those of an unsigned multiply. The three operand IMUL instruction can be used for unsigned operands as well. Protected Mode Exceptions #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 13 for a word operand at offset 0FFFFH. IN‘‘Input from Port Opcode Instruction Clocks Description E4 db IN AL,db 5 Input byte from immediate portinto AL EC IN AL,DX 5 Input byte from port DX into AL E5 db IN AX,db 5 Input word from immediate portinto AX ED IN AX,DX 5 Input word from port DX into AX Flags Modified None Flags Undefined None Operation IN transfers a data byte or data word from the port numbered by the second operand into the register (AL or AX) given as the first operand. You can access any port from 0 to 65535 by placing the port number in the DX register then using an IN instruction with DX as the second parameter. These I/O instructions can be shortened by using an 8-bit port I/O in the instruction. The upper 8 bits of the port address will be zero when an 8-bit port I/O is used. Intel has reserved I/O port addresses 00F8H through 00FFH; they should not be used. Protected Mode Exceptions #GP(0) if the current privilege level is bigger (has less privilege) than IOPL, which is the privilege level found in the flags register. Real Address Mode Exceptions None INC‘‘Increment by 1 Opcode Instruction Clocks Description FE /0 INC eb 2,mem=7 Increment EA byte by 1 FF /0 INC ew 2,mem=7 Increment EA word by 1 40+rw INC rw 2 Increment word register by 1 Flags Modified Overflow, sign, zero, auxiliary carry, parity Flags Undefined None Operation 1 is added to the operand. Note that the carry flag is not changed by this instruction. If you want the carry flag set, use the ADD instruction with a second operand of 1. Protected Mode Exceptions #GP(0) if the operand is in a non-writable segment. #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 13 for a word operand at offset 0FFFFH. INS/INSB/INSW‘‘Input from Port to String Opcode Instruction Clocks Description 6C INS eb,DX 5 Input byte from port DX into ES:[DI] 6D INS ew,DX 5 Input word from port DX into ES:[DI] 6C INSB 5 Input byte from port DX into ES:[DI] 6D INSW 5 Input word from port DX into ES:[DI] Flags Modified None Flags Undefined None Operation INS transfers data from the input port numbered by the DX register to the memory byte or word at ES:DI. The memory operand must be addressable from the ES register; no segment override ispossible. INS does not allow the specification of the port number as an immediate value. The port must be addressed through the DX register. After the transfer is made, DI is automatically advanced. If the direction flag is 0 (CLD was executed), DI increments; if the direction flag is 1 (STD was executed), DI decrements. DI increments or decrements by 1 if a byte was moved; by 2 if a word was moved. INS can be preceded by the REP prefix for block input of CX bytes or words. Refer to the REP instruction for details of this operation. Intel has reserved I/O port addresses 00F8H through 00FFH; they should not be used. Not all input port devices can handle the rate at which this instruction transfers input data to memory. Protected Mode Exceptions #GP(0) if CPL > IOPL. #GP(0) if the destination is in a non-writable segment. #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 13 for a word operand at offset 0FFFFH. INT/INTO‘‘Call to Interrupt Procedure Opcode Instruction Clocks Add one clock for each byte of the next instruction executed. Description CC INT 3 23 (real mode) Interrupt 3 (trap to debugger) CC INT 3 40 Interrupt 3, protected mode, same privilege CC INT 3 78 Interrupt 3, protected mode, more privilege CC INT 3 167 Interrupt 3, protected mode, via task gate CD db INT db 23 (real mode) Interrupt numbered by immediate byte CD db INT db 40 Interrupt, protected mode, same privilege CD db INT db 78 Interrupt, protected mode, more privilege CD db INT db 167 Interrupt, protected mode, via task gate CE INTO 24,noj=3 (real mode) Interrupt 4 if overflow flag is 1 Flags Modified All if a task switch takes place; Trap Flag reset if no task switch takes place. Interrupt Flag is always reset in Real Mode, and reset in Protected Mode when INT references an interrupt gate. Flags Undefined None Operation The INT instruction generates via software a call to an interrupt procedure. The immediate operand, from 0 to 255, gives the index number into the Interrupt Descriptor Table of the interrupt routine to be called. In protected mode, the IDT consists of 8-byte descriptors; the descriptor for the interrupt invoked must indicate an interrupt gate, a trap gate, or a task gate. In real address mode, the IDT is an array of 4-byte long pointers at the fixed location 00000H. The INTO instruction is identical to the INT instruction except that the interrupt number is implicitly 4, and the interrupt is made only if the overflow flag of the 80286 is on. The clock counts for the four forms of INT db are valid for INTO, with the number of clocks increased by 1 for the overflow flag test. The first 32 interrupts are reserved by Intel for systems use. Some of these interrupts are exception handlers for internally-generated faults. Most of these exception handlers should not be invoked with the INT instruction. Generally, interrupts behave like far CALLs except that the flags register is pushed onto the stack before the return address. Interrupt procedures return via the IRET instruction, which pops the flags from the stack. In Real Address mode, INT pushes the flags, CS and the return IP onto the stack in that order, then resets the Trap Flag, then jumps to the long pointer indexed by the interrupt number, in the interrupt vector table. In Protected mode, INT also resets the Trap Flag. In Protected mode, the precise semantics of the INT instruction are given by the following: INTERRUPT Interrupt vector must be within IDT table limits else #GP (vector number * 8+2+EXT) Descriptor AR byte must indicate interrupt gate, trap gate, or task gate else #GP (vector number * 8+2+EXT) If INT instruction then gate descriptor DPL must be  CPL else #GP (vector number * 8+2+EXT) Gate must be PRESENT else #NP (vector number * 8+2+EXT) If TRAP GATE or INTERRUPT GATE: Examine CS selector and descriptor given in the gate descriptor: Selector must be non-null else #GP (EXT) Selector must be within its descriptor table limits else #GP (selector+EXT) Descriptor AR byte must indicate code segment else #GP (selector + EXT) Segment must be PRESENT else #NP (selector+EXT) If code segment is non-conforming and DPL < CPL then INTERRUPT TO INNER PRIVILEGE: Check selector and descriptor for new stack in current Task State Segment: Selector must be non-null else #TS(EXT) Selector index must be within its descriptor table limits else #TS (SS selector+EXT) Selector's RPL must equal DPL of code segment else #TS (SS selector+EXT) Stack segment DPL must equal DPL of code segment else #TS (SS selector+EXT) Descriptor must indicate writable data segment else #TS (SS selector+EXT) Segment must be PRESENT else #SS (SS selector+EXT) New stack must have room for 10 bytes else #SS(0) IP must be in CS limit else #GP(0) Load new SS and SP value from TSS Load new CS and IP value from gate Load CS descriptor Load SS descriptor Push long pointer to old stack onto new stack Push return address onto new stack Set CPL to new code segment DPL Set RPL of CS to CPL If INTERRUPT GATE then set the Interrupts Enabled Flag to 0 (disabled) Set the Trap Flag to 0 Set the Nested Task Flag to 0 If code segment is conforming or code segment DPL = CPL then INTERRUPT TO SAME PRIVILEGE LEVEL: Current stack limits must allow pushing 6 bytes else #SS(0) If interrupt was caused by fault with error code then Stack limits must allow push of two more bytes else #SS(0) IP must be in CS limit else #GP(0) Push flags onto stack Push current CS selector onto stack Push return offset onto stack Load CS:IP from gate Load CS descriptor Set the RPL field of CS to CPL Push error code (if any) onto stack If INTERRUPT GATE then set the Interrupts Enabled Flag to 0 (disabled) Set the Trap Flag to 0 Set the Nested Task Flag to 0 Else #GP (CS selector + EXT) If TASK GATE: Examine selector to TSS, given in Task Gate descriptor: Must specify global in the local/global bit else #GP (TSS selector) Index must be within GDT limits else #GP (TSS selector) AR byte must specify available TSS (bottom bits 00001) else #GP (TSS selector) Task State Segment must be PRESENT else #NP (TSS selector) SWITCH_TASKS with nesting to TSS If interrupt was caused by fault with error code then Stack limits must allow push of two more bytes else #SS(0) Push error code onto stack IP must be in CS limit else #GP(0) EXT is 1 if an external event (i.e., a single step, an external interrupt, an MF exception, or an MP exception) caused the interrupt; 0 if not (i.e., an INT instruction or other exceptions). Protected Mode Exceptions #GP, #NP, #SS, and #TS, as indicated in the list above. Real Address Mode Exceptions None; the 80286 will shut down if the SP = 1, 3, or 5 before executing the INT or INTO instruction‘‘due to lack of stack space. IRET‘‘Interrupt Return Opcode Instruction Clocks Add one clock for each byte in the next instruction executed. Description CF IRET 17,pm=31 Interrupt return (far return and pop flags) CF IRET 55 Interrupt return, lesser privilege CF IRET 169 Interrupt return, different task (NT=1) Flags Modified Entire flags register popped from stack Flags Undefined None Operation In real address mode, IRET pops IP, CS, and FLAGS from the stack in that order, and resumes the interrupted routine. In protected mode, the action of IRET depends on the setting of the Nested Task Flag (NT) bit in the flag register. When popping the new flag image from the stack, note that the IOPL bits in the flag register are changed only when CPL=0. If NT=0, IRET returns from an interrupt procedure without a task switch. The code returned to must be equally or less privileged than the interrupt routine as indicated by the RPL bits of the CS selector popped from the stack. If the destination code is of less privilege, IRET then also pops SP and SS from the stack. If NT=1, IRET reverses the operation of a CALL or INT that caused a task switch. The task executing IRET has its updated state saved in its Task State Segment. This means that if the task is re-entered, the code that follows IRET will be executed. The exact checks and actions performed by IRET in protected mode are given on the following page. INTERRUPT RETURN: If Nested Task Flag=1 then RETURN FROM NESTED TASK: Examine Back Link Selector in TSS addressed by the current Task Register: Must specify global in the local/global bit else #TS (new TSS selector) Index must be within GDT limits else #TS (new TSS selector) AR byte must specify TSS else #TS (new TSS selector) New TSS must be busy else #TS (new TSS selector) Task State Segment must be PRESENT else #NP (new TSS selector) SWITCH_TASKS without nesting to TSS specified by back link selector Mark the task just abandoned as NOT BUSY IP must be in code segment limit else #GP(0) If Nested Task Flag=0 then INTERRUPT RETURN ON STACK: Second word on stack must be within stack limits else #SS(0) Return CS selector RPL must be  CPL else #GP (Return selector) If return selector RPL = CPL then INTERRUPT RETURN TO SAME LEVEL: Top 6 bytes on stack must be within limits else #SS(0) Return CS selector (at SP+2) must be non-null else #GP(0) Selector index must be within its descriptor table limits else #GP (Return selector) AR byte must indicate code segment else #GP (Return selector) If non-conforming then code segment DPL must = CPL else #GP (Return selector) If conforming then code segment DPL must be Ύ CPL else #GP (Return selector) Segment must be PRESENT else #NP (Return selector) IP must be in code segment limit else #GP(0) Load CS:IP from stack Load CS-cache with new code segment descriptor Load flags with third word on stack Increment SP by 6 Else INTERRUPT RETURN TO OUTER PRIVILEGE LEVEL: Top 10 bytes on stack must be within limits else #SS(0) Examine return CS selector (at SP+2) and associated descriptor: Selector must be non-null else #GP(0) Selector index must be within its descriptor table limits else #GP (Return selector) AR byte must indicate code segment else #GP (Return selector) If non-conforming then code segment DPL must = CS selector RPL else #GP (Return selector) If conforming then code segment DPL must be > CPL else #GP (Return selector) Segment must be PRESENT else #NP (Return selector) Examine return SS selector (at SP+8) and associated descriptor: Selector must be non-null else #GP(0) Selector index must be within its descriptor table limits else #GP (SS selector) Selector RPL must equal the RPL of the return CS selector else #GP (SS selector) AR byte must indicate a writable data segment else #GP (SS selector) Stack segment DPL must equal the RPL of the return CS selector else #GP (SS selector) SS must be PRESENT else #SS (SS selector) IP must be in code segment limit else #GP(0) Load CS:IP from stack Load flags with values at (SP+4) Load SS:SP from stack Set CPL to the RPL of the return CS selector Load the CS-cache with the CS descriptor Load the SS-cache with the SS descriptor For each of ES and DS: If the current register setting is not valid for the outer level, then zero the register and clear the valid flag To be valid, the register setting must satisfy the following properties: Selector index must be within descriptor table limits AR byte must indicate data or readable code segment If segment is data or non-conforming code, then: DPL must be  CPL, or DPL must be  RPL. Protected Mode Exceptions #GP, #NP, or #SS, as indicated in the above listing. Real Address Mode Exceptions Interrupt 13 if the stack is popped when it has offset 0FFFFH. Jcond‘‘Jump Short If Condition Met Opcode Instruction Clocks When a jump is taken, add one clock for every byte of the next instruction executed. Description 77 cb JA cb 7,noj=3 Jump short if above (CF=0 and ZF=0) 73 cb JAE cb 7,noj=3 Jump short if above or equal (CF=0) 72 cb JB cb 7,noj=3 Jump short if below (CF=1) 76 cb JBE cb 7,noj=3 Jump short if below or equal (CF=1 or ZF=1) 72 cb JC cb 7,noj=3 Jump short if carry (CF=1) E3 cb JCXZ cb 8,noj=4 Jump short if CX register is zero 74 cb JE cb 7,noj=3 Jump short if equal (ZF=1) 7F cb JG cb 7,noj=3 Jump short if greater (ZF=0 and SF=OF) 7D cb JGE cb 7,noj=3 Jump short if greater or equal (SF=OF) 7C cb JL cb 7,noj=3 Jump short if less (SF/=OF) 7E cb JLE cb 7,noj=3 Jump short if less or equal (ZF=1 or SF/=OF) 76 cb JNA cb 7,noj=3 Jump short if not above (CF=1 or ZF=1) 72 cb JNAE cb 7,noj=3 Jump short if not above/equal (CF=1) 73 cb JNB cb 7,noj=3 Jump short if not below (CF=0) 77 cb JNBE cb 7,noj=3 Jump short if not below/equal (CF=0 and ZF=0) 73 cb JNC cb 7,noj=3 Jump short if not carry (CF=0) 75 cb JNE cb 7,noj=3 Jump short if not equal (ZF=0) 7E cb JNG cb 7,noj=3 Jump short if not greater (ZF=1 or SF/=OF) 7C cb JNGE cb 7,noj=3 Jump short if not greater/equal (SF/=OF) 7D cb JNL cb 7,noj=3 Jump short if not less (SF=OF) 7F cb JNLE cb 7,noj=3 Jump short if not less/equal (ZF=0 and SF=OF) 71 cb JNO cb 7,noj=3 Jump short if notoverflow (OF=0) 7B cb JNP cb 7,noj=3 Jump short if not parity (PF=0) 79 cb JNS cb 7,noj=3 Jump short if not sign (SF=0) 75 cb JNZ cb 7,noj=3 Jump short if not zero (ZF=0) 70 cb JO cb 7,noj=3 Jump short if overflow (OF=1) 7A cb JP cb 7,noj=3 Jump short if parity (PF=1) 7A cb JPE cb 7,noj=3 Jump short if parity even (PF=1) 7B cb JPO cb 7,noj=3 Jump short if parity odd (PF=0) 78 cb JS cb 7,noj=3 Jump short if sign (SF=1) 74 cb JZ cb 7,noj=3 Jump short if zero (ZF=1) Flags Modified None Flags Undefined None Operation Conditional jumps (except for JCXZ, explained below) test the flags, which presumably have been set in some meaningful way by a previous instruction. The conditions for each mnemonic are given in parentheses after each description above. The terms "less" and "greater" are used for comparing signed integers; "above" and "below" are used for unsigned integers. If the given condition is true, then a short jump is made to the label provided as the operand. Instruction encoding is most efficient when the target for the conditional jump is in the current code segment and within -128 to +127 bytes of the first byte of the next instruction. Alternatively, the opposite sense (e.g., JNZ has opposite sense to that of JZ) of the conditional jump can skip around an unconditional jump to the destination. This range is necessary for the assembler to construct a one-byte signed displacement from the end of the current instruction. If the label is out-of-range, or if the label is a FAR label, then you must perform a jump with the opposite condition around an unconditional jump to the non-short label. Because there are, in many instances, several ways to interpret a particular state of the flags, ASM286 provides more than one mnemonic for most of the conditional jump opcodes. For example, consider that a programmer who has just compared a character to another in AL might wish to jump if the two were equal (JE), while another programmer who had just ANDed AX with a bit field mask would prefer to consider only whether the result was zero or not (he would use JZ, a synonym for JE). JCXZ differs from the other conditional jumps in that it actually tests the contents of the CX register for zero, rather than interrogating the flags. This instruction is useful following a conditionally repeated string operation (REPE SCASB, for example) or a conditional loop instruction (such as LOOPNE TARGETLABEL). These instructions implicitly use a limiting count in the CX register. Looping (repeating) ends when either the CX register goes to zero or the condition specified in the instruction (flags indicating equals in both of the above cases) occurs. JCXZ is useful when the terminations must be handled differently. Protected Mode Exceptions #GP(0) if the offset jumped to is beyond the limits of the code segment. Real Address Mode Exceptions None JMP‘‘Jump Opcode Instruction Clocks Add one clock for every byte of the next instruction executed. Description EB cb JMP cb 7 Jump short EA cd JMP cd 180 Jump to task gate E9 cw JMP cw 7 Jump near EA cd JMP cd 11,pm=23 Jump far (4-byte immediate address) EA cd JMP cd 38 Jump to call gate, same privilege EA cd JMP cd 175 Jump via Task State Segment FF /4 JMP ew 7,mem=11 Jump near to EA word (absolute offset) FF /5 JMP ed 15,pm=26 Jump far (4-byte effective address in memory doubleword) FF /5 JMP ed 41 Jump to call gate, same privilege FF /5 JMP ed 178 Jump via Task State Segment FF /5 JMP ed 183 Jump to task gate Flags Modified All if a task switch takes place; none if no task switch occurs. Flags Undefined None Operation The JMP instruction transfers program control to a different instruction stream without recording any return information. For inter-segment jumps, the destination can be a code segment, a call gate, a task gate, or a Task State Segment. The latter two destinations cause a complete task switch to take place. Control transfers within a segment use the JMP cw or JMP cb forms. The operand is a relative offset added modulo 65536 to the offset of the instruction that follows the JMP. The result is the new value of IP; the value of CS is unchanged. The byte operand is sign-extended before it is added; it can therefore be used to address labels within 128 bytes in either direction from the next instruction. Indirect jumps within a segment use the JMP ew form. The contents of the register or memory operand is an absolute offset, which becomes the new value of IP. Again, CS is unchanged. Inter-segment jumps in real address mode simply set IP to the offset part of the long pointer and set CS to the selector part of the pointer. In protected mode, inter-segment jumps cause the 80286 to consult the descriptor addressed by the selector part of the long pointer. The AR byte of the descriptor determines the type of the destination. (See table B-3 for possible values of the AR byte.) Following are the possible destinations: 1. Code segment‘‘The addressability and visibility of the destination are verified, and CS and IP are loaded with the destination pointer values. 2. Call gate‘‘The offset part of the destination pointer is ignored. After checking for validity, the processor jumps to the location stored in the call gate descriptor. 3. Task gate‘‘The current task's state is saved in its Task State Segment (TSS), and the TSS named in the task gate is used to load a new context. The outgoing task is marked not busy, the new TSS is marked busy, and execution resumes at the point at which the new task was last suspended. 4. TSS‘‘The current task is suspended and the new task is initiated as in 3 above except that there is no intervening gate. Following is the list of checks and actions taken for long jumps in protected mode: JUMP FAR: If indirect then check access of EA doubleword #GP(0) or #SS(0) if limit violation Destination selector is not null else #GP(0) Destination selector index is within its descriptor table limits else #GP (selector) Examine AR byte of destination selector for legal values: JUMP CONFORMING CODE SEGMENT: Descriptor DPL must be Ύ CPL else #GP (selector) Segment must be PRESENT else #NP (selector) IP must be in code segment limit else #GP(0) Load CS:IP from destination pointer Load CS-cache with new segment descriptor JUMP NONCONFORMING CODE SEGMENT: RPL of destination selector must be Ύ CPL else #GP (selector) Descriptor DPL must = CPL else #GP (selector) Segment must be PRESENT else #NP (selector) IP must be in code segment limit else #GP(0) Load CS:IP from destination pointer Load CS-cache with new segment descriptor Set RPL field of CS register to CPL JUMP TO CALL GATE: Descriptor DPL must be  CPL else #GP (gate selector) Descriptor DPL must be  gate selector RPL else #GP (gate selector) Gate must be PRESENT else #NP (gate selector) Examine selector to code segment given in call gate descriptor: Selector must not be null else #GP(0) Selector must be within its descriptor table limits else #GP (CS selector) Descriptor AR byte must indicate code segment else #GP (CS selector) If non-conforming, code segment descriptor DPL must = CPL else #GP (CS selector) If conforming, then code segment descriptor DPL must be Ύ CPL else #GP (CS selector) Code Segment must be PRESENT else #NP (CS selector) IP must be in code segment limit else #GP(0) Load CS:IP from call gate Load CS-cache with new code segment Set RPL of CS to CPL JUMP TASK GATE: Gate descriptor DPL must be  CPL else #GP (gate selector) Gate descriptor DPL must be  gate selector RPL else #GP (gate selector) Task Gate must be PRESENT else #NP (gate selector) Examine selector to TSS, given in Task Gate descriptor: Must specify global in the local/global bit else #GP (TSS selector) Index must be within GDT limits else #GP (TSS selector) Descriptor AR byte must specify available TSS (bottom bits 00001) else #GP (TSS selector) Task State Segment must be PRESENT else #NP (TSS selector) SWITCH_TASKS without nesting to TSS IP must be in code segment limit else #GP(0) JUMP TASK STATE SEGMENT: TSS DPL must be  CPL else #GP (TSS selector) TSS DPL must be  TSS selector RPL else #GP (TSS selector) Descriptor AR byte must specify available TSS (bottom bits 00001) else #GP (TSS selector) Task State Segment must be PRESENT else #NP (TSS selector) SWITCH_TASKS with nesting to TS. IP must be in code segment limit else #GP(0) Else GP (selector) Protected Mode Exceptions For NEAR jumps, #GP(0) if the destination offset is beyond the limits of the current code segment. For FAR jumps, #GP, #NP, #SS, and #TS, as indicated above. #UD if indirect inter-segment jump operand is a register. Real Address Mode Exceptions #UD if indirect inter-segment jump operand is a register. LAHF‘‘Load Flags into AH Register Opcode Instruction Clocks Description 9F LAHF 2 Load: AH = flags SF ZF xx AF xx PF xx CF Flags Modified None Flags Undefined None Operation The low byte of the flags word is transferred to AH. The bits, from MSB to LSB, are as follows: sign, zero, indeterminate, auxiliary carry, indeterminate, parity, indeterminate, and carry. See figure 3-5. Protected Mode Exceptions None Real Address Mode Exceptions None LAR‘‘Load Access Rights Byte Opcode Instruction Clocks Description 0F 02 /r LAR rw,ew 14,mem=16 Load: high(rw)= Access Rights byte, selector ew Flags Modified Zero Flags Undefined None Operation LAR expects the second operand (memory or register word) to contain a selector. If the associated descriptor is visible at the current privilege level and at the selector RPL, then the access rights byte of the descriptor is loaded into the high byte of the first (register) operand, and the low byte is set to zero. The zero flag is set if the loading was performed (i.e., the selector index is within the table limit, descriptor DPL  CPL, and descriptor DPL  selector RPL); the zero flag is cleared otherwise. Selector operands cannot cause protection exceptions. Protected Mode Exceptions #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exception INTERRUPT 6; LAR is unrecognized in Real Address mode. LDS/LES‘‘Load Doubleword Pointer Opcode Instruction Clocks Description C5 /r LDS rw,ed 7,pm=21 Load EA doubleword into DS and word register C4 /r LES rw,ed 7,pm=21 Load EA doubleword into ES and word register Flags Modified None Flags Undefined None Operation The four-byte pointer at the memory location indicated by the second operand is loaded into a segment register and a word register. The first word of the pointer (the offset) is loaded into the register indicated by the first operand. The last word of the pointer (the selector) is loaded into the segment register (DS or ES) given by the instruction opcode. When the segment register is loaded, its associated cache is also loaded. The data for the cache is obtained from the descriptor table entry for the selector given. A null selector (values 0000-0003) can be loaded into DS or ES without a protection exception. Any memory reference using such a segment register value will cause a #GP(0) exception but will not result in a memory reference. The saved segment register value will be null. Following is a list of checks and actions taken when loading the DS or ES registers: If selector is non-null then: Selector index must be within its descriptor table limits else #GP(selector) Examine descriptor AR byte: Data segment or readable non-conforming code segment Descriptor DPL  CPL else #GP (selector) Descriptor DPL  selector RPL else #GP (selector) Readable conforming code segment No DPL, RPL, or CPL checks Else #GP (selector) Segment must be present else #NP (selector) Load registers from operand Load segment register descriptor cache If selector is null then: Load registers from operand Mark segment register cache as invalid Protected Mode Exceptions #GP or #NP, as indicated in the list above. #GP(0) or #SS(0) if operand lies outside segment limit. #UD if the source operand is a register. Real Address Mode Exceptions Interrupt 13 for operand at offset 0FFFFH or 0FFFDH. #UD if the source operand is a register. LEA‘‘Load Effective Address Offset Opcode Instruction Clocks Description 8D /r LEA rw,m 3 Calculate EA offset given by m, place in rw Flags Modified None Flags Undefined None Operation The effective address (offset part) of the second operand is placed in the first (register) operand. Protected Mode Exceptions #UD if second operand is a register. Real Address Mode Exceptions #UD if second operand is a register. LEAVE‘‘High Level Procedure Exit Opcode Instruction Clocks Description C9 LEAVE 5 Set SP to BP, then POP BP Flags Modified None Flags Undefined None Operation LEAVE is the complementary operation to ENTER; it reverses the effects of that instruction. By copying BP to SP, LEAVE releases the stack space used by a procedure for its dynamics and display. The old frame pointer is now popped into BP, restoring the caller's frame, and a subsequent RET instruction will follow the back-link and remove any arguments pushed on the stack for the exiting procedure. Protected Mode Exceptions #SS(0) if BP does not point to a location within the current stack segment. Real Address Mode Exceptions Interrupt 13 for a word operand at offset 0FFFFH. LGDT/LIDT‘‘Load Global/Interrupt Descriptor Table Register Opcode Instruction Clocks Description 0F 01 /2 LGDT m 11 Load m into Global Descriptor Table reg 0F 01 /3 LIDT m 12 Load m into Interrupt Descriptor Table reg Flags Modified None Flags Undefined None Operation The Global or the Interrupt Descriptor Table Register is loaded from the six bytes of memory pointed to by the effective address operand (see figure 10-3). The LIMIT field of the descriptor table register loads from the first word; the next three bytes go to the BASE field of the register; the last byte is ignored. LGDT and LIDT appear in operating systems software; they are not used in application programs. These are the only instructions that directly load a physical memory address in 80286 protected mode. Protected Mode Exceptions #GP(0) if the current privilege level is not 0. #UD if source operand is a register. #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions These instructions are valid in Real Address mode to allow the power-up initialization for Protected mode. Interrupt 13 for a word operand at offset 0FFFFH. #UD if source operand is a register. LLDT‘‘Load Local Descriptor Table Register Opcode Instruction Clocks Description 0F 00 /2 LLDT ew 17,mem=19 Load selector ew into Local Descriptor Table register Flags Modified None Flags Undefined None Operation The word operand (memory or register) to LLDT should contain a selector pointing to the Global Descriptor Table. The GDT entry should be a Local Descriptor Table Descriptor. If so, then the Local Descriptor Table Register is loaded from the entry. The descriptor cache entries for DS, ES, SS, and CS are not affected. The LDT field in the TSS is not changed. The selector operand is allowed to be zero. In that case, the Local Descriptor Table Register is marked invalid. All descriptor references (except by LAR, VERR, VERW or LSL instructions) will cause a #GP fault. LLDT appears in operating systems software; it does not appear in applications programs. Protected Mode Exceptions #GP(0) if the current privilege level is not 0. #GP (selector) if the selector operand does not point into the Global Descriptor Table, or if the entry in the GDT is not a Local Descriptor Table. #NP (selector) if LDT descriptor is not present. #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 6; LLDT is not recognized in Real Address Mode. LMSW‘‘Load Machine Status Word Opcode Instruction Clocks Description 0F 01 /6 LMSW ew 3,mem=6 Load EA word into Machine Status Word Flags Modified None Flags Undefined None Operation The Machine Status Word is loaded from the source operand. This instruction may be used to switch to protected mode. If so, then it must be followed by an intra-segment jump to flush the instruction queue. LMSW will not switch back to Real Address Mode. LMSW appears only in operating systems software. It does not appear in applications programs. Protected Mode Exceptions #GP(0) if the current privilege level is not 0. #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 13 for a word operand at offset 0FFFFH. LOCK‘‘Assert BUS LOCK Signal Opcode Instruction Clocks Description F0 LOCK 0 Assert BUSLOCK signal for the next instruction Flags Modified None Flags Undefined None Operation LOCK is a prefix that will cause the BUS LOCK signal of the 80286 to be asserted for the duration of the instruction that it prefixes. In a multiprocessor environment, this signal should be used to ensure that the 80286 has exclusive use of any shared memory while BUS LOCK is asserted. The read-modify-write sequence typically used to implement TEST-AND-SET in the 80286 is the XCHG instruction. The 80286 LOCK prefix activates the lock signal for the following instructions: MOVS, INS, and OUTS. XCHG always asserts BUS LOCK regardless of the presence or absence of the LOCK prefix. Protected Mode Exceptions #GP(0) if the current privilege level is bigger (less privileged) than the I/O privilege level. Other exceptions may be generated by the subsequent (locked) instruction. Real Address Mode Exceptions None. Exceptions may still be generated by the subsequent (locked) instruction. LODS/LODSB/LODSW‘‘Load String Operand Opcode Instruction Clocks Description AC LODS mb 5 Load byte [SI] into AL AD LODS mw 5 Load word [SI] into AX AC LODSB 5 Load byte DS:[SI] into AL AD LODSW 5 Load word DS:[SI] into AX Flags Modified None Flags Undefined None Operation LODS loads the AL or AX register with the memory byte or word at SI. After the transfer is made, SI is automatically advanced. If the direction flag is 0 (CLD was executed), SI increments; if the direction flag is 1 (STD was executed), SI decrements. SI increments or decrements by 1 if a byte was moved; by 2 if a word was moved. Protected Address Mode Exceptions #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 13 for a word operand at offset 0FFFFH. LOOP/LOOPcond‘‘Loop Control with CX Counter Opcode Instruction Clocks Description E2 cb LOOP cb 8,noj=4 DEC CX; jump short if CX<>0 E1 cb LOOPE cb 8,noj=4 DEC CX; jump short if CX<>E0 and equal (ZF=1) E0 cb LOOPNE cb 8,noj=4 DEC CX; jump short if CX<>E0 and not equal (ZF=0) E0 cb LOOPNZ cb 8,noj=4 DEC CX; jump short if CX<>E0 and ZF=0 E1 cb LOOPZ cb 8,noj=4 DEC CX; jump short if CX<>E0 and zero (ZF=1) Flags Modified None Flags Undefined None Operation LOOP first decrements the CX register without changing any of the flags. Then, conditions are checked as given in the description above for the form of LOOP being used. If the conditions are met, then an intra-segment jump is made. The destination to LOOP is in the range from 126 (decimal) bytes before the instruction to 127 bytes beyond the instruction. The LOOP instructions are intended to provide iteration control and to combine loop index management with conditional branching. To use the LOOP instruction you load an unsigned iteration count into CX, then code the LOOP at the end of a series of instructions to be iterated. The destination of LOOP is a label that points to the beginning of the iteration. Protected Address Mode Exceptions #GP(0) if the offset jumped to is beyond the limits of the current code segment. Real Address Mode Exceptions None LSL‘‘Load Segment Limit Opcode Instruction Clocks Description 0F 03 /r LSL rw,ew 14,mem=16 Load: rw = Segment Limit, selector ew Flags Modified Zero Flags Undefined None Operation If the descriptor denoted by the selector in the second (memory or register) operand is visible at the CPL, a word that consists of the limit field of the descriptor is loaded into the left operand, which must be a register. The value is the limit field for that segment. The zero flag is set if the loading was performed (that is, if the selector is non-null, the selector index is within the descriptor table limits, the descriptor is a non-conforming segment descriptor with DPL  CPL, and the descriptor DPL  selector RPL); the zero flag is cleared otherwise. The LSL instruction returns only the limit field of segments, task state segments, and local descriptor tables. The interpretation of the limit value depends on the type of segment. The selector operand's value cannot result in a protection exception. Protected Address Mode Exceptions #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 6; LSL is not recognized in Real Address mode. LTR‘‘Load Task Register Opcode Instruction Clocks Description 0F 00 /3 LTR ew 17,mem=19 Load EA word into Task Register Flags Modified None Flags Undefined None Operation The Task Register is loaded from the source register or memory location given by the operand. The loaded TSS is marked busy. A task switch operation does not occur. LTR appears only in operating systems software. It is not used in applications programs. Protected Address Mode Exceptions #GP for an illegal memory operand effective address in the CS, DS, or ES segments; #SS for an illegal address in the SS segment. #GP(0) if the current privilege level is not 0. #GP (selector) if the object named by the source selector is not a TSS or is already busy. #NP (selector) if the TSS is marked not present. Real Address Mode Exceptions Interrupt 6; LTR is not recognized in Real Address mode. MOV‘‘Move Data Opcode Instruction Clocks Description 88 /r MOV eb,rb 2,mem=3 Move byte register into EA byte 89 /r MOV ew,rw 2,mem=3 Move word register into EA word 8A /r MOV rb,eb 2,mem=5 Move EA byte into byte register 8B /r MOV rw,ew 2,mem=5 Move EA word into word register 8C /0 MOV ew,ES 2,mem=3 Move ES into EA word 8C /1 MOV ew,CS 2,mem=3 Move CS into EA word 8C /2 MOV ew,SS 2,mem=3 Move SS into EA word 8C /3 MOV ew,DS 2,mem=3 Move DS into EA word 8E /0 MOV ES,mw 5,pm=19 Move memory word into ES 8E /0 MOV ES,rw 2,pm=17 Move word register into ES 8E /2 MOV SS,mw 5,pm=19 Move memory word into SS 8E /2 MOV SS,rw 2,pm=17 Move word register into SS 8E /3 MOV DS,mw 5,pm=19 Move memory word into DS 8E /3 MOV DS,rw 2,pm=17 Move word register into DS A0 dw MOV AL,xb 5 Move byte variable (offset dw) into AL A1 dw MOV AX,xw 5 Move word variable (offset dw=) into AX A2 dw MOV xb,AL 3 Move AL into byte variable (offset dw=) A3 dw MOV xw,AX 3 Move AX into word register (offset dw=) B0+ rb db MOV rb,db 2 Move immediate byte into byte register B8+ rw dw MOV rw,dw 2 Move immediate word into word register C6 /0 db MOV eb,db 2,mem=3 Move immediate byte into EA byte C7 /0 dw MOV ew,dw 2,mem=3 Move immediate word into EA word Flags Modified None Flags Undefined None Operation The second operand is copied to the first operand. If the destination operand is a segment register (DS, ES, or SS), then the associated segment register cache is also loaded. The data for the cache is obtained from the descriptor table entry for the selector given. A null selector (values 0000-0003) can be loaded into DS and ES registers without causing a protection exception. Any use of a segment register with a null selector to address memory will cause #GP(0) exception. No memory reference will occur. Any move into SS will inhibit all interrupts until after the execution of the next instruction. Following is a listing of the protected-mode checks and actions taken in the loading of a segment register: If SS is loaded: If selector is null then #GP(0) Selector index must be within its descriptor table limits else #GP (selector) Selector's RPL must equal CPL else #GP (selector) AR byte must indicate a writable data segment else #GP (selector) DPL in the AR byte must equal CPL else #GP (selector) Segment must be marked PRESENT else #SS (selector) Load SS with selector Load SS cache with descriptor If ES or DS is loaded with non-null selector Selector index must be within its descriptor table limits else #GP (selector) AR byte must indicate data or readable code segment else #GP (selector) If data or non-conforming code, then both the RPL and the CPL must be less than or equal to DPL in AR byte else #GP (selector) Segment must be marked PRESENT else #NP (selector) Load segment register with selector Load segment register cache with descriptor If ES or DS is loaded with a null selector: Load segment register with selector Clear descriptor valid bit Real Address Mode Exceptions Interrupt 13 for a word operand at offset 0FFFFH. MOVS/MOVSB/MOVSW‘‘Move Data from String to String Opcode Instruction Clocks Description A4 MOVS mb,mb 5 Move byte [SI] to ES:[DI] A5 MOVS mw,mw 5 Move word [SI] to ES:[DI] A4 MOVSB 5 Move byte DS:[SI] to ES:[DI] A5 MOVSW 5 Move word DS:[SI] to ES:[DI] Flags Modified None Flags Undefined None Operation MOVS copies the byte or word at [SI] to the byte or word at ES:[DI]. The destination operand must be addressable from the ES register; no segment override is possible. A segment override may be used for the source operand. After the data movement is made, both SI and DI are automatically advanced. If the direction flag is 0 (CLD was executed), the registers increment; if the direction flag is 1 (STD was executed), the registers decrement. The registers increment or decrement by 1 if a byte was moved; by 2 if a word was moved. MOVS can be preceded by the REP prefix for block movement of CX bytes or words. Refer to the REP instruction for details of this operation. Protected Address Mode Exceptions #GP(0) if the destination is in a non-writable segment. #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 13 for a word operand at offset 0FFFFH. MUL‘‘Unsigned Multiplication of AL or AX Opcode Instruction Clocks Description F6 /4 MUL eb 13,mem=16 Unsigned multiply (AX = AL * EA byte) F7 /4 MUL ew 21,mem=24 Unsigned multiply (DXAX = AX * EA word) Flags Modified Overflow, carry Flags Undefined Sign, zero, auxiliary carry, parity Operation If MUL has a byte operand, then the byte is multiplied by AL, and the result is left in AX. Carry and overflow are set to 0 if AH is 0; they are set to 1 otherwise. If MUL has a word operand, then the word is multiplied by AX, and the result is left in DX:AX. DX contains the high order 16 bits of the product. Carry and overflow are set to 0 if DX is 0; they are set to 1 otherwise. Protected Address Mode Exceptions #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 13 for a word operand at offset 0FFFFH. NEG‘‘Two's Complement Negation Opcode Instruction Clocks Description F6 /3 NEG eb 2,mem=7 Two's complement negate EA byte F7 /3 NEG ew 2,mem=7 Two's complement negate EA word Flags Modified Overflow, sign, zero, auxiliary carry, parity, carry Flags Undefined None Operation The two's complement of the register or memory operand replaces the old operand value. Likewise, the operand is subtracted from zero, and the result is placed in the operand. The carry flag is set to 1 except when the input operand is zero, in which case the carry flag is cleared to 0. Protected Address Mode Exceptions #GP(0) if the result is in a non-writable segment. #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 13 for a word operand at offset 0FFFFH. NOP‘‘No OPERATION Opcode Instruction Clocks Description 90 NOP 3 No OPERATION Flags Modified None Flags Undefined None Operation Performs no operation. NOP is a one-byte filler instruction that takes up space but affects none of the machine context except IP. Protected Address Mode Exceptions None Real Address Mode Exceptions None NOT‘‘One's Complement Negation Opcode Instruction Clocks Description F6 /2 NOT eb 2,mem=7 Reverse each bit of EA byte F7 /2 NOT ew 2,mem=7 Reverse each bit of EA word Flags Modified None Flags Undefined None Operation The operand is inverted; that is, every 1 becomes a 0 and vice versa. Protected Address Mode Exceptions #GP(0) if the result is in a non-writable segment. #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 13 for a word operand at offset 0FFFFH. OR‘‘Logical Inclusive OR Opcode Instruction Clocks Description 08 /r OR eb,rb 2,mem=7 Logical-OR byte register into EA byte 09 /r OR ew,rw 2,mem=7 Logical-OR word register into EA word 0A /r OR rb,eb 2,mem=7 Logical-OR EA byte into byte register 0B /r OR rw,ew 2,mem=7 Logical-OR EA word into word register 0C db OR AL,db 3 Logical-OR immediate byte into AL 0D dw OR AX,dw 3 Logical-OR immediate word into AX 80 /1 db OR eb,db 3,mem=7 Logical-OR immediate byte into EA byte 81 /1 dw OR ew,dw 3,mem=7 Logical-OR immediate word into EA word Flags Modified Overflow=0, sign, zero, parity, carry=0 Flags Undefined Auxiliary carry Operation This instruction computes the inclusive OR of the two operands. Each bit of the result is 0 if both corresponding bits of the operands are 0; each bit is 1 otherwise. The result is placed in the first operand. Protected Address Mode Exceptions #GP(0) if the result is in a non-writable segment. #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 13 for a word operand at offset 0FFFFH. OUT‘‘Output to Port Opcode Instruction Clocks Description E6 db OUT db,AL 3 Output byte AL to immediate port number db E7 db OUT db,AX 3 Output word AX to immediate port number db EE OUT DX,AL 3 Output byte AL to port number DX EF OUT DX,AX 3 Output word AX to port number DX Flags Modified None Flags Undefined None Operation OUT transfers a data byte or data word from the register (AL or AX) given as the second operand to the output port numbered by the first operand. You can output to any port from 0-65535 by placing the port number in the DX register then using an OUT instruction with DX as the first operand. If the instruction contains an 8-bit port ID, that value is zero-extended to 16 bits. Intel reserves I/O port addresses 00F8H through 00FFH; these addresses should not be used. Protected Address Mode Exceptions #GP(0) if the current privilege level is bigger (has less privilege) than IOPL, which is the privilege level found in the flags register. Real Address Mode Exceptions None OUTS/OUTSB/OUTSW‘‘Output String to Port Opcode Instruction Clocks Description 6E OUTS DX,eb 5 Output byte [SI] to port number DX 6F OUTS DX,ew 5 Output word [SI] to port number DX 6E OUTSB 5 Output byte DS:[SI] to port number DX 6F OUTSW 5 Output word DS:[SI] to port number DX Flags Modified None Flags Undefined None Operation OUTS transfers data from the memory byte or word at SI to the output port numbered by the DX register. OUTS does not allow the specification of the port number as an immediate value. The port must be addressed through the DX register. After the transfer is made, SI is automatically advanced. If the direction flag is 0 (CLD was executed), SI increments; if the direction flag is 1 (STD was executed), SI decrements. SI increments or decrements by 1 if a byte was moved; by 2 if a word was moved. OUTS can be preceded by the REP prefix for block output of CX bytes or words. Refer to the REP instruction for details of this operation. Intel reserves I/O port addresses 00F8H through 00FFH; these addresses should not be used. ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ NOTE Not all output devices can handle the rate at which this instruction transfers data. ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Protected Mode Exceptions #GP(0) if CPL > IOPL. #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 13 for a word operand at offset 0FFFFH. POP‘‘Pop a Word from the Stack Opcode Instruction Clocks Description 1F POP DS 5,pm=20 Pop top of stack into DS 07 POP ES 5,pm=20 Pop top of stack into ES 17 POP SS 5,pm=20 Pop top of stack into SS 8F /0 POP mw 5 Pop top of stack into memory word 58+rw POP rw 5 Pop top of stack into word register Flags Modified None Flags Undefined None Operation The word on the top of the 80286 stack, addressed by SS:SP, replaces the previous contents of the memory, register, or segment register operand. The stack pointer SP is incremented by 2 to point to the new top of stack. If the destination operand is another segment register (DS, ES, or SS), the value popped must be a selector. In protected mode, loading the selector initiates automatic loading of the descriptor information associated with that selector into the hidden part of the segment register; loading also initiates validation of both the selector and the descriptor information. A null value (0000-0003) may be loaded into the DS or ES register without causing a protection exception. Attempts to reference memory using a segment register with a null value will cause #GP(0) exception. No memory reference will occur. The saved value of the segment register will be null. A POP SS instruction will inhibit all interrupts, including NMI, until after the execution of the next instruction. This permits a POP SP instruction to be performed first. Following is a listing of the protected-mode checks and actions taken in the loading of a segment register: If SS is loaded: If selector is null then #GP(0) Selector index must be within its descriptor table limits else #GP (selector) Selector's RPL must equal CPL else #GP (selector) AR byte must indicate a writable data segment else #GP (selector) DPL in the AR byte must equal CPL else #GP (selector) Segment must be marked PRESENT else #SS (selector) Load SS register with selector Load SS cache with descriptor If ES or DS is loaded with non-null selector: AR byte must indicate data or readable code segment else #GP (selector) If data or non-conforming code, then both the RPL and the CPL must be less than or equal to DPL in AR byte else #GP (selector) Segment must be marked PRESENT else #NP (selector) Load segment register with selector Load segment register cache with descriptor If ES or DS is loaded with a null selector: Load segment register with selector Clear valid bit in cache Protected Mode Exceptions If a segment register is being loaded, #GP, #SS, and #NP, as described in the listing above. Otherwise, #SS(0) if the current top of stack is not within the stack segment. #GP(0) if the destination is in a non-writable segment. #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 13 for a word operand at offset 0FFFFH. POPA‘‘Pop All General Registers Opcode Instruction Clocks Description 61 POPA 19 Pop in order: DI,SI,BP,SP,BX,DX,CX,AX Flags Modified None Flags Undefined None Operation POPA pops the eight general registers given in the description above, except that the SP value is discarded instead of loaded into SP. POPA reverses a previous PUSHA, restoring the general registers to their values before PUSHA was executed. The first register popped is DI. Protected Mode Exceptions #SS(0) if the starting or ending stack address is not within the stack segment. Real Address Mode Exceptions Interrupt 13 for a word operand at offset 0FFFFH. POPF‘‘Pop from Stack into the Flags Register Opcode Instruction Clocks Description 9D POPF 5 Pop top of stack into flags register Flags Modified Entire flags register is popped from stack Flags Undefined None Operation The top of the 80286 stack, pointed to by SS:SP, is copied into the 80286 flags register. The stack pointer SP is incremented by 2 to point to the new top of stack. The flags, from the top bit (bit 15) to the bottom (bit 0), are as follows: undefined, nested task, I/O privilege level (2 bits), overflow, direction, interrupts enabled, trap, sign, zero, undefined, auxiliary carry, undefined, parity, undefined, and carry. The I/O privilege level will be altered only when executing at privilege level 0. The interrupt enable flag will be altered only when executing at a level at least as privileged as the I/O privilege level. If you execute a POPF instruction with insufficient privilege, there will be no exception nor will the privileged bits be changed. Protected Mode Exceptions #SS(0) if the top of stack is not within the stack segment. Real Address Mode Exceptions Interrupt 13 for a word operand at 0FFFFH. In real mode the NT and IOPL bits will not be modified. PUSH‘‘Push a Word onto the Stack Opcode Instruction Clocks Description 06 PUSH ES 3 Push ES 0E PUSH CS 3 Push CS 16 PUSH SS 3 Push SS 1E PUSH DS 3 Push DS 50+ rw PUSH rw 3 Push word register FF /6 PUSH mw 5 Push memory word 68 dw PUSH dw 3 Push immediate word 6A db PUSH db 3 Push immediate sign-extended byte Flags Modified None Flags Undefined None Operation The stack pointer SP is decremented by 2, and the operand is placed on the new top of stack, which is pointed to by SS:SP. The 80286 PUSH SP instruction pushes the value of SP as it existed before the instruction. This differs from the 8086, which pushes the new (decremented by 2) value. Protected Mode Exceptions #SS(0) if the new value of SP is outside the stack segment limit. #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions None; the 80286 will shut down if SP = 1 ‘‘due to lack of stack space. PUSHA‘‘Push All General Registers Opcode Instruction Clocks Description 60 PUSHA 17 Push in order: AX,CX,DX,BX,original SP,BP,SI,DI Flags Modified None Flags Undefined None Operation PUSHA saves the registers noted above on the 80286 stack. The stack pointer SP is decremented by 16 to hold the 8 word values. Since the registers are pushed onto the stack in the order in which they were given, they will appear in the 16 new stack bytes in the reverse order. The last register pushed is DI. Protected Mode Exceptions #SS(0) if the starting or ending address is outside the stack segment limit. Real Address Mode Exceptions The 80286 will shut down if SP = 1, 3, or 5 before executing PUSHA. If SP = 7, 9, 11, 13, or 15, exception 13 will occur. PUSHF‘‘Push Flags Register onto the Stack Opcode Instruction Clocks Description 9C PUSHF 3 Push flags register Flags Modified None Flags Undefined None Operation The stack pointer SP is decremented by 2, and the 80286 flags register is copied to the new top of stack, which is pointed to by SS:SP. The flags, from the top bit (15) to the bottom bit (0), are as follows: undefined, nested task, I/O privilege level (2 bits), overflow, direction, interrupts enabled, trap, sign, zero, undefined, auxiliary carry, undefined, parity, undefined, and carry. Protected Mode Exceptions #SS(0) if the new value of SP is outside the stack segment limit. Real Address Mode Exceptions None; the 80286 will shut down if SP=1 due‘‘to lack of stack space. RCL/RCR/ROL/ROR‘‘Rotate Instructions Opcode Instruction Clocks-N Add 1 clock to the times shown for each rotate made Description D0 /2 RCL eb,1 2,mem=7 Rotate 9-bits (CF, EA byte) left once D2 /2 RCL eb,CL 5,mem=8 Rotate 9-bits (CF, EA byte) left CL times C0 /2 db RCL eb,db 5,mem=8 Rotate 9-bits (CF, EA byte) left db times D1 /2 RCL ew,1 2,mem=7 Rotate 17-bits (CF, EA word) left once D3 /2 RCL ew,CL 5,mem=8 Rotate 17-bits (CF, EA word) left CL times C1 /2 db RCL ew,db 5,mem=8 Rotate 17-bits (CF, EA word) left db times D0 /3 RCR eb,1 2,mem=7 Rotate 9-bits (CF, EA byte) right once D2 /3 RCR eb,CL 5,mem=8 Rotate 9-bits (CF, EA byte) right CL times C0 /3 db RCR eb,db 5,mem=8 Rotate 9-bits (CF, EA byte) right db times D1 /3 RCR ew,1 2,mem=7 Rotate 17-bits (CF, EA word) right once D3 /3 RCR ew,CL 5,mem=8 Rotate 17-bits (CF, EA word) right CL times C1 /3 db RCR ew,db 5,mem=8 Rotate 17-bits (CF, EA word) right db times D0 /0 ROL eb,1 2,mem=7 Rotate 8-bit EA byte left once D2 /0 ROL eb,CL 5,mem=8 Rotate 8-bit EA byte left CL times C0 /0 db ROL eb,db 5,mem=8 Rotate 8-bit EA byte left db times D1 /0 ROL ew,1 2,mem=7 Rotate 16-bit EA word left once D3 /0 ROL ew,CL 5,mem=8 Rotate 16-bit EA word left CL times C1 /0 db ROL ew,db 5,mem=8 Rotate 16-bit EA word left db times D0 /1 ROR eb,1 2,mem=7 Rotate 8-bit EA byte right once D2 /1 ROR eb,CL 5,mem=8 Rotate 8-bit EA byte right CL times C0 /1 db ROR eb,db 5,mem=8 Rotate 8-bit EA byte right db times D1 /1 ROR ew,1 2,mem=7 Rotate 16-bit EA word right once D3 /1 ROR ew,CL 5,mem=8 Rotate 16-bit EA word right CL times C1 /1 db ROR ew,db 5,mem=8 Rotate 16-bit EA word right db times Flags Modified Overflow (only for single rotates), carry Flags Undefined Overflow for multi-bit rotates Operation Each rotate instruction shifts the bits of the register or memory operand given. The left rotate instructions shift all of the bits upward, except for the top bit, which comes back around to the bottom. The right rotate instructions do the reverse: the bits shift downward, with the bottom bit coming around to the top. For the RCL and RCR instructions, the carry flag is part of the rotated quantity. RCL shifts the carry flag into the bottom bit and shifts the top bit into the carry flag; RCR shifts the carry flag into the top bit and shifts the bottom bit into the carry flag. For the ROL and ROR instructions, the original value of the carry flag is not a part of the result; nonetheless, the carry flag receives a copy of the bit that was shifted from one end to the other. The rotate is repeated the number of times indicated by the second operand, which is either an immediate number or the contents of the CL register. To reduce the maximum execution time, the 80286 does not allow rotation counts greater than 31. If a rotation count greater than 31 is attempted, only the bottom five bits of the rotation are used. The 8086 does not mask rotate counts. The overflow flag is set only for the single-rotate (second operand = 1) forms of the instructions. The OF bit is set to be accurate if a shift of length 1 is done. Since it is undefined for all other values, including a zero shift, it can always be set for the count-of-1 case regardless of the actual count. For left shifts/rotates, the CF bit after the shift is XORed with the high-order result bit. For right shifts/rotates, the high-order two bits of the result are XORed to get OF. Neither flag bit is modified when the count value is zero. Protected Mode Exceptions #GP(0) if the result is in a non-writable segment. #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 13 for a word operand at offset 0FFFFH. REP/REPE/REPNE‘‘Repeat Following String Operation Opcode Instruction Clocks N denotes the number of iterations actually executed. Description F3 6C REP INS eb,DX 5+4 CX Input CX bytes from port DX into ES:[DI] F3 6D REP INS ew,DX 5+4 CX Input CX words from port DX into ES:[DI] F3 6C REP INSB 5+4 CX Input CX bytes from port DX into ES:[DI] F3 6D REP INSW 5+4 CX Input CX words from port DX into ES:[DI] F3 A4 REP MOVS mb,mb 5+4 CX Move CX bytes from [SI] to ES:[DI] F3 A5 REP MOVS mw,mw 5+4 CX Move CX words from [SI] to ES:[DI] F3 A4 REP MOVSB 5+4 CX Move CX bytes from DS:[SI] to ES:[DI] F3 A5 REP MOVSW 5+4 CX Move CX words from DS:[SI] to ES:[DI] F3 6E REP OUTS DX,eb 5+4 CX Output CX bytes from [SI] to port DX F3 6F REP OUTS DX,ew 5+4 CX Output CX words from [SI] to port DX F3 6E REP OUTSB 5+4 CX Output CX bytes from DS:[SI] to port DX F3 6F REP OUTSW 5+4 CX Output CX words from DS:[SI] to port DX F3 AA REP STOS mb 4+3 CX Fill CX bytes at ES:[DI] with AL F3 AB REP STOS mw 4+3 CX Fill CX words at ES:[DI] with AX F3 AA REP STOSB 4+3 CX Fill CX bytes at ES:[DI] with AL F3 AB REP STOSW 4+3 CX Fill CX words at ES:[DI] with AX F3 A6 REPE CMPS mb,mb 5+9 N Find nonmatching bytes in ES:[DI] and [SI] F3 A7 REPE CMPS mw,mw 5+9 N Find nonmatching words in ES:[DI] and [SI] F3 A6 REPE CMPSB 5+9 N Find nonmatching bytes in ES:[DI] and DS:[SI] F3 A7 REPE CMPSW 5+9 N Find nonmatching words in ES:[DI] and DS:[SI] F3 AE REPE SCAS mb 5+8 N Find non-AL byte starting at ES:[DI] F3 AF REPE SCAS mw 5+8 N Find non-AX word starting at ES:[DI] F3 AE REPE SCASB 5+8 N Find non-AL byte starting at ES:[DI] F3 AF REPE SCASW 5+8 N Find non-AX word starting at ES:[DI] F2 A6 REPNE CMPS mb,mb 5+9 N Find matching bytes in ES:[DI] and [SI] F2 A7 REPNE CMPS mw,mw 5+9 N Find matching words in ES:[DI] and [SI] F2 A6 REPNE CMPSB 5+9 N Find matching bytes in ES:[DI] and DS:[SI] F2 A7 REPNE CMPSW 5+9 N Find matching words in ES:[DI] and DS:[SI] F2 AE REPNE SCAS mb 5+8 N Find AL, starting at ES:[DI] F2 AF REPNE SCAS mw 5+8 N Find AX, starting at ES:[DI] F2 AE REPNE SCASB 5y+8 N Find AL, starting at ES:[DI] F2 AF REPNE SCASW 5+8 N Find AX, starting at ES:[DI] Flags Modified By CMPS and SCAS, none by REP Flags Undefined None Operation REP, REPE, and REPNE are prefix operations. These prefixes cause the string instruction that follows to be repeated CX times or (for REPE and REPNE) until the indicated condition in the zero flag is no longer met. Thus, REPE stands for "Repeat while equal," REPNE for "Repeat while not equal." The REP prefixes make sense only in the contexts listed above. They cannot be applied to anything other than string operations. Synonymous forms of REPE and REPNE are REPZ and REPNZ, respectively. The REP prefixes apply only to one string instruction at a time. To repeat a block of instructions, use a LOOP construct. The precise action for each iteration is as follows: 1. Check the CX register. If it is zero, exit the iteration and move to the next instruction. 2. Acknowledge any pending interrupts. 3. Perform the string operation once. 4. Decrement CX by 1; no flags are modified. 5. If the string operation is SCAS or CMPS, check the zero flag. If the repeat condition does not hold, then exit the iteration and move to the next instruction. Exit if the prefix is REPE and ZF=0 (the last comparison was not equal), or if the prefix is REPNE and ZF=1 (the last comparison was equal). 6. Go to step 1 for the next iteration. As defined by the individual string-ops, the direction of movement through the block is determined by the direction flag. If the direction flag is 1 (STD was executed), SI and/or DI start at the end of the block and move backward; if the direction flag is 0 (CLD was executed), SI and/or DI start at the beginning of the block and move forward. For repeated SCAS and CMPS operations the repeat can be exited for one of two different reasons: the CX count can be exhausted or the zero flag can fail the repeat condition. Your code will probably want to distinguish between the two cases. It can do so via either the JCXZ instruction or the conditional jumps that test the zero flag (JZ, JNZ, JE, and JNE). Not all input/output ports can handle the rate at which the repeated I/O instructions execute. Protected Mode Exceptions None by REP; exceptions can be generated when the string-op is executed. Real Address Mode Exceptions None by REP; exceptions can be generated when the string-op is executed. RET‘‘Return from Procedure Opcode Instruction Clocks Add 1 clock for each byte in the next instruction executed. Description CB RET 15,pm=25 Return to far caller, same privilege CB RET 55 Return, lesser privilege, switch stacks C3 RET 11 Return to near caller, same privilege CA dw RET dw 15,pm=25 RET (far), same privilege, pop dw bytes CA dw RET dw 55 RET (far), lesser privilege, pop dw bytes C2 dw RET dw 11 RET (near), same privilege, pop dw bytes pushed before Call Flags Modified None Flags Undefined None Operation RET transfers control to a return address located on the stack. The address is usually placed on the stack by a CALL instruction; in that case, the return is made to the instruction that follows the CALL. There is an optional numeric parameter to RET. It gives the number of stack bytes to be released after the return address is popped. These bytes are typically used as input parameters to the procedure called. For the intra-segment return, the address on the stack is a 2-byte quantity popped into IP. The CS register is unchanged. For the inter-segment return, the address on the stack is a 4-byte-long pointer. The offset is popped first, followed by the selector. In real address mode, CS and IP are directly loaded. In protected mode, an inter-segment return causes the processor to consult the descriptor addressed by the return selector. The AR byte of the descriptor must indicate a code segment of equal or less privilege (of greater or equal numeric value) than the current privilege level. Returns to a lesser privilege level cause the stack to be reloaded from the value saved beyond the parameter block. The DS and ES segment registers may be set to zero by the inter-segment RET instruction. If these registers refer to segments which cannot be used by the new privilege level, they are set to zero to prevent unauthorized access. The following list of checks and actions describes the protected-mode inter-segment return in detail. Inter-segment RET: Second word on stack must be within stack limits else #SS(0) Return selector RPL must be  CPL else #GP (return selector) If return selector RPL = CPL then RETURN TO SAME LEVEL: Return selector must be non-null else #GP(0) Selector index must be within its descriptor table limits else #GP (selector) Descriptor AR byte must indicate code segment else #GP (selector) If non-conforming then code segment DPL must equal CPL else #GP (selector) If conforming then code segment DPL must be Ύ CPL else #GP (selector) Code segment must be PRESENT else #NP (selector) Top word on stack must be within stack limits else #SS(0) IP must be in code segment limit else #GP(0) Load CS:IP from stack Load CS-cache with descriptor Increment SP by 4 plus the immediate offset if it exists Else RETURN TO OUTER PRIVILEGE LEVEL: Top (8+immediate) bytes on stack must be within stack limits else #SS(0) Examine return CS selector (at SP+2) and associated descriptor: Selector must be non-null else #GP(0) Selector index must be within its descriptor table limits else #GP (selector) Descriptor AR byte must indicate code segment else #GP (selector) If non-conforming then code segment DPL must equal return selector RPL else #GP (selector) If conforming then code segment DPL must be Ύ return selector RPL else #GP (selector) Segment must be PRESENT else #NP (selector) Examine return SS selector (at SP+6+imm) and associated descriptor: Selector must be non-null else #GP(0) Selector index must be within its descriptor table limits else #GP (selector) Selector RPL must equal the RPL of the return CS selector else #GP (selector) Descriptor AR byte must indicate a writable data segment else #GP (selector) Descriptor DPL must equal the RPL of the return CS selector else #GP (selector) Segment must be PRESENT else #SS (selector) IP must be in code segment limit else # GP(0) Set CPL to the RPL of the return CS selector Load CS:IP from stack Set CS RPL to CPL Increment SP by 4 plus the immediate offset if it exists Load SS:SP from stack Load the CS-cache with the return CS descriptor Load the SS-cache with the return SS descriptor For each of ES and DS: If the current register setting is not valid for the outer level, set the register to null (selector = AR = 0) To be valid, the register setting must satisfy the following properties: Selector index must be within descriptor table limits Descriptor AR byte must indicate data or readable code segment If segment is data or non-conforming code, then: DPL must be  CPL, or DPL must be  RPL Protected Mode Exceptions #GP, #NP, or #SS, as described in the above listing. Real Address Mode Exceptions Interrupt 13 if the stack pop wraps around from 0FFFFH to 0. SAHF‘‘Store AH into Flags Opcode Instruction Clocks Description 9E SAHF 2 Store AH into flags SF ZF xx AF xx PF xx CF Flags Modified Sign, zero, auxiliary carry, parity, carry Flags Undefined None Operation The flags listed above are loaded with values from the AH register, from bits 7, 6, 4, 2, and 0, respectively. Protected Mode Exceptions None Real Address Mode Exceptions None SAL/SAR/SHL/SHR‘‘Shift Instructions Opcode Instruction Clocks-N Add 1 clock to the times shown for each shift performed Description D0 /4 SAL eb,1 2,mem=7 Multiply EA byte by 2, once D2 /4 SAL eb,CL 5,mem=8 Multiply EA byte by 2, CL times C0 /4 db SAL eb,db 5,mem=8 Multiply EA byte by 2, db times D1 /4 SAL ew,1 2,mem=7 Multiply EA word by 2, once D3 /4 SAL ew,CL 5,mem=8 Multiply EA word by 2, CL times C1 /4 db SAL ew,db 5,mem=8 Multiply EA word by 2, db times D0 /7 SAR eb,1 2,mem=7 Signed divide EA byte by 2, once D2 /7 SAR eb,CL 5,mem=8 Signed divide EA byte by 2, CL times C0 /7 db SAR eb,db 5,mem=8 Signed divide EA byte by 2, db times D1 /7 SAR ew,1 2,mem=7 Signed divide EA word by 2, once D3 /7 SAR ew,CL 5,mem=8 Signed divide EA word by 2, CL times C1 /7 db SAR ew,db 5,mem=8 Signed divide EA word by 2, db times D0 /5 SHR eb,1 2,mem=7 Unsigned divide EA byte by 2, once D2 /5 SHR eb,CL 5,mem=8 Unsigned divide EA byte by 2, CL times C0 /5 db SHR eb,db 5,mem=8 Unsigned divide EA byte by 2, db times D1 /5 SHR ew,1 2,mem=7 Unsigned divide EA word by 2, once D3 /5 SHR ew,CL 5,mem=8 Unsigned divide EA word by 2, CL times Flags Modified Overflow (only for single-shift form), carry, zero, parity, sign Flags Undefined Auxiliary carry; also overflow for multibit shifts (only). Operation SAL (or its synonym SHL) shifts the bits of the operand upward. The high-order bit is shifted into the carry flag, and the low-order bit is set to 0. SAR and SHR shift the bits of the operand downward. The low-order bit is shifted into the carry flag. The effect is to divide the operand by 2. SAR performs a signed divide: the high-order bit remains the same. SHR performs an unsigned divide: the high-order bit is set to 0. The shift is repeated the number of times indicated by the second operand, which is either an immediate number or the contents of the CL register. To reduce the maximum execution time, the 80286 does not allow shift counts greater than 31. If a shift count greater than 31 is attempted, only the bottom five bits of the shift count are used. The 8086 uses all 8 bits of the shift count. The overflow flag is set only if the single-shift forms of the instructions are used. For left shifts, it is set to 0 if the high bit of the answer is the same as the result carry flag (i.e., the top two bits of the original operand were the same); it is set to 1 if they are different. For SAR it is set to 0 for all single shifts. For SHR, it is set to the high-order bit of the original operand. Neither flag bit is modified when the count value is zero. Protected Mode Exceptions #GP(0) if the operand is in a non-writable segment. #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 13 for a word operand at offset 0FFFFH. SBB‘‘Integer Subtraction With Borrow Opcode Instruction Clocks Description 18 /r SBB eb,rb 2,mem=7 Subtract with borrow byte register from EA byte 19 /r SBB ew,rw 2,mem=7 Subtract with borrow word register from EA word 1A /r SBB rb,eb 2,mem=7 Subtract with borrow EA byte from byte register 1B /r SBB rw,ew 2,mem=7 Subtract with borrow EA word from word register 1C db SBB AL,db 3 Subtract with borrow imm. byte from AL 1D dw SBB AX,dw 3 Subtract with borrow imm. word from AX 80 /3 db SBB eb,db 3,mem=7 Subtract with borrow imm. byte from EA byte 81 /3 dw SBB ew,dw 3,mem=7 Subtract with borrow imm. word from EA word 83 /3 db SBB ew,db 3,mem=7 Subtract with borrow imm. byte from EA word Flags Modified Overflow, sign, zero, auxiliary carry, parity, carry Flags Undefined None Operation The second operand is added to the carry flag and the result is subtracted from the first operand. The first operand is replaced with the result of the subtraction, and the flags are set accordingly. When a byte-immediate value is subtracted from a word operand, the immediate value is first sign-extended. Protected Mode Exceptions #GP(0) if the result is in a non-writable segment. #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 13 for a word operand at offset 0FFFFH. SCAS/SCASB/SCASW‘‘Compare String Data Opcode Instruction Clocks Description AE SCAS mb 7 Compare bytes AL - ES:[DI], advance DI AF SCAS mw 7 Compare words AX - ES:[DI], advance DI AE SCASB 7 Compare bytes AL - ES:[DI], advance DI AF SCASW 7 Compare words AX - ES:[DI], advance DI Flags Modified Overflow, sign, zero, auxiliary carry, parity, carry Flags Undefined None Operation SCAS subtracts the memory byte or word at ES:DI from the AL or AX register. The result is discarded; only the flags are set. The operand must be addressable from the ES register; no segment override is possible. After the comparison is made, DI is automatically advanced. If the direction flag is 0 (CLD was executed), DI increments; if the direction flag is 1 (STD was executed), DI decrements. DI increments or decrements by 1 if bytes were compared; by 2 if words were compared. SCAS can be preceded by the REPE or REPNE prefix for a block search of CX bytes or words. Refer to the REP instruction for details of this operation. Protected Mode Exceptions #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 13 for a word operand at offset 0FFFFH. SGDT/SIDT‘‘Store Global/Interrupt Descriptor Table Register Opcode Instruction Clocks Description 0F 01 /0 SGDT m 11 Store Global Descriptor Table register to m 0F 01 /1 SIDT m 12 Store Interrupt Descriptor Table register to m Flags Modified None Flags Undefined None Operation The contents of the descriptor table register are copied to six bytes of memory indicated by the operand. The LIMIT field of the register goes to the first word at the effective address; the next three bytes get the BASE field of the register; and the last byte is undefined. SGDT and SIDT appear only in operating systems software; they are not used in applications programs. Protected Mode Exceptions #UD if the destination operand is a register. #GP(0) if the destination is in a non-writable segment. #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions These instructions are valid in Real Address mode to facilitate power-up or to reset initialization prior to entering Protected mode. #UD if the destination operand is a register. Interrupt 13 for a word operand at offset 0FFFFH. SLDT‘‘Store Local Descriptor Table Register Opcode Instruction Clocks Description 0F 00 /0 SLDT ew 2,mem=3 Store Local Descriptor Table register to EA word Flags Modified None Flags Undefined None Operation The Local Descriptor Table register is stored in the 2-byte register or memory location indicated by the effective address operand. This register is a selector that points into the Global Descriptor Table. SLDT appears only in operating systems software. It is not used in applications programs. Protected Mode Exceptions #GP(0) if the destination is in a non-writable segment. #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 6; SLDT is not recognized in Real Address mode. SMSW‘‘Store Machine Status Word Opcode Instruction Clocks Description 0F 01 /4 SMSW ew 2,mem=3 Store Machine Status Word to EA word Flags Modified None Flags Undefined None Operation The Machine Status Word is stored in the 2-byte register or memory location indicated by the effective address operand. Protected Mode Exceptions #GP(0) if the destination is in a non-writable segment. #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 13 for a word operand at offset 0FFFFH. STC‘‘Set Carry Flag Opcode Instruction Clocks Description F9 STC 2 Set carry flag Flags Modified Carry=1 Flags Undefined None Operation The carry flag is set to 1. Protected Mode Exceptions None Real Address Mode Exceptions None STD‘‘Set Direction Flag Opcode Instruction Clocks Description FD STD 2 Set direction flag so SI and DI will decrement Flags Modified Direction=1 Flags Undefined None Operation The direction flag is set to 1. This causes all subsequent string operations to decrement the index registers (SI and/or DI) on which they operate. Protected Mode Exceptions None Real Address Mode Exceptions None STI‘‘Set Interrupt Enable Flag Opcode Instruction Clocks Description FB STI 2 Set interrupt enable flag, interrupts enabled Flags Modified Interrupt=1 (enabled) Flags Undefined None Operation The interrupts-enabled flag is set to 1. The 80286 will now respond to external interrupts after executing the STI instruction. Protected Mode Exceptions #GP(0) if the current privilege level is bigger (has less privilege) than the I/O privilege level. Real Address Mode Exceptions None STOS/STOSB/STOSW‘‘Store String Data Opcode Instruction Clocks Description AA STOS mb 3 Store AL to byte ES:[DI], advance DI AB STOS mw 3 Store AX to word ES:[DI], advance DI AA STOSB 3 Store AL to byte ES:[DI], advance DI AB STOSW 3 Store AX to word ES:[DI], advance DI Flags Modified None Flags Undefined None Operation STOS transfers the contents the AL or AX register to the memory byte or word at ES:DI. The operand must be addressable from the ES register; no segment override is possible. After the transfer is made, DI is automatically advanced. If the direction flag is 0 (CLD was executed), DI increments; if the direction flag is 1 (STD was executed), DI decrements. DI increments or decrements by 1 if a byte was moved; by 2 if a word was moved. STOS can be preceded by the REP prefix for a block fill of CX bytes or words. Refer to the REP instruction for details of this operation. Protected Mode Exceptions #GP(0) if the destination is in a non-writable segment. #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 13 for a word operand at offset 0FFFFH. STR‘‘Store Task Register Opcode Instruction Clocks Description 0F 00 /1 STR ew 2,mem=3 Store Task Register to EA word Flags Modified None Flags Undefined None Operation The contents of the Task Register are copied to the 2-byte register or memory location indicated by the effective address operand. Protected Mode Exceptions #GP(0) if the destination is in a non-writable segment. #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 6; STR is not recognized in Real Address mode. SUB‘‘Integer Subtraction Opcode Instruction Clocks Description 28 /r SUB eb,rb 2,mem=7 Subtract byte register from EA byte 29 /r SUB ew,rw 2,mem=7 Subtract word register from EA word 2A /r SUB rb,eb 2,mem=7 Subtract EA byte from byte register 2B /r SUB rw,ew 2,mem=7 Subtract EA word from word register 2C db SUB AL,db 3 Subtract immediate byte from AL 2D dw SUB AX,dw 3 Subtract immediate word from AX 80 /5 db SUB eb,db 3,mem=7 Subtract immediate byte from EA byte 81 /5 dw SUB ew,dw 3,mem=7 Subtract immediate word from EA word 83 /5 db SUB ew,db 3,mem=7 Subtract immediate byte from EA word Flags Modified Overflow, sign, zero, auxiliary carry, parity, carry Flags Undefined None Operation The second operand is subtracted from the first operand, and the first operand is replaced with the result. When a byte-immediate value is subtracted from a word operand, the immediate value is firstsign-extended. Protected Mode Exceptions #GP(0) if the result is in a non-writable segment. #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 13 for a word operand at offset 0FFFFH. TEST‘‘Logical Compare Opcode Instruction Clocks Description 84 /r TEST eb,rb 2,mem=6 AND byte register into EA byte for flags only 84 /r TEST rb,eb 2,mem=6 AND EA byte into byte register for flags only 85 /r TEST ew,rw 2,mem=6 AND word register into EA word for flags only 85 /r TEST rw,ew 2,mem=6 AND EA word into word register for flags only A8 db TEST AL,db 3 AND immediate byte into AL for flags only A9 dw TEST AX,dw 3 AND immediate word into AX for flags only F6 /0 db TEST eb,db 3,mem=6 AND immediate byte into EA byte for flags only F7 /0 dw TEST ew,dw 3,mem=6 AND immediate word into EA word for flags only Flags Modified Overflow=0, sign, zero, parity, carry=0 Flags Undefined Auxiliary carry Operation TEST computes the bit-wise logical AND of the two operands given. Each bit of the result is 1 if both of the corresponding bits of the operands are 1; each bit is 0 otherwise. The result of the operation is discarded; only the flags are modified. Protected Mode Exceptions #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 13 for a word operand at offset 0FFFFH. VERR,VERW‘‘Verify a Segment for Reading or Writing Opcode Instruction Clocks Description 0F 00 /4 VERR ew 14,mem=16 Set ZF=1 if seg. can be read, selector ew 0F 00 /5 VERW ew 14,mem=16 Set ZF=1 if seg. can be written, selector ew Flags Modified Zero Flags Undefined None Operation VERR and VERW expect the 2-byte register or memory operand to contain the value of a selector. The instructions determine whether the segment denoted by the selector is reachable from the current privilege level; the instructions also determine whether it is readable or writable. If the segment is determined to be accessible, the zero flag is set to 1; if the segment is not accessible, it is set to 0. To set ZF, the following conditions must be met: 1. The selector must denote a descriptor within the bounds of the table (GDT or LDT); that is, the selector must be "defined." 2. The selector must denote the descriptor of a code or data segment. 3. If the instruction is VERR, the segment must be readable. If the instruction is VERW, the segment must be a writable data segment. 4. If the code segment is readable and conforming, the descriptor privilege level (DPL) can be any value for VERR. Otherwise, the DPL must be greater than or equal to (have less or the same privilege as) both the current privilege level and the selector's RPL. The validation performed is the same as if the segment were loaded into DS or ES and the indicated access (read or write) were performed. The zero flag receives the result of the validation. The selector's value cannot result in a protection exception. This enables the software to anticipate possible segment access problems. Protected Mode Exceptions The only faults that can occur are those generated by illegally addressing the memory operand which contains the selector. The selector is not loaded into any segment register, and no faults attributable to the selector operand are generated. #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 6; VERR and VERW are not recognized in Real Address Mode. WAIT‘‘Wait Until BUSY Pin Is Inactive (HIGH) Opcode Instruction Clocks Description 9B WAIT 3 Wait until BUSY pin is inactive (HIGH) Flags Modified None Flags Undefined None Operation WAIT suspends execution of 80286 instructions until the BUSY pin is inactive (high). The BUSY pin is driven by the 80287 numeric processor extension. WAIT is issued to ensure that the numeric instruction being executed is complete, and to check for a possible numeric fault (see below). Protected Mode Exceptions #NM if task switch flag in MSW is set. #MF if 80287 has detected an unmasked numeric error. Real Address Mode Exceptions Same as Protected mode. XCHG‘‘Exchange Memory/Register with Register Opcode Instruction Clocks Description 86 /r XCHG eb,rb 3,mem=5 Exchange byte register with EA byte 86 /r XCHG rb,eb 3,mem=5 Exchange EA byte with byte register 87 /r XCHG ew,rw 3,mem=5 Exchange word register with EA word 87 /r XCHG rw,ew 3,mem=5 Exchange EA word with word register 90+ rw XCHG AX,rw 3 Exchange word register with AX 90+ rw XCHG rw,AX 3 Exchange with word register Flags Modified None Flags Undefined None Operation The two operands are exchanged. The order of the operands is immaterial. BUS LOCK is asserted for the duration of the exchange, regardless of the presence or absence of the LOCK prefix or IOPL. Protected Mode Exceptions #GP(0) if either operand is in a non-writable segment. #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 13 for a word operand at offset 0FFFFH. XLAT‘‘Table Look-up Translation Opcode Instruction Clocks Description D7 XLAT mb 5 Set AL to memory byte DS:[BX + unsigned AL] D7 XLATB 5 Set AL to memory byte DS:[BX + unsigned AL] Flags Modified None Flags Undefined None Operation When XLAT is executed, AL should be the unsigned index into a table addressed by DS:BX. XLAT changes the AL register from the table index into the table entry. BX is unchanged. Protected Mode Exceptions #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 13 for a word operand at offset 0FFFFH. XOR‘‘Logical Exclusive OR Opcode Instruction Clocks Description 30 /r XOR eb,rb 2,mem=7 Exclusive-OR byte register into EA byte 31 /r XOR ew,rw 2,mem=7 Exclusive-OR word register into EA word 32 /r XOR rb,eb 2,mem=7 Exclusive-OR EA byte into byte register 33 /r XOR rw,ew 2,mem=7 Exclusive-OR EA word into word register 34 db XOR AL,db 3 Exclusive-OR immediate byte into AL 35 dw XOR AX,dw 3 Exclusive-OR immediate word into AX 80 /6 db XOR eb,db 3,mem=7 Exclusive-OR immediate byte into EA byte 81 /6 dw XOR ew,dw 3,mem=7 Exclusive-OR immediate word into EA word Flags Modified Overflow=0, sign, zero, parity, carry=0 Flags Undefined Auxiliary carry Operation XOR computes the exclusive OR of the two operands. Each bit of the result is 1 if the corresponding bits of the operands are different; each bit is 0 if the corresponding bits are the same. The answer replaces the first operand. Protected Mode Exceptions #GP(0) if the result is in a non-writable segment. #GP(0) for an illegal memory operand effective address in the CS, DS, or ES segments; #SS(0) for an illegal address in the SS segment. Real Address Mode Exceptions Interrupt 13 for a word operand at offset 0FFFFH. Appendix C 8086/8088 Compatibility Considerations ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Software Compatibility Considerations In general, the real address mode 80286 will correctly execute ROM-based 8086/8088 software. The following is a list of the minor differences between 8086 and 80286 (Real mode). 1. Add Six Interrupt Vectors. The 80286 adds six interrupts which arise only if the 8086 program has a hidden bug. These interrupts occur only for instructions which were undefined on the 8086/8088 or if a segment wraparound is attempted. It is recommended that you add an interrupt handler to the 8086 software that is to be run on the 80286, which will treat these interrupts as invalid operations. This additional software does not significantly effect the existing 8086 software because the interrupts do not normally occur and should not already have been used since they are in the interrupt group reserved by Intel. Table C-1 describes the new 80286 interrupts. 2. Do not Rely on 8086/8088 Instruction Clock Counts. The 80286 takes fewer clocks for most instructions than the 8086/8088. The areas to look into are delays between I/O operations, and assumed delays in 8086/8088 operating in parallel with an 8087. 3. Divide Exceptions Point at the DIV Instruction. Any interrupt on the 80286 will always leave the saved CS:IP value pointing at the beginning of the instruction that failed (including prefixes). On the 8086, the CS:IP value saved for a divide exception points at the next instruction. 4. Use Interrupt 16 for Numeric Exceptions. Any 80287 system must use interrupt vector 16 for the numeric error interrupt. If an 8086/8087 or 8088/8087 system uses another vector for the 8087 interrupt, both vectors should point at the numeric error interrupt handler. 5. Numeric Exception Handlers Should allow Prefixes. The saved CS:IP value in the NPX environment save area will point at any leading prefixes before an ESC instruction. On 8086/8088 systems, this value points only at the ESC instruction. 6. Do Not Attempt Undefined 8086/8088 Operations. Instructions like POP CS or MOV CS,op will either cause exception 6 (undefined opcode) or perform a protection setup operation like LIDT on the 80286. Undefined bit encodings for bits 5-3 of the second byte of POP MEM or PUSH MEM will cause exception 13 on the 80286. 7. Place a Far JMP Instruction at FFFF0H. After reset, CS:IP = F000:FFF0 on the 80286 (versus FFFF:0000 on the 8086/8088). This change was made to allow sufficient code space to enter protected mode without reloading CS. Placing a far JMP instruction at FFFF0H will avoid this difference. Note that the BOOTSTRAP option of LOC86 will automatically generate this jump instruction. 8. Do not Rely on the Value Written by PUSH SP. The 80286 will push a different value on the stack for PUSH SP than the 8086/8088. If the value pushed is important, replace PUSH SP instructions with the following three instructions: PUSH BP MOV BP,SP XCHG BP,[BP] This code functions as the 8086/8088 PUSH SP instruction on the 80286. 9. Do not Shift or Rotate by More than 31 Bits. The 80286 masks all shift/rotate counts to the low 5 bits. This MOD 32 operation limits the count to a maximum of 31 bits. With this change, the longest shift/rotate instruction is 39 clocks. Without this change, the longest shift/rotate instruction would be 264 clocks, which delays interrupt response until the instruction completes execution. 10. Do not Duplicate Prefixes. The 80286 sets an instruction length limit of 10 bytes. The only way to violate this limit is by duplicating a prefix two or more times before an instruction. Exception 6 occurs if the instruction length limit is violated. The 8086/8088 has no instruction length limit. 11. Do not Rely on Odd 8086/8088 LOCK Characteristics. The LOCK prefix and its corresponding output signal should only be used to prevent other bus masters from interrupting a data movement operation. The 80286 will always assert LOCK during an XCHG instruction with memory (even if the LOCK prefix was not used). LOCK should only be used with the XCHG, MOV, MOVS, INS, and OUTS instructions. The 80286 LOCK signal will not go active during an instruction prefetch. 12. Do not Single Step External Interrupt Handlers. The priority of the 80286 single step interrupt is different from that of the 8086/8088. This change was made to prevent an external interrupt from being single-stepped if it occurs while single stepping through a program. The 80286 single step interrupt has higher priority than any external interrupt. The 80286 will still single step through an interrupt handler invoked by INT instructions or an instruction exception. 13. Do not Rely on IDIV Exceptions for Quotients of 80H or 8000H. The 80286 can generate the largest negative number as a quotient for IDIV instructions. The 8086 will instead cause exception 0. 14. Do not Rely on NMI Interrupting NMI Handlers. After an NMI is recognized, the NMI input and processor extension limit error interrupt is masked until the first IRET instruction is executed. 15. The NPX error signal does not pass through an interrupt controller (an 8087 INT signal does). Any interrupt controller-oriented instructions for the 8087 may have to be deleted. 16. If any real-mode program relies on address space wrap-around (e.g., FFF0:0400=0000:0300), then external hardware should be used to force the upper 4 addresses to zero during real mode. 17. Do not use I/O ports 00F8-00FFH. These are reserved for controlling 80287 and future processor extensions. Table C-1. New 80286 Interrupts Interrupt Function Number 5 A BOUND instruction was executed with a register value outside the two limit values. 6 An undefined opcode was encountered. 7 The EM bit in the MSW has been set and an ESC instruction was executed. This interrupt will also occur on WAIT instructions if TS is set. 8 The interrupt table limit was changed by the LIDT instruction to a value between 20H and 43H. The default limit after reset is 3FFH, enough for all 256 interrupts. 9 A processor extension data transfer exceeded offset 0FFFFH in a segment. This interrupt handler must execute FNINIT before any ESC or WAIT instruction is executed. 13 Segment wraparound was attempted by a word operation at offset 0FFFFH. 16 When 80286 attempted to execute a coprocessor instruction ERROR pin indicated an unmasked exception from previous coprocessor instruction. Hardware Compatibility Considerations 1. Address after Reset 8086 has CS:IP = FFFF:0000 and physical address FFFF0. 80286 has CS:IP = F000:FFF0 and physical address FFFFF0. ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ NOTE After 80286 reset, until the first 80286 far JMP or far CALL, the code segment base is FF0000. This means A20-A23 will be high for CS-relative bus cycles (code fetch or use of CS override prefix) after reset until the first far JMP or far CALL instruction is performed. ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ 2. Physical Address Formation In real mode or protected mode, the 80286 always forms a physical address by adding a 16-bit offset with a 24-bit segment base value (8086 has 20-bit base value). Therefore, if the 80286 in real mode has a segment base within 64K of the top of the 1 Mbyte address space, and the program adds an offset of ffffh to the segment base, the physical address will be slightly above 1Mbyte. Thus, to fully duplicate 1Mbyte wraparound that the 8086 has, it is always necessary to force A20 low externally when the 80286 is in real mode, but system hardware uses all 24 address lines. 3. LOCK signal On the 8086, LOCK asserted means this bus cycle is within a group of two or more locked bus cycles. On the 80286, the LOCK signal means lock this bus cycle to the NEXT bus cycle. Therefore, on the 80286, the LOCK signal is not asserted on the last locked bus cycle of the group of locked bus cycles. 4. Coprocessor Interface 8086, synchronous to 8086, can become a bus master. 80287, asynchronous to 80286 and 80287, cannot become a bus master. 8087 pulls opcode and pointer information directly from data bus. 80286 passes opcode and pointer information to 80287. 8087 uses interrupt path to signal errors to 8086. 80287 uses dedicated ERROR signal. 8086 requires explicit WAIT opcode preceding all ESC instructions to synchronize with 8087. 80286 has automatic instruction synchronization with 80287. 5. Bus Cycles 8086 has four-clock minimum bus cycle, with a time-multiplexed address/data bus. 80286 has two-clock minimum bus cycle, with separate buses for address and data. Appendix D 80286/80386 Software Compatibility Considerations ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ This appendix describes the considerations required in designing an Operating System for the protected mode 80286 so that it will operate on an 80386. An 80286 Operating System running on the 80386 would not use any of the advanced features of the 80386 (i.e., paging or segments larger than 64K), but would run 80286 code faster. Use of the new 80386 features requires changes in the 80286Operating System. The 80386 is no different than any other software compatible processor in terms of requiring the same system environment to run the same software; the 80386 must have the same amount of physical memory and I/O devices in the system as the 80286 system to run the same software. Note that an 80386 system requires a different memory system to achieve the higher performance. The 80286 design considerations can be generally characterized as avoiding use of functions or memory that the 80386 will use. The exception to this rule is initialization code executed after power up. Such code must be changed to configure the 80386 system to match that of the 80286 system. The following are 80286/80386 software compatibility design considerations: 1. Isolate the protected mode initialization code. System initialization code will be required on the 80386 to program operating parameters before executing any significant amount of 80286 software. The 80286 initialization software should be isolated from the rest of the Operating System. The initialization code in Appendix A is an example of isolated initialization code. Such code can be extended to include programming of operating parameters before executing the initial protected mode task. 2. Avoid wraparound of 80286 24-bit physical address space. Since the 80386 has a larger physical address space, any segment whose base address is greater than FF0000 and whose limit is beyond FFFFFF will address the seventeenth megabyte of memory in the 80386 32-bit physical address space instead of the first megabyte on an 80286. No expand-down segments shouldhave a base address in the range FF00001-FFFFFF. No expand-up segments should wrap around the 80286 address space (the sum of their base and limit is in the range 000000-00FFFE). 3. Zero the last word of every 80286 descriptor. The 80386 uses the last word of each descriptor to expand the base address and limit fields of segments. Placing zeros in the descriptor will cause the 80386 to treat the segments the same way as an 80286 (except for address space wraparound as mentioned above). 4. Use only 80H or 00H for invalid descriptors. The 80386 uses more descriptor types than the 80286. Numeric values of 8-15 in bits 3-0 of the access byte for control descriptors will cause a protection exception on the 80286, but may be defined for other segment types on the 80386. Access byte values of 80H and 00H will remain undefined descriptors on both the 80286 and the 80386. 5. Put error interrupt handlers in reserved interrupts 14, 15, 17-31. Some of the unused, Intel-reserved interrupts of the 80286 will be used by the 80386 (i.e., page fault or bus error). These interrupts should not occur while executing an 80286 operating system on an 80386. However, it is safest to place an interrupt handler in these interrupts to print an error message and stop the system if they do occur. 6. Do not change bits 15-4 of MSW. The 80386 uses some of the undefined bits in the machine status word. 80286 software should ignore bits 15-4 of the MSW. To change the MSW on an 80286, read the old value first with LMSW, change bits 3-0 only, then write the new value with SMSW. 7. Use a restricted LOCK protocol for multiprocessor systems. The 80386 supports the 8086/80286 LOCK functions for simple instructions, but not the string move instructions. Any need for locked string moves can be satisfied by gaining control of a status semaphore before using the string move instruction. Any attempt to execute a locked string move will cause a protection exception on the 80386. The general 80286 LOCK protocol does not efficiently extend to large multiprocessor systems. If all the processors in the system frequently use the 8086/80286 LOCK, they will prevent other processors from accessing memory and thereby impact system performance. Access to semaphores in the future, including current 80286 Operating Systems, should use a protocol with the following restrictions: Ž Be sure the semaphore starts at a physical memory address that is a multiple of 4. Ž Do not use string moves to access the variable. Ž All accesses by any instruction or I/O device (even simple reads or writes) must use the LOCK prefix or system LOCK signal. Index ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ A ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ AAA AAD AAM AAS ADC ADD Addressing Modes Based Indexed Mode Based Indexed Mode with Displacement Based Mode (on BX or BP Registers) Direct Address Mode Displacement Immediate Operand Indexed Mode (by DI or SI) Opcode Register Indirect Mode Summary AF Flag, (see Flags) AH Register AL Register AND Instruction Arithmetic Instructions ASCII (see Data Types) AX Register B ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Based Index Mode (see Addressing Modes) Based Index Mode with Displacement (see Addressing Modes) Based Mode (see Addressing Modes) BCD Arithmetic (see Data Management Instructions) BH Register BL Register BOUND Instruction (see Extended Instruction Set) Bound Range Exceeded (Interrupt 5), (see Interrupt Handling) BP Register Breakpoint Interrupt 3, (see Interrupt Handling) BUSY BX Register (cont.) Byte (See Data Types) C ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ CALL Instructions Call Gates CBW Instructions CF (Carry Flag) (see Flags) CH Register CL Register CLC Instruction CLD Instruction CLI Instruction CLTS Instruction CMP Instruction Code Segment Access Comparison Instructions Conforming Code Segments Constant Instructions Control Transfers CPL (Current Privilege Level) CS Register CWD Instruction CX Register D ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ DAA DAS Data Management Instructions Address Manipulation Arithmetic Instructions Addition Instructions Division Instructions Multiplication Instructions Subtraction Instructions BCD Arithmetic Character Transfer and String Instructions Repeat Prefixes String Move String Translate Control Transfer Instructions Conditional Transfer Software Generated Interrupts Interrupt Instructions Unconditional Transfer Flag Control Logical Instructions Shift and Rotate Instructions Type Conversion Instructions Processor Extension Intructions Test and Compare Instructions Trusted Instructions Input/Output Instructions Stack Manipulation Data Transfer Instructions Data Types ASCII BCD Byte Floating Point Integer Packed BCD Pointer Strings Word DEC Instruction Dedicated Interrupt Vector Descriptor Table Descriptor Table Register DF Flag, (see Flags) DH Register DI Instruction Direct Address Mode (see Addressing Modes) Divide Error (Interrupt 0) (see Interrupt Handling) DIV Instruction DL Register DPL (Descriptor Privilege Level) DS Register DX Register E ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ EM (Bit in MSW) ENTER Instruction ES Register ESC (Instructions for Coprocessor) Extended Instruction Set (Chapter 4) ENTER Build Stackframe LEAVE Remove Stackframe Repeated IN and OUT String Instructions F ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Flag Register Flags see also Use of Flags with Basic Instructions AF (Auxilliary Carry Flag) CF (Carry Flag) (cont.) DF (Direction Flag) IF (Interrupt Flag) IOPL (Privilege Level) NT (Nested Task Flag) OF (Overflow Flag) PF (Parity Flag) SF (Sign Flag) TF (Trap Flag) TS (Task Switch) ZF (Zero Flag) Floating Point (see Data Types) G ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Gates GDT GDTR (Global Descriptor Register) General Protection Fault (Interrupt 3), (see Interrupt Handling) General Registers H ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ HLT Instruction Hierarchy of 86, 186, 286 Instruction Sets Basic Instruction Set, Chapter 3 Extended Instruction Set Instruction Set Overview System Control Register Set, Chapter 4, Chapter 5, Chapter 6, Chapter 7 (cont.) Chapter 8, Chapter 9, Chapter 10 I ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ I/O IDIV Instruction IDT (Interrupt Descriptor Table) IDTR (Interrupt Descriptor Table Register) IF (Interrupt Flag), (see Flags) IMUL Instruction IN Instruction INC Instruction INDEX Field Indexed Mode Index, Pointer and Base Register Input/Output Instructions Memory Mapped I/O Restrictions in Protected Mode Separate I/O Space INS/INSB/INSW Instruction INT Instruction, (see Interrupt Handling) Integer, (see Data Types) Interrupt Handling (cont.) Interrupt Priorities Interrupt 0 Divide Error Interrupt 1 Single-Step Interrupt 2 Nonmaskable Interrupt 3 Breakpoint Interrupt 4 INTO Detected Overflow Interrupt 5 BOUND Range Exceeded Interrupt 6 Invalid Opcode Interrupt 7 Processor Extension Not Available Interrupt 8, Interrupt Table Limit Too Small Interrupt Vectors Reserved Vectors Interrupt Vector Table Interrupts and Exceptions,(see Interrupt Handling and Interrupt Priorities) INTO Detected Overflow (Interrupt 4), (see Interrupt Handling and Interrupt Priorities) INTO Instruction INTR Invalid opcode (Interrupt 6), (see Interrupt Handling and Interrupt Priorities) IOPL (I/O Privilege Level), (see Flags) IP Register IRET Instruction J ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ JCXZ Instruction JMP Instruction L ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ LAHF Instruction LAR Instruction LDS Instruction LDT (Local Descriptor Table) (cont.) LEA Instruction LEAVE Instruction LES Instruction LGDT Instruction LIDT Instruction LLDT Instruction LMSW Instruction LOCK Prefix LODS/LODSB/LODSW LOOP Instruction LOOPE Instruction LOOPNE LOOPNZ LSL Instruction M ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Memory, Physical Size Segmentation Implied Usage Interpretation in Protected Mode Interpretation in Real Mode Modularity Virtual Size Memory Addressing Modes Memory Management Task Managment, Chapter 8 Context Switching (Task Switching) Overview Memory Management Registers, Chapter 6 Memory Mapped I/O, (see Input/Output) Memory Mode Memory Segmentation and Segment Registers MOV Instructions MOVS Instructions MOVSB Instructions MOVSW Instruction MSW Register MUL Instruction N ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ NEG Instruction NMI (Non maskable Interrupt) Nonmaskable (Interrupt 2), (see Interrupt Priorities) NOP Instruction NOT Instruction Not Present (Interrupt 11) (see Interrupt Priorities) NPX Processor Extension NT (Nested Task Flag), (see Flags) Numeric Data Processor Instructions O ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ OF (Overflow Flag), (see Flags) Offset Computation Operands OR Instruction OUT/OUTW OUTS/OUTSB/OUTSW Instruction P ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ PF (Parity Flag), (see Flags) Pointer, (see Data Types) POP Instruction POPA Instruction POPF Instruction Processor Extension Error (Interrupt 6), (see Interrupt Handling and Interrupt Priorities) Processor Extension Not Available, (Interrupt 7), (see Interrupt and Interrupt Priorities) Processor Extension Segment Overrun Interrupt (Interrupt 9), (see Interrupt and Interrupt Priorities) Protected Mode Protected Virtual Address Mode Protection Implementation Protection Mechanisms PUSH PUSHA PUSHF R ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Real Address Mode Register, Base Architecture Diagram Base Register BX Flags Register General Registers Index Registers DI, SI Overview Pointer Registers BP and SP Segment Registers Status and Control Register Direct Mode Register and Immediate Modes Register Indirect Mode (see Addressing Modes) Reserved Interrupt Vectors, (see Interrupt Handling and Interrupt Priorities) RESET RCL Instruction RCR Instruction REP Prefix REPE Prefix REPNE Prefix REPNZ Prefix REPZ Prefix RET Instructon ROL Instruction ROR Instruction RPL S ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ SAL Instruction SAR Instruction SBB Instruction SCAS Instruction SEG (Segment Override Prefix) Segment Address Translation Registers Segment Descriptor Segment Overrun Exception (Interrupt 13), (see Interrupt Handling and Interrupt Priorities) Segment Selection SF (Sign Flag), (see Flags) SGDT Instruction SHL Instruction SHR Instruction SI Register SIDT Instruction Single Step (Interrupt 1), (see Interrupt Priorities) SMSW Instruction SP Register SS Register (cont.) Status and Control Registers Stack Flag, (see Flags) Stack Fault (Interrupt 12), (see Interrupt Priorities) Stack Manipulation Instructions Stack Operations Grow Down Overview Segment Register Usage Segment Usage Override Stack Frame Base Pointer BP Top of Stack TOS with BP and SP Registers Status Flags STC Instructions STD Instructions STI Instructions String Instructions SUB Instruction System Address Registers System Initialization System Control Instructions T ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ TEST Instruction TF (Trap Flags), (see Flags) TOS (Top of Stack), (see Stack Operation) TR (Task Register) Transcendental Instruction TSS (Task State Segment) U ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Use of Flags with Basic Instructions V ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Virtual Address W ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ WAIT Instruction X ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ XCHG Instruction XLAT Instruction XOR Instruction