Rick Hohensee 	July 2003

This is my own heavy edit of 386INTEL.TXT, INTEL 80386 PROGRAMMER'S
REFERENCE MANUAL 1986.  Unlike that document, this one is pure 7-bit
ASCII, and no lines are over 80 columns. This one is also split into five
files...
	intro-applications programming
	systems programming
	backward-compatibility
	detailed instruction dictionary
	appendices and deprecations

Errors and typos in a document such as this can be sanity-threatening.
There are apparently a very few clear errors in the INTeL original, and I
have surely added some. This document is only an adjunct to the original,
of course, an other authoratative works, such as the machine itself.

I have edited this file in several ways to make it more to tastes not
deeply imbued in INTeLism, and beyond, to the brink of osimplayism. For
example, understand that on 386 for instructions that have a byte operand
opcode and a word operand opcode, word really means "cell" here, i.e.
"word" is the default operand size of the CS code segment in force,
usually 32 bits, a quad. The INTeL original likes to pretend an opcode is
more than one opcode if it works in a USE32 segment or a USE16 segment,
which they basically all do. That is horribly obfuscating.

The syntax of assembly examples has been changed mostly to op-source-dest,
using osimplay source/dest seperators "to" and "with". Far pointers are
listed in the form offset:segment, which is how they sit in memory if you
think of memory addresses increasing left-to-right.  Bits will still be in
the convention of being considered to increase in magnitude right-to-left,
such that "left shift" means up-significance. EAX is now A. AX is still
AX.

"general" registers are now refered to as "core" registers. The generality
of 386 core registers is not typically useful when the special aspects of
each register are needed, such as DX necessarily holding port addresses,
operations using DI that default to the ES segment, XCHG working only with
A and another operand, C necessarily being the count for REP operations,
and so on.

I have reversed the sense of the descriptions of priviledge bits to
restriction bits, such that CPL and IOPL are called CRL and IORL herein.
That is, ring 0 is restriction level 0. 

Most charts showing spans of memory follow occidental page-traversal such
that addresses increase left-to-right, then top-to-bottom. This means
stack diagrams grow toward lower addresses, which is up the page.

Where I believe INTeL had a typo in (my copy of) 386INTEL.TXT I correct it
and note the change.

I changed all the diagrams to 7-bit ascii-art, and there's some
information loss there, but it's mostly aesthetic, I hope. I didn't fix up
any of the charts about paging, because it doesn't interest me personally,
so I'd be doing so at a greater error-introduction rate.

The 386 always uses segments, and the characteristics of each segment
available to the CPU at a particular instant are what has been set via the
segment registers. Thus there are up to 6 active segments at a time, CS,
DS, SS, ES, FS and GS. The segment active under the controls set via a
particular segment register are said to be "through" that register, i.e.
implicit stack users go "through" SS. Or "via" or "under".

Look at things as atomically as possible. INTeL's names for things
frequently don't make sense. Think about what things really do. For
example, "real mode" isn't real. It's not a basic mode of the machine,
it's the result of setting a bunch of things to get a 32 bit machine to
act like a 20 bit machine, but it is not what you get simply by flipping
the protection bit, PE, to off. It definitely is not the opposite of
protected mode. The 386 is, by all accounts, an amazing achievment, given
the backward-compatibility constraints and so on. Actually explaining the
thing lucidly would be a similar achievement, and that work continues.
Back to thinking atomically. The opcode descriptions in the fourth file of
this edit are pretty solid. I've only seen a couple typos, and no
out-and-out inaccuracy that overall descriptions like "real mode" can
hardly avoid. They pretty much state what the machine actually does,
exactly, bit by bit. That's how you'll comprehend it.

The x86 is repulsive, but it's quite usable, servicable, and of course
successful. If you run it fast enough it can do bunches of computing.
Being as backward-compatible as it is is terribly dysfunctionalizing,
particularly to the new 386 programmer, but has its advantages. The
machine has better code density than a CISC, and faster state-changes,
potentially, than a RISC, it seems. One 386 contains most of the history
of the microprocessor, and some of that history is pretty nifty. The
"general registers" aren't general, but the first thing you do with a true
general register is give it some specific function, and the specific
functions of the 386 core registers are well chosen, and not unlike
something such as the 6502, which was a design delight for its era.

The ultimate reference is the machine itself. Try things. 

There was nobody speaking in first-person in the INTeL manual, so if
somebody in here says "I" or "me", it's Rick Hohensee schpreckenzie atcha.


...........................................

INTEL 80386 PROGRAMMER'S REFERENCE MANUAL 1986

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.

Trademark notices and partners list in part 5.

Table of Contents

Chapter 1  Introduction to the 80386

1.1  Organization of This Manual
      1.1.1  Part I .. Applications Programming
      1.1.2  Part II .. Systems Programming
      1.1.3  Part III .. Compatibility
      1.1.4  Part IV .. Instruction Set
      1.1.5  Appendices

1.2  Related Literature
1.3  Notational Conventions
      1.3.1  Data-Structure Formats
      1.3.2  Undefined Bits and Software Compatibility
      1.3.3  Instruction Operands
      1.3.4  Hexadecimal Numbers
      1.3.5  Sub- and Super-Scripts

		     PART I    APPLICATIONS PROGRAMMING                   

Chapter 2  Basic Programming Model

2.1  Memory Organization and Segmentation
      2.1.1  The"Flat" Model
      2.1.2  The Segmented Model

2.2  Data Types
2.3  Registers
      2.3.1  Core Registers
      2.3.2  Segment Registers
      2.3.3  Stack Implementation
      2.3.4  Flags Register
	      2.3.4.1  Status Flags
	      2.3.4.2  Control Flag
	      2.3.4.3  Instruction Pointer

2.4  Instruction Format
2.5  Operand Selection
      2.5.1  Immediate Operands
      2.5.2  Register Operands
      2.5.3  Memory Operands
	      2.5.3.1  Segment Selection
	      2.5.3.2  Effective-Address Computation

2.6  Interrupts and Exceptions

Chapter 3  Applications Instruction Set

3.1  Data Movement Instructions
      3.1.1  General-Purpose Data Movement Instructions
      3.1.2  Stack Manipulation Instructions
      3.1.3  Type Conversion Instructions

3.2  Binary Arithmetic Instructions
      3.2.1  Addition and Subtraction Instructions
      3.2.2  Comparison and Sign Change Instruction
      3.2.3  Multiplication Instructions
      3.2.4  Division Instructions

3.3  Decimal Arithmetic Instructions
      3.3.1  Packed BCD Adjustment Instructions
      3.3.2  Unpacked BCD Adjustment Instructions

3.4  Logical Instructions
      3.4.1  Boolean Operation Instructions
      3.4.2  Bit Test and Modify Instructions
      3.4.3  Bit Scan Instructions
      3.4.4  Shift and Rotate Instructions
	      3.4.4.1  Shift Instructions
	      3.4.4.2  Double-Shift Instructions
	      3.4.4.3  Rotate Instructions
	      3.4.4.4  Fast"bit-blt" Using Double Shift
			 Instructions
	      3.4.4.5  Fast Bit-String Insert and Extract

      3.4.5  Byte-Set-On-Condition Instructions
      3.4.6  Test Instruction

3.5  Control Transfer Instructions
      3.5.1  Unconditional Transfer Instructions
	      3.5.1.1  Jump Instruction
	      3.5.1.2  Call Instruction
	      3.5.1.3  Return and Return-From-Interrupt Instruction

      3.5.2  Conditional Transfer Instructions
	      3.5.2.1  Conditional Jump Instructions
	      3.5.2.2  Loop Instructions
	      3.5.2.3  Executing a Loop or Repeat Zero Times

      3.5.3  Software-Generated Interrupts

3.6  String and Character Translation Instructions
      3.6.1  Repeat Prefixes
      3.6.2  Indexing and Direction Flag Control
      3.6.3  String Instructions

3.7  Instructions for Block-Structured Languages
3.8  Flag Control Instructions
      3.8.1  Carry and Direction Flag Control Instructions
      3.8.2  Flag Transfer Instructions

3.9  Coprocessor Interface Instructions
3.10 Segment Register Instructions
      3.10.1  Segment-Register Transfer Instructions
      3.10.2  Far Control Transfer Instructions
      3.10.3  Data Pointer Instructions

3.11  Miscellaneous Instructions
       3.11.1  Address Calculation Instruction
       3.11.2  No-Operation Instruction
       3.11.3  Translate Instruction

		       PART II    SYSTEMS PROGRAMMING                     
(second file)
Chapter 4  Systems Architecture

4.1  Systems Registers
      4.1.1  Systems Flags
      4.1.2  Memory-Management Registers
      4.1.3  Control Registers
      4.1.4  Debug Register
      4.1.5  Test Registers

4.2  Systems Instructions

Chapter 5  Memory Management

5.1  Segment Translation
      5.1.1  Descriptors
      5.1.2  Descriptor Tables
      5.1.3  Selectors
      5.1.4  Segment Registers

5.2  Page Translation
      5.2.1  Page Frame
      5.2.2  Linear Address
      5.2.3  Page Tables
      5.2.4  Page-Table Entries
	      5.2.4.1  Page Frame Address
	      5.2.4.2  Present Bit
	      5.2.4.3  Accessed and Dirty Bits
	      5.2.4.4  Read/Write and User/Supervisor Bits

      5.2.5  Page Translation Cache

5.3  Combining Segment and Page Translation
      5.3.1  "Flat" Architecture
      5.3.2  Segments Spanning Several Pages
      5.3.3  Pages Spanning Several Segments
      5.3.4  Non-Aligned Page and Segment Boundaries
      5.3.5  Aligned Page and Segment Boundaries
      5.3.6  Page-Table per Segment

Chapter 6  Protection

6.1  Why Protection?
6.2  Overview of 80386 Protection Mechanisms
6.3  Segment-Level Protection
      6.3.1  Descriptors Store Protection Parameters
	      6.3.1.1  Type Checking
	      6.3.1.2  Limit Checking
	      6.3.1.3  Privilege Levels

      6.3.2  Restricting Access to Data
	      6.3.2.1  Accessing Data in Code Segments

      6.3.3  Restricting Control Transfers
      6.3.4  Gate Descriptors Guard Procedure Entry Points
	      6.3.4.1  Stack Switching
	      6.3.4.2  Returning from a Procedure

      6.3.5  Some Instructions are Reserved for Operating System
	      6.3.5.1  Privileged Instructions
	      6.3.5.2  Sensitive Instructions

      6.3.6  Instructions for Pointer Validation
	      6.3.6.1  Descriptor Validation
	      6.3.6.2  Pointer Integrity and RPL

6.4  Page-Level Protection
      6.4.1  Page-Table Entries Hold Protection Parameters
	      6.4.1.1  Restricting Addressable Domain
	      6.4.1.2  Type Checking

      6.4.2  Combining Protection of Both Levels of Page Tables
      6.4.3  Overrides to Page Protection

6.5  Combining Page and Segment Protection

Chapter 7  Multitasking

7.1  Task State Segment
7.2  TSS Descriptor
7.3  Task Register
7.4  Task Gate Descriptor
7.5  Task Switching
7.6  Task Linking
      7.6.1  Busy Bit Prevents Loops
      7.6.2  Modifying Task Linkages

7.7  Task Address Space
      7.7.1  Task Linear-to-Physical Space Mapping
      7.7.2  Task Logical Address Space

Chapter 8    Input/Output

8.1  I/O Addressing
      8.1.1  I/O Address Space
      8.1.2  Memory-Mapped I/O

8.2  I/O Instructions
      8.2.1  Register I/O Instructions
      8.2.2  Block I/O Instructions

8.3  Protection and I/O
      8.3.1  I/O Privilege Level
      8.3.2  I/O Permission Bit Map

Chapter 9  Exceptions and Interrupts

9.1  Identifying Interrupts
9.2  Enabling and Disabling Interrupts
      9.2.1  NMI Masks Further NMls
      9.2.2  IF Masks INTR
      9.2.3  RF Masks Debug Faults
      9.2.4  MOV or POP to SS Masks Some Interrupts and Exceptions

9.3  Priority Among Simultaneous Interrupts and Exceptions
9.4  Interrupt Descriptor Table
9.5  IDT Descriptors
9.6  Interrupt Tasks and Interrupt Procedures
      9.6.1  Interrupt Procedures
	      9.6.1.1  Stack of Interrupt Procedure
	      9.6.1.2  Returning from an Interrupt Procedure
	      9.6.1.3  Flags Usage by Interrupt Procedure
	      9.6.1.4  Protection in Interrupt Procedures

      9.6.2  Interrupt Tasks

9.7  Error Code
9.8  Exception Conditions
      9.8.1  Interrupt 0 .. Divide Error
      9.8.2  Interrupt 1 .. Debug Exceptions
      9.8.3  Interrupt 3 .. Breakpoint
      9.8.4  Interrupt 4 .. Overflow
      9.8.5  Interrupt 5 .. Bounds Check
      9.8.6  Interrupt 6 .. Invalid Opcode
      9.8.7  Interrupt 7 .. Coprocessor Not Available
      9.8.8  Interrupt 8 .. Double Fault
      9.8.9  Interrupt 9 .. Coprocessor Segment Overrun
      9.8.10 Interrupt 10 .. Invalid TSS
      9.8.11 Interrupt 11 .. Segment Not Present
      9.8.12 Interrupt 12 .. Stack Exception
      9.8.13 Interrupt 13 .. General Protection Exception
      9.8.14 Interrupt 14 .. Page Fault
	      9.8.14.1  Page Fault during Task Switch
	      9.8.14.2  Page Fault with Inconsistent Stack Pointer

      9.8.15 Interrupt 16 .. Coprocessor Error

9.9  Exception Summary

9.10  Error Code Summary

Chapter 10  Initialization

10.1  Processor State after Reset
10.2  Software Initialization for Real-Address Mode
       10.2.1  Stack
       10.2.2  Interrupt Table
       10.2.3  First Instructions

10.3  Switching to Protected Mode
10.4  Software Initialization for Protected Mode
       10.4.1  Interrupt Descriptor Table
       10.4.2  Stack
       10.4.3  Global Descriptor Table
       10.4.4  Page Tables
       10.4.5  First Task

10.5  Initialization Example
10.6  TLB Testing
       10.6.1  Structure of the TLB
       10.6.2  Test Registers
       10.6.3  Test Operations

Chapter 11  Coprocessing and Multiprocessing

11.1  Coprocessing
       11.1.1  Coprocessor Identification
       11.1.2  ESC and WAIT Instructions
       11.1.3  EM and MP Flags
       11.1.4  The Task-Switched Flag
       11.1.5  Coprocessor Exceptions
		11.1.5.1  Interrupt 7 .. Coprocessor Not Available
		11.1.5.2  Interrupt 9 .. Coprocessor Segment Overrun
		11.1.5.3  Interrupt 16 .. Coprocessor Error

11.2  General Multiprocessing
       11.2.1  LOCK and the LOCK# Signal
       11.2.2  Automatic Locking
       11.2.3  Cache Considerations

Chapter 12  Debugging

12.1  Debugging Features of the Architecture
12.2  Debug Registers
       12.2.1  Debug Address Registers (DRO-DR3)
       12.2.2  Debug Control Register (DR7)
       12.2.3  Debug Status Register (DR6)
       12.2.4  Breakpoint Field Recognition

12.3  Debug Exceptions
       12.3.1  Interrupt 1 .. Debug Exceptions
		12.3.1.1  Instruction Address Breakpoint
		12.3.1.2  Data Address Breakpoint
		12.3.1.3  General Detect Fault
		12.3.1.4  Single-Step Trap
		12.3.1.5  Task Switch Breakpoint

       12.3.2  Interrupt 3 .. Breakpoint Exception
(third file)
			  PART III    COMPATIBILITY                       

Chapter 13  Executing 80286 Protected-Mode Code

13.1  80286 Code Executes as a Subset of the 80386
13.2  Two Ways to Execute 80286 Tasks
13.3  Differences from 80286
       13.3.1  Wraparound of 80286 24-Bit Physical Address Space
       13.3.2  Reserved Word of Descriptor
       13.3.3  New Descriptor Type Codes
       13.3.4  Restricted Semantics of LOCK
       13.3.5  Additional Exceptions

Chapter 14  80386 Real-Address Mode

14.1  Physical Address Formation
14.2  Registers and Instructions
14.3  Interrupt and Exception Handling
14.4  Entering and Leaving Real-Address Mode
       14.4.1  Switching to Protected Mode

14.5  Switching Back to Real-Address Mode
14.6  Real-Address Mode Exceptions
14.7  Differences from 8086
14.8  Differences from 80286 Real-Address Mode
       14.8.1  Bus Lock
       14.8.2  Location of First Instruction
       14.8.3  Initial Values of Core Registers
       14.8.4  MSW Initialization

Chapter 15  Virtual 8088 Mode

15.1  Executing 8086 Code
       15.1.1  Registers and Instructions
       15.1.2  Linear Address Formation

15.2  Structure of a V86 Task
       15.2.1  Using Paging for V86 Tasks
       15.2.2  Protection within a V86 Task

15.3  Entering and Leaving V86 Mode
       15.3.1  Transitions Through Task Switches
       15.3.2  Transitions Through Trap Gates and Interrupt Gates

15.4  Additional Sensitive Instructions
       15.4.1  Emulating 8086 Operating System Calls
       15.4.2  Virtualizing the Interrupt-Enable Flag

15.5  Virtual I/O
       15.5.1  I/O-Mapped I/O
       15.5.2  Memory-Mapped I/O
       15.5.3  Special I/O Buffers

15.6  Differences from 8086
15.7  Differences from 80286 Real-Address Mode

Chapter 16  Mixing 16-Bit and 32-Bit Code

16.1  How the 80386 Implements 16-Bit and 32-Bit Features
16.2  Mixing 32-Bit and 16-Bit Operations
16.3  Sharing Data Segments among Mixed Code Segments
16.4  Transferring Control among Mixed Code Segments
       16.4.1  Size of Code-Segment Pointer
       16.4.2  Stack Management for Control Transfers
		16.4.2.1  Controlling the Operand-Size for a CALL
		16.4.2.2  Changing Size of Call

       16.4.3  Interrupt Control Transfers
       16.4.4  Parameter Translation
       16.4.5  The Interface Procedure

			 PART IV    INSTRUCTION SET                       
(fourth file)
Chapter 17  80386 Instruction Set

17.1  Operand-Size and Address-Size Attributes
       17.1.1  Default Segment Attribute
       17.1.2  Operand-Size and Address-Size Instruction Prefixes
       17.1.3  Address-Size Attribute for Stack

17.2  Instruction Format
       17.2.1  ModR/M and SIB Bytes
       17.2.2  How to Read the Instruction Set Pages
		17.2.2.1  Opcode
		17.2.2.2  Instruction
		17.2.2.3  Clocks
		17.2.2.4  Description
		17.2.2.5  Operation
		17.2.2.6  Description
		17.2.2.7  Flags Affected
		17.2.2.8  Protected Mode Exceptions
		17.2.2.9  Real Address Mode Exceptions
		17.2.2.10 Virtual-8086 Mode Exceptions

Instruction Sets

AAA AAD AAM AAS ADC ADD AND ARPL BOUND BSF BSR BT BTC BTR BTS CALL
CBW/CWDE CLC CLD CLI CLTS CMC CMP CMPS/CMPSB/CMPSW/CMPSD CWD/CDQ DAA DAS
DEC DIV ENTER HLT IDIV IMUL IN INC INS/INSB/INSW/INSD INT/INTO IRET/IRETD
Jcc JMP LAHF LAR LEA LEAVE LGDT/LIDT LGS/LSS/LDS/LES/LFS LLDT LMSW LOCK
LODS/LODSB/LODSW/LODSD LOOP/LOOPcond LSL LTR MOV MOV
MOVS/MOVSB/MOVSW/MOVSD MOVSX MOVZX MUL NEG NOP NOT OR OUT
OUTS/OUTSB/OUTSW/OUTSD POP POPA/POPAD POPF/POPFD PUSH PUSHA/PUSHAD
PUSHF/PUSHFD RCL/RCR/ROL/ROR REP/REPE/REPZ/REPNE/REPNZ RET SAHF
SAL/SAR/SHL/SHR SBB SCAS/SCASB/SCASW/SCASD SETcc SGDT/SIDT SHLD SHRD SLDT
SMSW STC STD STI STOS/STOSB/STOSW/STOSD STR SUB TEST VERR,VERW WAIT XCHG
XLAT/XLATB XOR

(fifth file)
Appendix A  Opcode Map

Appendix B  Complete Flag Cross-Reference

Appendix C  Status Flag Summary

Appendix D  Condition Codes

Stuff I felt is useless, like the AAA instruction.


Figures

1-1     Example Data Structure

2-1     Two-Component Pointer
2-2     Fundamental Data Types
2-3     Bytes and cells in Memory
2-4     80386 Data Types
2-5     80386 Applications Register Set
2-6     Use of Memory Segmentation
2-7     80386 Stack
2-8     EFLAGS Register
2-9     Instruction Pointer Register
2-10    Effective Address Computation

3-1     PUSH
3-2     PUSHA
3-3     POP
3-4     POPA
3-5     Sign Extension
3-6     SAL and SHL
3-7     SHR
3-8     SAR
3-9     Using SAR to Simulate IDIV
3-10    Shift Left Double
3-11    Shift Right Double
3-12    ROL
3-13    ROR
3-14    RCL
3-15    RCR
3-16    Formal Definition of the ENTER Instruction
3-17    Variable Access in Nested Procedures
3-18    Stack Frame for MAIN at Level 1
3-19    Stack Frame for Prooedure A
3-20    Stack Frame for Procedure B at Level 3 Called from A
3-21    Stack Frame for Procedure C at Level 3 Called from B
3-22    LAHF and SAHF
3-23    Flag Format for PUSHF and POPF

4-1     Systems Flags of EFLAGS Register
4-2     Control Registers

5-1     Address Translation Overview
5-2     Segment Translation
5-3     General Segment-Descriptor Format
5-4     Format of Not-Present Descriptor
5-5     Descriptor Tables
5-6     Format of a Selector
5-7     Segment Registers
5-8     Format of a Linear Address
5-9     Page Translation
5-10    Format of a Page Table Entry
5-11    Invalid Page Table Entry
5-12    80386 Addressing Mechanism
5-13    Descriptor per Page Table

6-1     Protection Fields of Segment Descriptors
6-2     Levels of Privilege
6-3     Privilege Check for Data Access
6-4     Privilege Check for Control Transfer without Gate
6-5     Format of 80386 Call Gate
6-6     Indirect Transfer via Call Gate
6-7     Privilege Check via Call Gate
6-8     Initial Stack Pointers of TSS
6-9     Stack Contents after an Interievel Call
6-10    Protection Fields of Page Table Entries

7-1     80386 32-Bit Task State Segment
7-2     TSS Descriptor for 32-Bit TSS
7-3     Task Register
7-4     Task Gate Descriptor
7-5     Task Gate Indirectly Identifies Task
7-6     Partially-Overlapping Linear Spaces

8-1     Memory-Mapped I/O
8-2     I/O Address Bit Map

9-1     IDT Register and Table
9-2     Pseudo-Descriptor Format for LIDT and SIDT
9-3     80386 IDT Gate Descriptors
9-4     Interrupt Vectoring for Procedures
9-5     Stack Layout after Exception of Interrupt
9-6     Interrupt Vectoring for Tasks
9-7     Error Code Format
9-8     Page-Fault Error Code Format
9-9     CR2 Format

10-1    Contents of D after RESET
10-2    Initial Contents of CRO
10-3    TLB Structure
10-4    Test Registers

12-1    Debug Registers

14-1    Real-Address Mode Address Formation

15-1    V86 Mode Address Formation
15-2    Entering and Leaving an 8086 Program
15-3    PL 0 Stack after Interrupt in V86 Task

16-1    Stack after Far 16-Bit and 32-Bit Calls

17-1    80386 Instruction Format
17-2    ModR/M and SIB Byte Formats
17-3    Bit Offset for BIT[ A, 21]
17-4    Memory Bit Indexing


Tables

2-1      Default Segment Register Selection Rules
2-2      80386 Reserved Exceptions and Interrupts

3-1      Bit Test and Modify Instructions
3-2      Interpretation of Conditional Transfers

6-1      System and Gate Descriptor Types
6-2      Useful Combinations of E, G, and B Bits
6-3      Interievel Return Checks
6-4      Valid Descriptor Types for LSL
6-5      Combining Directory and Page Protection

7-1      Checks Made during a Task Switch
7-2      Effect of Task Switch on BUSY, NT, and Back-Link

9-1      Interrupt and Exception ID Assignments
9-2      Priority Among Simultaneous Interrupts and Exceptions
9-3      Double-Fault Detection Classes
9-4      Double-Fault Definition
9-5      Conditions That Invalidate the TSS
9-6      Exception Summary
9-7      Error-Code Summary

10-1     Meaning of D, U, and W Bit Pairs

12-1     Breakpeint Field Recognition Examples
12-2     Debug Exception Conditions

14-1     80386 Real-Address Mode Exceptions
14-2     New 80386 Exceptions

17-1     Effective Size Attributes
17-2     16-Bit Addressing Forms with the ModR/M Byte
17-3     32-Bit Addressing Forms with the ModR/M Byte
17-4     32-Bit Addressing Forms with the SIB Byte
17-5     Task Switch Times for Exceptions
17-6     80386 Exceptions


Chapter 1  Introduction to the 80386
............................................................................

The 80386 is an advanced 32-bit microprocessor optimized for multitasking
operating systems and designed for applications needing very high
performance. The 32-bit registers and data paths support 32-bit addresses
and data types. The processor can address up to four gigabytes of physical
memory and 64 terabytes (2^(46) bytes) of virtual memory. The on-chip
memory-management facilities include address translation registers,
advanced multitasking hardware, a protection mechanism, and paged virtual
memory. Special debugging registers provide data and code breakpoints even
in ROM-based software.


1.1  Organization of This Manual

This book presents the architecture of the 80386 in five parts:

   Part I      .. Applications Programming
   Part II     .. Systems Programming
   Part III    .. Compatibility
   Part IV     .. Instruction Set
   Appendices

These divisions are determined in part by the architecture itself and in
part by the different ways the book will be used. As the following table
indicates, the latter two parts are intended as reference material for
programmers actually engaged in the process of developing software for the
80386. The first three parts are explanatory, showing the purpose of
architectural features, developing terminology and concepts, and describing
instructions as they relate to specific purposes or to specific
architectural features.

Explanation                Part I   .. Applications Programming
			   Part II  .. Systems Programming
			   Part III .. Compatibility

Reference                  Part IV  .. Instruction Set
			   Appendices

The first three parts follow the execution modes and protection features of
the 80386 CPU. The distinction between applications features and systems
features is determined by the protection mechanism of the 80386. One purpose
of protection is to prevent applications from interfering with the operating
system; therefore, the processor makes certain registers and instructions
inaccessible to applications programs. The features discussed in Part I are
those that are accessible to applications; the features in Part II are
available only to systems software that has been given special privileges or
in unprotected systems.

The processing mode of the 80386 also determines the features that are
accessible. The 80386 has three processing modes:

   1.  Protected Mode.
   2.  Real-Address Mode.
   3.  Virtual 8086 Mode.

Protected mode is the natural 32-bit environment of the 80386 processor. In
this mode all instructions and features are available.

Real-address mode (often called just "real mode") is the mode of the
processor immediately after RESET. In real mode the 80386 appears to
programmers as a fast 8086 with some new instructions. Most applications of
the 80386 will use real mode for initialization only.

Virtual 8086 mode (also called V86 mode) is a dynamic mode in the sense
that the processor can switch repeatedly and rapidly between V86 mode and
protected mode. The CPU enters V86 mode from protected mode to execute an
8086 program, then leaves V86 mode and enters protected mode to continue
executing a native 80386 program.

The features that are available to applications programs in protected mode
and to all programs in V86 mode are the same. These features form the
content of Part I. The additional features that are available to systems
software in protected mode form Part II. Part III explains real-address
mode and V86 mode, as well as how to execute a mix of 32-bit and 16-bit
programs.

Available in All Modes             Part I .. Applications Programming

Available in Protected             Part II .. Systems Programming
Mode Only

Compatibility Modes                Part III .. Compatibility


In actuality, there are not 3 distinct modes on the 386. There are various
accumulated state variables that set different aspects of overall
operation. These various settings are largely orthogonal to each other,
but require great care to keep coordinated. "real mode" is a particular
configuration for running legacy 8086 code. The machine sets itself up
that way initially, and can be reset to that state from other states. The
analagous state-reset was not possible on the 286, except by means of an
extraordinary hack.

When the PE bit in CR0 is 1, memory protections are enforced. This means
segments are specified via the GDT or LDT. When the D-bit in a code
segment under CS is 1, the 386 interprets code as having quad operands and
addresses. When the D bit is 0, machine code is considered to be using
16-bit addresses and operands. This is a USE16 segment.

1.1.1  Part I .. Applications Programming

This part presents those aspects of the architecture that are customarily
used by applications programmers.

Chapter 2 .. Basic Programming Model: Introduces the models of memory
organization. Defines the data types. Presents the register set used by
applications. Introduces the stack. Explains string operations. Defines the
parts of an instruction. Explains addressing calculations. Introduces
interrupts and exceptions as they may apply to applications programming.

Chapter 3 .. Application Instruction Set: Surveys the instructions commonly
used for applications programming. Considers instructions in functionally
related groups; for example, string instructions are considered in one
section, while control-transfer instructions are considered in another.
Explains the concepts behind the instructions. Details of individual
instructions are deferred until Part IV, the instruction-set reference.


1.1.2  Part II .. Systems Programming

This part presents those aspects of the architecture that are customarily
used by programmers who write operating systems, device drivers, debuggers,
and other software that supports applications programs in the protected mode
of the 80386.

Chapter 4 .. Systems Architecture: Surveys the features of the 80386 that 
are used by systems programmers. Introduces the remaining registers and data
structures of the 80386 that were not discussed in Part I. Introduces the
systems-oriented instructions in the context of the registers and data
structures they support. Points to the chapter where each register, data
structure, and instruction is considered in more detail.

Chapter 5 .. Memory Management: Presents details of the data structures,
registers, and instructions that support virtual memory and the concepts of
segmentation and paging. Explains how systems designers can choose a model
of memory organization ranging from completely linear ("flat") to fully
paged and segmented.

Chapter 6 .. Protection: Expands on the memory management features of the
80386 to include protection as it applies to both segments and pages.
Explains the implementation of privilege rules, stack switching, pointer
validation, user and supervisor modes. Protection aspects of multitasking
are deferred until the following chapter.

Chapter 7 .. Multitasking: Explains how the hardware of the 80386 supports
multitasking with context-switching operations and intertask protection.

Chapter 8 .. Input/Output: Reveals the I/O features of the 80386, including
I/O instructions, protection as it relates to I/O, and the I/O permission
map.

Chapter 9 .. Exceptions and Interrupts: Explains the basic interrupt
mechanisms of the 80386. Shows how interrupts and exceptions relate to
protection. Discusses all possible exceptions, listing causes and including
information needed to handle and recover from the exception.

Chapter 10 .. Initialization: Defines the condition of the processor after
RESET or power-up. Explains how to set up registers, flags, and data
structures for either real-address mode or protected mode. Contains an
example of an initialization program.

Chapter 11 .. Coprocessing and Multiprocessing: Explains the instructions
and flags that support a numerics coprocessor and multiple CPUs with shared
memory.

Chapter 12 .. Debugging: Tells how to use the debugging registers of the
80386.


1.1.3  Part III .. Compatibility

Other parts of the book treat the processor primarily as a 32-bit machine,
omitting for simplicity its facilities for 16-bit operations. Indeed, the
80386 is a 32-bit machine, but its design fully supports 16-bit operands
and addressing, too. This part completes the picture of the 80386 by
explaining the features of the architecture that support 16-bit programs
and 16-bit operations in 32-bit programs. All three processor modes are
used to execute 16-bit programs: protected mode can directly execute
16-bit 80286 protected mode programs, real mode executes 8086 programs and
real-mode 80286 programs, and virtual 8086 mode executes 8086 programs in
a multitasking environment with other 80386 protected-mode programs. In
addition, 32-bit and 16-bit modules and individual 32-bit and 16-bit
operations can be mixed in protected mode.

Chapter 13 .. Executing 80286 Protected-Mode Code: In its protected mode,
the 80386 can execute complete 80286 protected-mode systems, because 80286
capabilities are a subset of 80386 capabilities.

Chapter 14 .. 80386 Real-Address Mode: Explains the real mode of the 80386
CPU. In this mode the 80386 appears as a fast real-mode 80286 or fast 8086
enhanced with additional instructions.

Chapter 15 .. Virtual 8086 Mode: The 80386 can switch rapidly between its
protected mode and V86 mode, giving it the ability to multiprogram 8086
programs along with "native mode" 32-bit programs.

Chapter 16 .. Mixing 16-Bit and 32-Bit Code: Even within a program or task,
the 80386 can mix 16-bit and 32-bit modules. Furthermore, any given module
can utilize both 16-bit and 32-bit operands and addresses.


1.1.4  Part IV .. Instruction Set

Parts I, II, and III present overviews of the instructions as they relate
to specific aspects of the architecture, but this part presents the
instructions in alphabetical order, providing the detail needed by
assembly-language programmers and programmers of debuggers, compilers,
operating systems, etc. Instruction descriptions include algorithmic
description of operation, effect of flag settings, effect on flag
settings, effect of operand- or address-size attributes, effect of
processor modes, and possible exceptions.


1.1.5  Appendices

The appendices present tables of encodings and other details in a format
designed for quick reference by assembly-language and systems programmers.


1.2  Related Literature

The following books contain additional material concerning the 80386
microprocessor:

  !  Introduction to the 80386, order number 231252

  !  80386 Hardware Reference Manual, order number 231732

  !  80386 System Software Writer's Guide, order number 231499

  !  80386 High Performance 32-bit Microprocessor with Integrated Memory
     Management (Data Sheet), order number 231630


1.3  Notational Conventions

This manual uses special notations for data-structure formats, for
symbolic representation of instructions, for hexadecimal numbers, and for
super- and sub-scripts. 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. A review of these notations will make it easier
to read the manual.

1.3.1  Data-Structure Formats

In illustrations of data structures in memory, smaller addresses appear at
the lower-right part of the figure; addresses increase toward the left and
upwards. Bit positions are numbered from right to left. Figure 1-1
illustrates this convention.


1.3.2  Undefined Bits and Software Compatibility

In many register and memory layout descriptions, certain bits are marked as
undefined. When bits are marked as undefined (as illustrated in Figure
1-1), it is essential for compatibility with future processors that
software treat these bits as undefined. Software should follow these
guidelines in dealing with undefined bits:

  !  Do not depend on the states of any undefined bits when testing the
     values of registers that contain such bits. Mask out the undefined bits
     before testing.

  !  Do not depend on the states of any undefined bits when storing them in
     memory or in another register.

  !  Do not depend on the ability to retain information written into any
     undefined bits.

  !  When loading a register, always load the undefined bits as zeros or
     reload them with values previously stored from the same register.

............................................................................
NOTE
  Depending upon the values of undefined register bits will make software
  dependent upon the unspecified manner in which the 80386 handles these
  bits. Depending upon undefined values risks making software incompatible
  with future processors that define usages for these bits. AVOID ANY
  SOFTWARE DEPENDENCE UPON THE STATE OF UNDEFINED 80386 REGISTER BITS.
............................................................................


Figure 1-1.  Example Data Structure

The memory used by the x86 is byte-addressable, but data can be processed
in various sizes, particularly the cell, which is normally a quad in a
USE32 segment, i.e. in 386+ application code.

Data in memory considered as five sequential quads from address 0...


address        +0             +1              +2              +3
	________________________________________________________________
0	| bits 0-7	|  bits 8-15	|  bits 16-23	|  bits 24-31	|
	|_______________________________________________________________|
4	| bits 0-7	|  bits 8-15	|  bits 16-23	|  bits 24-31	|
	|_______________________________________________________________|
8	| bits 0-7	|  bits 8-15	|  bits 16-23	|  bits 24-31	|
	|_______________________________________________________________|
12 0xc	| bits 0-7	|  bits 8-15	|  bits 16-23	|  bits 24-31	|
	|_______________________________________________________________|
16 0x10	| bits 0-7	|  bits 8-15	|  bits 16-23	|  bits 24-31	|
	|_______________________________________________________________|
	|								|


1.3.3  Instruction Operands

When instructions are represented symbolically, a subset of the 80386
Assembly Language is used. In this subset, an instruction has the following
format:

label: prefix mnemonic argument1, argument2, argument3

where:

  !  A label is an identifier that is followed by a colon.

  !  A prefix is an optional reserved name for one of the instruction
     prefixes.

  !  A mnemonic is a reserved name for a class of instruction opcodes that
     have the same function.

  !  The operands argument1, argument2, and argument3 are optional. There
     may be from zero to three operands, depending on the opcode.  When
     present, they take the form of either literals or identifiers for data
     items.  Operand identifiers are either reserved names of registers or
     are assumed to be assigned to data items declared in another part of
     the program (which may not be shown in the example). When two operands
     are present in an instruction that modifies data, the left operand is
     the source and the right operand is the destination.

For example:

LOADREG: MOV SUBTOTAL to A

In this example LOADREG is a label, MOV is the mnemonic identifier of an
opcode,  A is the destination operand, and SUBTOTAL is the source operand.

1.3.4  Hexadecimal Numbers

Base 16 numbers are represented by a string of hexadecimal digits followed
by the character H.  A hexadecimal digit is a character from the set (0, 1,
2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F).  In some cases, especially in
examples of program syntax, a leading zero is added if the number would
otherwise begin with one of the digits A-F.  For example, 0FH is equivalent
to the decimal number 15.

1.3.5  Sub- and Super-Scripts

This manual uses special notation to represent sub- and super-script
characters. Sub-script characters are surrounded by {curly brackets}, for
example 10{2} = 10 base 2. Super-script characters are preceeded by a
caret and enclosed within (parentheses), for example 10^(3) = 10 to the
third power.


		     PART I    APPLICATIONS PROGRAMMING                    


Chapter 2  Basic Programming Model

............................................................................

This chapter describes the 80386 application programming environment as
seen by assembly language programmers when the processor is executing in a
USE32 code segment in protected mode. The chapter introduces programmers
to those features of the 80386 architecture that directly affect the
design and implementation of 80386 applications programs. Other chapters
discuss 80386 features that relate to systems programming or to
compatibility with other processors of the 8086 family.

The basic programming model consists of these aspects:

  !  Memory organization and segmentation
  !  Data types
  !  Registers
  !  Instruction format
  !  Operand selection
  !  Interrupts and exceptions

Note that input/output is not included as part of the basic programming
model. Systems designers may choose to make I/O instructions available to
applications or may choose to reserve these functions for the operating
system. For this reason, the I/O features of the 80386 are discussed in Part
II.

In any desktop operating system I'm aware of, the application interface to
interrupts is limited to using the INT instruction to make a syscall. INT
is a synchronous trap, and changes the state of the machine in a way that
the operating sytem can remain in control of. Thus applications do see a
small aspect of interrupts, but the bulk of the topic is left to the
systems section. 

This chapter contains a section for each aspect of the architecture that is
normally visible to applications.


2.1  Memory Organization and Segmentation

The physical memory of an 80386 system is organized as a sequence of 8-bit
bytes. Each byte is assigned a unique address that ranges from zero to a
maximum of 2^(32) -1 (4 gigabytes), i.e. 4 gigabytes beginning at 0.

80386 programs, however, are independent of the physical address space.
This means that programs can be written without knowledge of how much
physical memory is available and without knowledge of exactly where in
physical memory the instructions and data are located.

The model of memory organization seen by applications programmers is
determined by systems-software designers. The architecture of the 80386
gives designers the freedom to choose a model for each task. The model of
memory organization can range between the following extremes:

  !  A "flat" address space consisting of a single array of up to 4
     gigabytes.

  !  A segmented address space consisting of a collection of up to 16,383
     linear address spaces of up to 4 gigabytes each.

Both models can provide memory restriction. Different tasks may employ
different models of memory organization. The criteria that designers use
to determine a memory organization model and the means that systems
programmers use to implement that model are covered in Part II..Systems
Programming.


2.1.1  The "Flat" Model

The 386 always operates with memory accesses controlled in six semantic
spaces called segments, with each segment controlled by a segment
register. A degenerate case of a segmented layout, where each segment is
maximal in size and based at physical address 0, can provide a flat model
of the machine. In a "flat" model of memory organization, the applications
programmer sees a single array of up to 2^(32) bytes (4 gigabytes). While
the physical memory can contain up to 4 gigabytes, it is usually much
smaller; the processor maps the 4 gigabyte flat space onto the physical
address space by the address translation mechanisms described in Chapter
5. Applications programmers do not need to know the details of the
mapping.

A pointer into this flat address space is a 32-bit ordinal (unsigned
integer) number that may range from 0 to 2^(32) -1.

2.1.2  The Segmented Model

In a segmented model of memory organization, the address space as viewed by
an applications program (called the logical address space) is a much larger
space of up to 2^(46) bytes (64 terabytes). The processor maps the 64
terabyte logical address space onto the physical address space (up to 4
gigabytes) by the address translation mechanisms described in Chapter 5.
Applications programmers do not need to know the details of this mapping.

Applications programmers view the logical address space of the 80386 as a
collection of up to 16,383 one-dimensional subspaces, each with a specified
length. Each of these linear subspaces is called a segment. A segment is a
unit of contiguous address space. Segment sizes may range from one byte up
to a maximum of 2^(32) bytes (4 gigabytes).

A complete pointer in this address space consists of two parts (see Figure
2-1):

  1.  A segment selector, which is a 16-bit field that identifies a
      segment.

  2.  An offset, which is a 32-bit ordinal that addresses to the byte level
      within a segment.


During execution of a program, the processor associates with a segment
selector the physical address of the beginning of the segment. Separately
compiled modules can be relocated at run time by changing the base address
of their segments, which must be done by the system software. The size of
a segment is variable; therefore, a segment can be exactly the size of the
module it contains.

2.2  Data Types

Bytes and cells are the fundamental data types (refer to Figure 2-2). A
byte is eight contiguous bits starting at any logical address. The bits
are numbered 0 through 7; bit zero is the least significant bit.

A cell is two or four contiguous bytes starting at any byte address. A
cell thus contains 16 or 32 bits. The bits of a cell are numbered from 0
through 15 or 31; bit 0 is the least significant bit in arithmetic
operations. The byte containing the lowest signifiance bit of the cell is
the lowest byte of the cell in memory. "word" often implied a cell in the
opcode dictionary section.

Each byte within a cell has its own address, and the smaller of the
addresses is the address of the cell. 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.

Note that cells need not be aligned at even-numbered addresses. This
allows maximum flexibility in data structures (e.g., records containing
mixed items) and efficiency in memory utilization. When used in a
configuration with a 32-bit bus (and larger, in post-386 devices), actual
transfers of data between processor and memory take place in units of
quads beginning at addresses evenly divisible by four; however, the
processor converts requests for misaligned cells into the appropriate
sequences of requests acceptable to the memory interface. Such misaligned
data transfers reduce performance by requiring extra memory cycles. For
maximum performance, data structures (including stacks) should be designed
in such a way that, whenever possible, cell operands are
cell-size-aligned. Due to instruction prefetching and queuing within the
CPU, there is also no requirement for instructions to be aligned on cell
boundaries.(However, a slight increase in speed results if the target
addresses of control transfers are evenly divisible by four.)

Various operations on the basic data elements impart various meanings for
those data items.

Twos-Complement signed Integer:

The negate operation considers cells and bytes as 2s-complement signed
integers. The most significant bit of a datum is the sign of the datum in
2s-complement; a 1 in that bit meaning that entire datum represents a
negative value. Conditional branches consider only a datum with all bits 0
to be the value 0, which is one advantage of twos-complement.
Ones-complement requires that either all-bits-on (the legendary "negative
zero" of ones-complement, -1 in twos-complement) or all-bits-off be
considered arithmetic zero, which the 386 does not provide explicit tests
for. 

unsigned integer:

An unsigned binary numeric value contained in a quad cell, a dual cell or
8-bit byte. All bits are considered in determining magnitude of the
number. The value range of an 8-bit ordinal number is 0-255; 16 bits can
represent values from 0 through 65,535; 32 bits can represent values from
0 through 2^(32) -1.

Near Pointer:
A 32-bit logical address. A near pointer is a 0-based offset within a
segment. Near pointers are used in either a flat or a segmented model of
memory organization.

Far Pointer:
A 48-bit logical address of two components: a 16-bit segment selector
component and a 32-bit offset component. Far pointers are used by
applications programmers only when systems designers choose a
segmented memory organization.

String:
A contiguous sequence of bytes or cells. A string may
contain from zero bytes to 2^(32) -1 bytes (4 gigabytes).

Bit field:
A contiguous sequence of bits. A bit field may begin at any bit position
of any byte and may contain up to 32 bits.

Bit string:
A contiguous sequence of bits. A bit string may begin at any bit position
of any byte and may contain up to 2^(32) -1 bits.

(see part 5 for BCD)

Figure 2-4 graphically summarizes the data types supported by the 80386.


Figure 2-1.  Two-Component Pointer
	


	 16	       0     /-->> r---------------t  0 linear  
	r---------------t   /	   |               |
	| segment 	|   |	   |               |
	|   selector	|---+	   |               |
	|		|   |	   |               |
	`--------------'    | 	   |               |    segment base in
			    \	   |               |     linear space is
			    /----- |---------------|<<--  offset 0 within
       16|32         0      |      |               | |    selected segment
      r-------|-------------+      |---------------| |    
      |    OFFSET     |     \.--->>|    OPERAND    | l
      `-------|-------'            |---------------| L-- limit of selected
			           |               | l	   segment
	                           |               | l
	                           |               | l
			           |---------------|.|
	                           |               |
				   Q               Q


Figure 2-2.  Fundamental Data Types

  7              0
 r---------------L
 |     BYTE      |  BYTE
 `---------------'



Figure 2-3.  Bytes duals and quads in Memory

		  MEMORY
       BYTE       VALUES
     ADDRESS   r----------t
	      0|          |
	       |----------|..t
	      1|    7A    |  L. quad at address 1
	       |----------|. l   contains 0x3606fe7a
	      2|    FE    | ll
	       |----------| L. dual at address 2
	      3|    06    | ll  contains 0x6fe
	       |----------|.|l
	      4|    36    |  l
	       |----------|--'
	      5|    1F    |  ,. dual at address 5
	       |----------|..|  contains 0x1f
	      6|          |
	       |----------|..t
	      7|    23    |  l
	       |----------|  L. dual at address 7
	      8|    OB    |  l   contains 0xb23
	       |----------|..|
	      9|          |
	       |----------|
	      a|          |
	       |----------|..\
	      b|    74    |  l
	       |----------|.(L. dual at address b
	      c|    CB    | ll  contains 0xcb74
	       |----------|..|
	      d|    31    | L.. dual at address c
	       |----------|.|   contains 0x31cb
	      e|          |
	       `----------'

All values in hexadecimal


Figure 2-4.  80386 Data Types


byte address  0      		      0			      0       +1
bit#	   7      0                7      0                7     0 15    8

   signed  ,,,,,,,,          byte  ,,,,,,,,          dual  ,,,,,,, ,,,,,,,, 
   byte   ||       |      unsigned|        |      signed  |       | |      |
	  /|-------'              `--------'              `------/+|-------'
   sign bit				                        /  sign bit
	    |....../              \......../                  lsb
	  7-bit magnitude      8-bit magnitude            \.......| |....../
							 15-bit magnitude


byte addr.    0       +1		   0       +1       +2      +3
bit#      7      0 15     8            7      0 15     8 23    16 24    31   

unsigned  ,,,,,,,, ,,,,,,,,    signed  ,,,,,,,, ,,,,,,,, ,,,,,,,, ,,,,,,,, 
 dual    |        |        |     quad |        |        |        ||       |
	 `-------/+--------'          `-------/+--------+--------+|-------'
     		lsb			    lsb                  /
							      sign bit	
	 \................/           \..........................| |....../
	 16-bit magnitude                               31-bit magnitude


			    0        +1       +2       +3
			 7      0 15     8 23    16 24    31
	       unsigned  ,,,,,,,, ,,,,,,,, ,,,,,,,, ,,,,,,,, 
		quad    |        |        |        |        |
			`--------+--------+--------+--------'

			\................................../
				32-bit magnitude



               0        +1       +2       +3       +4       +5  
	     7     0 15     8 23    16 24    31 7      0 15     8
USE32 far   ,,,,,,,, ,,,,,,,, ,,,,,,,, ,,,,,,,, ,,,,,,,, ,,,,,,,,
   pointer |        |        |        |        |        l        |
	   `--------+--------+--------+--------|--------+--------'
	   \................................../ \................/
		offset                              selector 



2.3  Registers

The 80386 contains a total of sixteen registers that are of interest to the
applications programmer. As Figure 2-5 shows, these registers may be
grouped into these basic categories:

  1.  Core registers. These eight 32-bit general-purpose registers are
      used primarily to contain operands for arithmetic and logical
      operations. 

  2.  Segment registers. These special-purpose registers permit systems
      software designers to choose either a flat or segmented model of
      memory organization. These six registers determine, at any given time,
      which segments of memory are currently addressable.

  3.  Status and instruction registers. These special-purpose registers are
      used to record and alter certain aspects of the 80386 processor state.


2.3.1  Core Registers

The core registers of the 80386 are the 32-bit registers A, B, C, D, SP,
BP, SI, and DI. These registers are used interchangeably to contain the
operands of most logical and arithmetic operations. They may also be used
interchangeably for operands of address computations (except that SP
cannot be used as an index operand).

As Figure 2-5 shows, the low-order word of each of these eight registers
has a separate name and can be treated as a unit. This feature is useful for
handling 16-bit data items and for compatibility with the 8086 and 80286
processors. The word registers are named AX, BX, CX, DX, BP, SP, SI, and DI.

Figure 2-5 also illustrates that each byte of the 16-bit registers AX, BX,
CX, and DX has a separate name and can be treated as a unit. This feature is
useful for handling characters and other 8-bit data items. The byte
registers are named AH, BH, CH, and DH (high bytes); and AL, BL, CL, and DL
(low bytes).

All of the core registers are available for addressing calculations and
for the results of most arithmetic and logical calculations; however, a
few functions are dedicated to certain registers. By implicitly choosing
registers for these functions, the 80386 architecture can encode
instructions more compactly. The instructions that use specific registers
include: double-precision multiply and divide, I/O, string instructions,
translate, loop, variable shift and rotate, and return stack operations.


2.3.2  Segment Registers

The segment registers of the 80386 give systems software designers the
flexibility to choose among various models of memory organization.
Implementation of memory models is the subject of Part II .. Systems
Programming. Designers may choose a model in which applications programs do
not need to modify segment registers, in which case applications programmers
may skip this section.

Complete programs generally consist of many different modules, each
consisting of instructions and data. However, at any given time during
program execution, only a small subset of a program's modules are actually
in use. The 80386 architecture takes advantage of this by providing
mechanisms to support direct access to the instructions and data of the
current module's environment, with access to additional segments on demand.

At any given instant, six segments of memory may be immediately accessible
to an executing 80386 program. The segment registers CS, DS, SS, ES, FS, and
GS are used to identify these six current segments. Each of these registers
specifies a particular kind of segment, as characterized by the associated
mnemonics ("code," "data," or "stack") shown in Figure 2-6. Each register
uniquely determines one particular segment, from among the segments that
make up the program, that is to be immediately accessible at highest speed.

The segment containing the currently executing sequence of instructions is
known as the current code segment; it is specified by means of the CS
register. The 80386 fetches all instructions from this code segment, using
as an offset the contents of the instruction pointer. CS is only changed
implicitly as the result of intersegment control-transfer instructions
(for example, CALL and JMP), interrupts, and exceptions. CS can not be
changed otherwise.

Subroutine calls, parameters, and procedure activation records (stack
frames) usually require that a region of memory be allocated for a return
stack. All stack operations use the SS register implicity to locate the
stack. Unlike CS, the SS register can be loaded explicitly, thereby
permitting programmers to define stacks dynamically.

The DS, ES, FS, and GS registers allow the specification of four data
segments, each addressable by the currently executing program. Accessibility
to four separate data areas helps programs efficiently access different
types of data structures; for example, one data segment register can point
to the data structures of the current module, another to the exported data
of a higher-level module, another to a dynamically created data structure,
and another to data shared with another task. An operand within a data
segment is addressed by specifying its offset either directly in an
instruction or indirectly via core registers.

Depending on the structure of data (e.g., the way data is parceled into one
or more segments), a program may require access to more than four data
segments. To access additional segments, the DS, ES, FS, and GS registers
can be changed under program control during the course of a program's
execution. This simply requires that the program execute an instruction to
load the appropriate segment register prior to executing instructions that
access the data. 

When a segment selector is loaded into a segment register, the selected
segment remains associated with that segment register until changed.  
When a far transfer of control changes CS, and thus the code segment, for
example, the program continues to fetch its instructions from that segment
without further manipulation of CS. The processor associates a base
address with each segment selected by a segment register. To address an
element within a segment, a 32-bit offset is added to the segment's base
address. Once a segment is selected (by loading the segment selector into
a segment register), a data manipulation instruction only needs to specify
the offset. Simple rules define which segment register is used to form an
address when only an offset is specified.


Figure 2-5.  80386 Applications Register Set

			      core REGISTERS

  31                23                15                7               0
 r-----------------|-----------------|-----------------|-----------------t
 |                                <--A-->     AH       AX      AL        |
 |-----------------|-----------------+-----------------+-----------------|
 |                                   C        CH       CX      CL        |
 |-----------------|-----------------+-----------------+-----------------|
 |                                   D        DH       DX      DL        |
 |-----------------|-----------------+-----------------+-----------------|
 |                                   B        BH       BX      BL        |
 |-----------------|-----------------+-----------------+-----------------|
 |                                   SP          (B-bit=0 SP)            |
 |-----------------|-----------------+-----------------|-----------------|
 |                                   BP          (USE16 BP)              |
 |-----------------|-----------------+-----------------|-----------------|
 |                                   SI          (USE16 SI)              |
 |-----------------|-----------------+-----------------|-----------------|
 |                                   DI          (USE16 DI)              |
 `-----------------|-----------------+-----------------|-----------------'


386 applications code is typically quad-cell, but the sub-registers of A,
C, D, and B still have many uses. Arithmetic operations on AL, for
example, do not effect the other 24 bits of A, which allows some
manipulations to be done more conveniently than with no sub-registers.

Registers are shown in the order in which they are enumerated in opcodes
that specify the register, i.e. A is always represented by three 0-bits,
DI by three 1-bits (binary 7). The core registers of the 386 are a
superset of all previous x86 devices, and can emulate them.



		      15                7               0
		     r-----------------|-----------------t
		     |         CS (CODE SEGMENT)         |
		     L...................................|
		     |         SS (STACK SEGMENT)        |
    SEGMENT          L...................................|
    REGISTERS        |         DS (DATA SEGMENT)         |
		     L...................................|
		     |         ES (DATA SEGMENT)         |
		     L...................................|
		     |         FS (DATA SEGMENT)         |
		     L...................................|
		     |         GS (DATA SEGMENT)         |
		     `-----------------------------------'


		       STATUS AND INSTRUCTION REGISTERS

     31               23                15                7              0
   r-----------------|-----------------|-----------------|-----------------l
   |                                EFLAGS                                 |
   L.......................................................................|
   |                         IP (INSTRUCTION POINTER)                      |
   `-----------------|-----------------|-----------------|-----------------'


Figure 2-6.  Use of Memory Segmentation

     r----------------t                                r----------------t
     |     MODULE     |                                |     MODULE     |
     |       A        |<<-t                        ,->>|       A        |
     |      CODE      |   l                        l   |      DATA      |
     `----------------'   l  r------------------t  l   `----------------'
			  L..|    CS (CODE)     |  l
			     |------------------|  l
     r----------------t   r..|    SS (STACK)    |  l   r----------------t
     |                |   l  |------------------|  l   |      DATA      |
     |     STACK      |<<-|  |    DS (DATA)     L..|t.#|   STRUCTURE    |
     |                |      |------------------|   l  |       1        |
     `----------------'      |    ES (DATA)     L...|  `----------------'
			     |------------------|
			  /..|    FS (DATA)     |
     r----------------t   l  |------------------|      r----------------t
     |      DATA      |   l  |    GS (DATA)     L..,   |      DATA      |
     |   STRUCTURE    |<<-/  |------------------'  L->>|   STRUCTURE    |
     |       2        |                                |       3        |
     `----------------'                                `----------------'

CS is always code, always the only executable segment, and can only be
changed with far jumps of various kinds.


2.3.3  Stack Implementation

Stack operations are facilitated by three registers:

  1.  The stack segment (SS) register. Stacks are implemented in memory. A
      system may have a number of stacks that is limited only by the maximum
      number of segments. A stack may be up to 4 gigabytes long, the maximum
      length of a segment. One stack is directly addressable at a time..the
      one located by SS. This is the current return stack, often referred to 
      simply as "the" stack. SS is used automatically by the processor for all
      basic stack operations such as subroutine return address management.

  2.  The stack pointer (SP) register. SP points to the top item on the
      push-down stack (TOS). It is referenced implicitly by PUSH and POP
      operations, subroutine calls and returns, and interrupt operations.
      When an item is pushed onto the stack (see Figure 2-7), the processor
      decrements SP, then writes the item at the new TOS. When an item is
      popped off the stack, the processor copies it from TOS, then
      increments SP. In other words, the stack grows down in memory toward
      lesser addresses. 

  3.  The stack-frame base pointer (BP) register. The ENTER and LEAVE 
      instructions use BP implicitly to implement high-level procedure frames
      for scoped-context programming languages such as Pascal.


Figure 2-7.  80386 Stack, quad addressing (USE32 CS)

TOS is Top of Stack, which is a current data item on 386, not a vacancy.
Stack grows toward lower addresses, shown up-the-page here.
         
                                                              A  
		 A	       +0     +1     +2     +3        | direction of
                 |                                            | growth. Data 
lower addresses-/	    |------|------|------|------|     | above TOS 
			-c  |                           |     | (at lower 
			    |------|------|------|------|     | addresses) is
			-8  |                           |     | typically 
			    |------|------|------|------|    / useless due to
			-4  |                           |   /   unknown effects
			    |------|------|------|------|--/   of stack use by
		SP------>>> |                           |  \    unrelated
	(byte 0 of TOS)     |------|------|------|------|   \    processes
			+4  |                           |    |
			    |------|------|------|------|    | 
  			+8  |                           |    | previously
			    |------|------|------|------|     \  stacked data,
			+c  |                           |      | still valid
			    |------|------|------|------|      | 
			+12 |                           |      |
			    |------|------|------|------|      |
			    |                           |      V
			~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~		
			    |------|------|------|------|
			    |                           |
			    |------|------|------|------|
			    |                           |
			    `------+------+------+------' 
			   /	
		          /
                     initial SP


A stack segment may be specified by system software with a 16 or 32 bit
SP, independant of address sizes code is currently using. The +4 +8 and +c
(12 in hexadecimal) are relative to SP.


2.3.4  Flags Register

The flags register is a 32-bit register named EFLAGS. Figure 2-8 defines
the bits within this register. The flags control certain operations and
indicate the status of the 80386, and are tested by conditional branching
instructions.

The low-order 16 bits of EFLAGS is named FLAGS and can be treated as a
unit. This feature is useful when executing 8086 and 80286 code, because
this part of EFLAGS is identical to the FLAGS register of the 8086 and the
80286.

The flags may be considered in three groups: the status flags, the control
flags, and the systems flags. Discussion of the systems flags is delayed
until Part II.


Figure 2-8.  EFLAGS Register  

					      16-BIT FLAGS REGISTER
							 A
				     /...................L...............\

  31                  23                 |15              7             0
 r-------------------|---------------,-,-|-,-,-+-,-,-,-,-,-,-,-,-,-,-,-,-t
 |                                   |V|R|0lNlIO lOlDlIlTlSlZl0lAl0lPl lC|
 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | | |0l l - l l l l l l l0l l0l l1l |
 |                                   |M|F|0|T| PL|F|FlFlFlFlFl0lFl0lFl lF|
 `-------------------|---------------L,L,L-L,L-+-L,L,L,L,L,L,L-L,L-L,L-L,/
				      l l   l  l  l l l l l l   l   l   l
       VIRTUAL 8086 MODE...X........../ l   l  l  l l l l l l   l   l   l
	     RESUME FLAG...X............/   l  l  l l l l l l   l   l   l
	NESTED TASK FLAG...X................/  l  l l l l l l   l   l   l
2-bit I/O PRIVILEGE LEVEL..X.................../  l l l l l l   l   l   l
		OVERFLOW...S....................../ l l l l l   l   l   l
	  DIRECTION FLAG...C......................../ l l l l   l   l   l
	INTERRUPT ENABLE...X........................../ l l l   l   l   l
	       TRAP FLAG...S............................/ l l   l   l   l
	       SIGN FLAG...S............................../ l   l   l   l
	       ZERO FLAG...S................................/   l   l   l
	 AUXILIARY CARRY...S..................................../   l   l
	     PARITY FLAG...S......................................../   l
	      CARRY FLAG...S............................................/

	  S = STATUS FLAG, C = CONTROL FLAG, X = SYSTEM FLAG

	  Status flags are used by conditional branches.

	  NOTE: 0 OR 1 INDICATES INTEL RESERVED. DO NOT DEFINE


2.3.4.1  Status Flags

The status flags of the EFLAGS register allow the results of one
instruction to influence later 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.
There are instructions to set, clear, and complement CF before execution of
an arithmetic instruction. Refer to Appendix C for definition of each
status flag.


2.3.4.2  Control Flag

The control flag DF of the EFLAGS register controls string instructions.

DF (Direction Flag, bit 10)

  Setting DF to 1 causes string instructions to auto-decrement; that is, to
  process strings from high addresses to low addresses. Clearing DF causes
  string instructions to auto-increment, or to process strings from low
  addresses to high addresses.


2.3.4.3  Instruction Pointer

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. The instruction pointer is not directly
visible to the programmer; it is controlled implicitly by control-transfer
instructions, interrupts, and exceptions. What IP was recently can be
obtained with stack manipulations related to subroutines, since call e.g.
PUSHes IP onto the stack.

As Figure 2-9 shows, the low-order 16 bits of IP is named IP also and can
be used by the processor as a unit (in a USE16 CS segment). This feature
is useful when executing instructions designed for the 8086 and 80286
processors, or in extreme code-density circumstances like embedded
devices.


Figure 2-9.  Instruction Pointer Register

						 16-BIT IP REGISTER
				       /..................L................\

    31                23                15                7               0
   r-----------------|-----------------|-----------------|-----------------L
   |                        IP (INSTRUCTION POINTER)                       |
   `-----------------|-----------------|-----------------|-----------------'


2.4  Instruction Format

The information encoded in an 80386 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.

80386 instructions are composed of various elements and have various
formats. The exact format of instructions is shown in Appendix B; the
elements of instructions are described below. Of these instruction 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. The elements of an instruction, in order
of occurrence are as follows:

  !  Prefixes .. one or more bytes preceding an instruction that modify the
     operation of the instruction. The following types of prefixes can be
     used by applications programs:

     1.  Segment override .. explicitly specifies which segment register an
	 instruction should use, thereby overriding the default
	 segment-register selection used by the 80386 for that instruction.

     2.  Address size .. switches between 32-bit and 16-bit address 
	 generation.

     3.  Operand size .. switches between 32-bit and 16-bit operands.

     4.  Repeat .. used with a string instruction to cause the instruction
	 to act on each element of the string.

  !  Opcode .. specifies the operation performed by the instruction. Some
     operations have several different opcodes, each specifying a different
     variant of the operation.

  !  Register specifier .. an instruction may specify one or two register
     operands. Register specifiers may occur either in the same byte as the
     opcode or in the same byte as the addressing-mode specifier.

  !  Addressing-mode specifier .. when present, specifies whether an operand
     is a register or memory location; if in memory, specifies whether a
     displacement, a base register, an index register, and scaling are to be
     used.

  !  SIB (scale, index, base) byte .. when the addressing-mode specifier
     indicates that an index register will be used to compute the address of
     an operand, an SIB byte is included in the instruction to encode the
     base register, the index register, and a scaling factor.

  !  Displacement .. when the addressing-mode specifier indicates that a
     displacement will be used to compute the address of an operand, the
     displacement is encoded in the instruction. A displacement is a signed
     integer of 32, 16, or eight bits. The eight-bit form is used in the
     common case when the displacement is sufficiently small. The processor
     extends an eight-bit displacement to 16 or 32 bits, taking into
     account the sign.

  !  Immediate operand .. when present, directly provides the value of an
     operand of the instruction. Immediate operands may be 8, 16, or 32 bits
     wide. In cases where an eight-bit immediate operand is combined in some
     way with a 16- or 32-bit operand, the processor automatically extends
     the size of the eight-bit operand, taking into account the sign.

A 386 programmer will not typically be concerned with MOD-R/M or SIB bytes
unless writing an assembler.


2.5  Operand Selection

An instruction can act on zero or more operands, which are the data
manipulated by the instruction. An example of a zero-operand instruction is
NOP (no operation). An operand can be in any of these locations:

  !  In the instruction itself (an immediate operand)

  !  In a register ( A, B, C, D, SI, DI, SP, or  BP in the case
     of 32-bit operands; 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 segment registers; or the EFLAGS register for flag
     operations)

  !  In memory

  !  At 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,
and immediate operands already were as part of instruction cacheing.  
Register operands are available in the CPU.

Of the instructions that have operands, some specify operands implicitly;
others specify operands explicitly; still others use a combination of
implicit and explicit specification; for example:

The basic Boolean, arithmetic and copy operators usually have explicit
(shorter, faster) forms involving the A register.

Implicit operand: AAM

  By definition, AAM (ASCII adjust for multiplication) operates on the
  contents of the AX register. I have deprecated the ASCII and BCD
  instructions here.

Explicit operand: XCHG  A, B

  The operands to be exchanged are encoded in the instruction after the
  opcode.

Implicit and explicit operands: PUSH COUNTER

  The memory variable COUNTER (the explicit operand) is copied to the top of
  the stack (the implicit operand).

Note that most instructions have implicit operands. All arithmetic
instructions, for example, update the EFLAGS register.

An 80386 instruction can explicitly reference one or two operands.
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 unaffected by the
operation) and the destination operand (the one overwritten by the result).

For most instructions, one of the two explicitly specified operands -
either the source or the destination - can be either in a register or in
memory. The other operand must be in a register or be an immediate source
operand. Memory-to-memory is not a basic addressing mode of the 386, as on
RISCs.  Thus, the explicit two-operand instructions of the 80386 permit
operations of the following kinds:

  !  Register-to-register
  !  Register-to-memory
  !  Memory-to-register
  !  Immediate-to-register
  !  Immediate-to-memory

Certain string instructions and stack manipulation instructions, however,
transfer data from memory to memory. Both operands of some string
instructions are in memory and are implicitly specified. Also, push and
pop stack operations allow transfer between memory operands and the
memory-based stack.

2.5.1  Immediate Operands

Certain instructions use data from the instruction itself as one (and
sometimes two) of the operands. Such an operand is called an immediate
operand. The operand may be 32-, 16-, or 8-bits long. For example:

SHR 2, pattern

One byte of the instruction holds the value 2, the number of bits by which
to shift the variable PATTERN.

TEST 0FFFF00FFH, pattern

A quad of the instruction holds the mask that is used to test the variable
PATTERN.


2.5.2  Register Operands


Operands may be located in one of the 32-bit core registers (A, C, D, B,
SP, BP, SI or DI), in one of the 16-bit core registers (AX, CX, DX, BX,
SP, BP, SI or DI), or in one of the 8-bit core registers (AH, AL, CH, CL,
DH, DL, BH, BL).

The 80386 has instructions for explicitly copying between the segment
registers other than CS (DS, ES, SS, FS, GS) and A. These instructions are
used by applications programs only if systems designers have chosen a
segmented memory model.

The 80386 also has instructions for referring to the flag register. The
flags may be stored on the stack and restored from the stack implicity or
by INT and IRET. Certain instructions change the commonly modified flags
directly in the EFLAGS register. Other flags that are seldom modified can
be modified indirectly via the flags image in the stack, with varying
degrees of difficulty proportional to thier system ramifications. (The VM
bit only changes in regard to interrupts involving Virtual 8086 segments,
for example. An application can see system flags but typically can't
change them.).


2.5.3  Memory Operands

All memory access is controlled by segment registers, but the segment
registers only need to be modified when changing segments.

An 80386 data-manipulation instruction that accesses memory uses one of the
following methods for specifying the offset of a memory operand within its
segment:

  1.  Most data-manipulation instructions that access memory contain a byte
      that explicitly specifies the addressing method for the operand. A
      byte, known as the modR/M byte, follows the opcode and specifies
      whether the operand is in a register or in memory. If the operand is
      in memory, the address is computed from a segment register and any of
      the following values: a base register, an index register, a scaling
      factor, a displacement. When an index register is used, the modR/M
      byte is also followed by another byte that identifies the index
      register and scaling factor. This addressing method is the
      most flexible. Elaborate addressing modes are efficient for accessing
      complex data structures.

  2.  A few data-manipulation instructions implicitly use specialized
      addressing methods:

      !   For a few short forms of MOV that implicitly use the A register,
	  the offset of the operand is coded as a quad in the
	  instruction, i.e. follows the opcode immediately in CS. No base 
	  register, index register, or scaling factor are used.

      !   String operations implicitly address memory via DS:SI, (MOVS,
	  CMPS, OUTS, LODS, SCAS) or via ES:DI (MOVS, CMPS, INS, STOS).
	  NOTE: not DS, ES.

      !   Stack operations implicitly address operands via SS:SP
	  registers; e.g., PUSH, POP, PUSHA, PUSHAD, POPA, POPAD, PUSHF,
	  PUSHFD, POPF, POPFD, CALL, RET, IRET, IRETD, exceptions, and
	  interrupts. ENTER and LEAVE implicitly use SP, SP and BP.


2.5.3.1  Segment Selection

Data-manipulation instructions need not explicitly specify which segment
register is used. For all of these instructions, specification of a segment
register is optional. For all memory accesses, if a segment is not
explicitly specified by the instruction, the processor automatically chooses
a segment register according to the rules of Table 2-1. (If systems
designers have chosen a flat model of memory organization, the segment
registers and the rules that the processor uses in choosing them are not
apparent to applications programs.)

There is a close connection between the kind of memory reference and the
segment in which that operand resides. As a rule, a memory reference implies
the current data segment (i.e., the implicit segment selector is in DS).
However, SP and BP are used to access items on the stack; therefore, when
the SP or BP register is used as a base register, the current stack
segment is implied (i.e., SS contains the selector).

Special instruction prefix elements may be used to override the default
segment selection. Thus one can specify a segment for an instruction
temporarily from among segments currently in use but not the normal
implicit segment for that instruction. The 80386 has a segment-override
prefix for each of the segment registers. The segment-override prefixes
are one byte each in machine code, and are widely applicable. Only in the
following special cases is there an implied segment selection that a
segment prefix cannot override:

  !  The use of ES for destination strings in string instructions.
  !  The use of SS in stack instructions.
  !  The use of CS for instruction fetches.



Table 2-1. Default Segment Register Selection Rules

			 Segment
			  Register
Memory Reference Needed	   Used      Implicit Segment Selection Rule


Instructions             Code (CS)   Automatic with instruction prefetch

Stack                    Stack (SS)  All stack pushes and pops. Any
				     memory reference that uses SP or
				      BP as a base register.

Local Data               Data (DS)   All data references except when
				     relative to stack or string 
				     destination.

Destination Strings      Extra (ES)  Destination of string instructions.


2.5.3.2  Effective-Address Computation

The modR/M byte provides the most flexible of the addressing methods, and
instructions that require a modR/M byte as the second byte of the
instruction are the most common in the 80386 instruction set. For memory
operands defined by modR/M, the offset within the desired segment is
calculated by taking the sum of up to three components:

  !  A displacement element in the instruction.

  !  A base register.

  !  An index register. The index register may be automatically multiplied
     by a scaling factor of 2, 4, or 8.

The offset that results from adding these components is called an effective
address. Each of these components of an effective address may have either a
positive or negative value. If the sum of all the components exceeds 2^(32),
the effective address is truncated to 32 bits. Figure 2-10 illustrates the
full set of possibilities for modR/M addressing.

The displacement component, because it is encoded in the instruction, is
useful for fixed aspects of addressing; for example:

  !  Location of simple scalar operands.
  !  Beginning of a statically allocated array.
  !  Offset of an item within a record.

The base and index components have similar functions. Both utilize the
same set of core registers. Both can be used for aspects of addressing
that are determined dynamically; for example:

  !  Location of procedure parameters and local variables in stack.

  !  The beginning of one record among several occurrences of the same
     record type or in an array of records.

  !  The beginning of one dimension of multiple dimension array.

  !  The beginning of a dynamically allocated array.

The uses of core registers as base or index components differ in the
following respects:

  !  SP cannot be used as an index register.

  !  When SP or BP is used as the base register, the default segment is
     the one selected by SS. In all other cases the default segment is DS.

The scaling factor permits efficient indexing into an array in the common
cases when array elements are 2, 4, or 8 bytes wide. The shifting of the
index register is done by the processor at the time the address is evaluated
with no performance loss. This eliminates the need for a separate shift or
multiply instruction.

The base, index, and displacement components may be used in any
combination; any of these components may be null. A scale factor can be used
only when an index is also used. Each possible combination is useful for
data structures commonly used by programmers in high-level languages and
assembly languages. Following are possible uses for some of the various
combinations of address components.

DISPLACEMENT

   The displacement alone indicates the offset of the operand. This
   combination is used to directly address a statically allocated scalar
   operand. An 8-bit, 16-bit, or 32-bit displacement can be used.

BASE

   The offset of the operand is specified indirectly in one of the core
   registers, as for "based" variables.

BASE + DISPLACEMENT

   A register and a displacement can be used together for two distinct
   purposes:

   1.  Index into static array when element size is not 2, 4, or 8 bytes.
       The displacement component encodes the offset of the beginning of
       the array. The register holds the results of a calculation to
       determine the offset of a specific element within the array.

   2.  Access item of a record. The displacement component locates an
       item within record. The base register selects one of several
       occurrences of record, thereby providing a compact encoding for
       this common function.

   An important special case of this combination, is to access parameters
   in the procedure activation record in the stack. In this case, BP is
   the best choice for the base register, because when BP is used as a
   base register, the processor automatically uses the stack segment
   register (SS) to locate the operand, thereby providing a compact
   encoding for this common function.

(INDEX * SCALE) + DISPLACEMENT

   This combination provides efficient indexing into a static array when
   the element size is 2, 4, or 8 bytes. The displacement addresses the
   beginning of the array, the index register holds the subscript of the
   desired array element, and the processor automatically converts the
   subscript into an index by applying the scaling factor.

BASE + INDEX + DISPLACEMENT

   Two registers used together support either a two-dimensional array (the
   displacement determining the beginning of the array) or one of several
   instances of an array of records (the displacement indicating an item
   in the record).

BASE + (INDEX * SCALE) + DISPLACEMENT

   This combination provides efficient indexing of a two-dimensional array
   when the elements of the array are 2, 4, or 8 bytes wide.


Figure 2-10.  Effective Address Computation

      SEGMENT +    BASE   +    (INDEX * SCALE)  +     DISPLACEMENT
		 )     (
		 l --- l     )     (     )   (
      )    (     l  A l     l  A l     l 1 l
      l CS l     l C l     l C l     l   l     )                     (
      l SS l     l D l     l D l     l 2 l     l     NO DISPLACEMENT l
     .| DS L. + .| B L. + .| B L. * .|   L. + .|  8-BIT DISPLACEMENT L.
      l ES l     l SP l     l --- l     l 4 l     l 32-BIT DISPLACEMENT l
      l FS l     l  BP l     l  BP l     l   l     L                     |
      l GS l     l SI l     l SI l     l 6 l
      L    |     l DI l     l DI l     L   |
		 L     |     L     |

I'm told RISCs typically do not have a 3-register addressing mode.
Conversely, most CISCs have meory-to-memory, which the 386 only supports
in push, pop and string operations. Avoiding two-register addressing makes
386 code more easily ported to other devices at some possible performance
cost.

2.6  Interrupts and Exceptions

The 80386 has two mechanisms for interrupting program execution:

  1.  Exceptions are synchronous events that are the responses of the CPU
      to certain conditions detected during the execution of an instruction.

  2.  Interrupts are asynchronous events typically triggered by external
      devices needing attention.

Interrupts and exceptions are alike in that both cause the processor to
temporarily suspend its present program execution in order to execute a
program of higher priority. The major distinction between these two kinds of
interrupts is their origin. An exception is always reproducible by
re-executing with the program and data that caused the exception, whereas an
interrupt is generally independent of the currently executing program.

Application programmers are not normally concerned with servicing
interrupts. More information on interrupts for systems programmers may be
found in Chapter 9. Certain exceptions, however, are of interest to
applications programmers, and many operating systems give applications
programs the opportunity to service these exceptions. However, the
operating system itself defines the interface between the applications
programs and the exception mechanism of the 80386. 


Table 2-2 highlights the exceptions that may be of interest to applications
programmers.

  !  A divide error exception results when the instruction DIV or IDIV is
     executed with a zero denominator or when the quotient is too large for
     the destination operand. (Refer to Chapter 3 for a discussion of DIV
     and IDIV.)

  !  The debug exception may be reflected back to an applications program
     if it results from the trap flag (TF).

  !  A breakpoint exception results when the instruction INT 3 is executed.
     This instruction is used by some debuggers to stop program execution at
     specific points.

  !  An overflow exception results when the INTO instruction is executed
     and the OF (overflow) flag is set (after an arithmetic operation that
     set the OF flag). (Refer to Chapter 3 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. (Refer to Chapter 3 for a discussion of the BOUND instruction.)

  !  Invalid opcodes may be used by some applications to extend the
     instruction set. In such a case, the invalid opcode exception presents
     an opportunity to emulate the opcode.

  !  The "coprocessor not available" exception occurs if the program
     contains instructions for a coprocessor, but no coprocessor is present
     in the system.

  !  A coprocessor error is generated when a coprocessor detects an illegal
     operation.

The instruction INT generates an interrupt whenever it is executed; the
processor treats this interrupt as an exception. The effects of this
interrupt (and the effects of all other exceptions) are determined by
exception handler routines provided by the application program or as part of
the systems software (provided by systems programmers). The INT instruction
itself is discussed in Chapter 3. Refer to Chapter 9 for a more complete
description of exceptions.

The typical syscall is usually implemented with the INT instruction, a
synchronous trap. The application programmer just sees the INT side of
that, and the results provided by the system in question.


Table 2-2. 80386 Reserved Exceptions and Interrupts

Vector Number      Description

0                  Divide Error
1                  Debug Exceptions
2                  NMI Interrupt
3                  Breakpoint
4                  INTO Detected Overflow
5                  BOUND Range Exceeded
6                  Invalid Opcode
7                  Coprocessor Not Available
8                  Double Exception
9                  Coprocessor Segment Overrun
10                 Invalid Task State Segment
11                 Segment Not Present
12                 Stack Fault
13                 General Protection
14                 Page Fault
15                 (reserved)
16                 Coprocessor Error
17-32              (reserved)


Chapter 3  Applications Instruction Set

............................................................................

This chapter presents an overview of the instructions which programmers can
use to write application software for the 80386 executing in protected
virtual-address mode. The instructions are grouped by categories of related
functions.

The instructions not discussed in this chapter are those that are normally
used only by operating-system programmers. Part II describes the operation
of these instructions.

The descriptions in this chapter assume that the 80386 is operating in
protected mode with 32-bit addressing in effect; however, all instructions
discussed are also available when 16-bit addressing is in effect in
protected mode, real mode, or virtual 8086 mode. For any differences of
operation that exist in the various modes, refer to Chapter 13,
Chapter 14, or Chapter 15.

The instruction dictionary in Chapter 17 contains detailed reference
descriptions of all instructions, including encoding, operation, timing,
effect on flags, and potential exceptions.


3.1  Data Movement Instructions

These instructions provide convenient methods for moving bytes or cells of
data between memory and the registers of the base architecture. They fall
into the following classes:

  1.  General-purpose data movement instructions.
  2.  Stack manipulation instructions.
  3.  Type-conversion instructions (sign-extend e.g.).


3.1.1  General-Purpose Data Movement Instructions

MOV (Move) copies a byte or cell from the source operand to
the destination operand, "clobbering" and previous value in the
destination. The MOV instruction is useful for transferring data along any
of these paths ...

  !  To a register from memory
  !  To memory from a register
  !  Between core registers
  !  Immediate data to a register
  !  Immediate data to a memory

There are also variants of MOV that operate on segment registers.  These
are covered in a later section of this chapter. MOV with A is how system
registers are controlled, which is desribed in the system programming
section.

The MOV instruction cannot move from memory to memory or from segment
register to segment register are not allowed. Memory-to-memory moves can
be performed, however, by the string move instruction MOVS, given
appropriate values in SI and DI.

XCHG (Exchange) swaps the contents of two operands. This instruction takes
the place of three MOV instructions. It does not require a temporary
location to save the contents of one operand while load the other is being
loaded. XCHG is especially useful for implementing semaphores or similar
data structures for process synchronization, another systems issue.

The XCHG instruction can swap two byte operands or two cells. 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. Bus-locking is important for
multi-master busses, such as symmetrical multi-processing systems. (Refer
to Chapter 11 for more information on the bus lock.) 386 NOP, by the way,
is actually XCHG A with A.


3.1.2  Stack Manipulation Instructions

PUSH (Push) decrements the stack pointer (SP) by the size of the operand,
then transfers the source operand to the top of stack indicated by SP (see
Figure 3-1). Thus the stack grows toward lower addresses. 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.  
Variables pushed between return addresses are effectively "local
variables" to the routine that pushed them, while being a bit less volitle
than values in registers. The PUSH instruction operates on memory
operands, immediate operands, and register operands (including segment
registers).

PUSHA (Push All Registers) saves the contents of the eight core 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 core registers for use in a procedure. The processor pushes the core
registers on the stack in the following order: A, C, D, B, the initial
value of SP before A was pushed, BP, SI, and DI. PUSHA is complemented by
the POPA instruction. (pusha is "pushcore" in osimplay.)

POP (Pop) transfers the cell at the current top of stack (indicated by SP)
to the destination operand, and then increments SP to point to the new top
of stack. See Figure 3-3. POP moves information from the stack to a
core register, or to memory There are also a variant of POP that
operates on segment registers. This is covered in a later section of this
chapter.

POPA (Pop All Registers) restores the registers saved on the stack by
PUSHA, except that it ignores the saved value of SP. See Figure 3-4.


Figure 3-1.  PUSH

Memory addresses decrease down-the-page in this diagram. Dual cells are 
implied, but not particularly different than quad cells in this context. 


                |               |           |               |
                |-------|-------|           |-------|-------|
                |               |           |               |
                |-------|-------|           |-------|-------|
                |               |           |               |
                |-------|-------|           |-------|-------|
                |               |         SP|    OPERAND    |
                |-------|-------|           |-------|-------|
              SP|XXXXXXXXXXXXXXX|           |XXXXXXXXXXXXXXX|
                |-------|-------|           |-------|-------|
                |XXXXXXXXXXXXXXX|           |XXXXXXXXXXXXXXX|
                |-------|-------|           |-------|-------|
                |               |           |               |

                   BEFORE PUSH                  AFTER PUSH



Figure 3-2.  PUSHA

lower addresses

                |               |           |               |
                |-------|-------|           |-------|-------|
                |               |           |               |
                |-------|-------|           |-------|-------|
                |               |         SP|       DI      |
                |-------|-------|           |-------|-------|
                |               |           |       SI      |
                |-------|-------|           |-------|-------|
                |               |           |       BP      |
                |-------|-------|           |-------|-------|
                |               |           |    OLD SP     |
                |-------|-------|           |-------|-------|
                |               |           |       BX      |
                |-------|-------|           |-------|-------|
                |               |           |       DX      |
                |-------|-------|           |-------|-------|
                |               |           |       CX      |
                |-------|-------|           |-------|-------|
                |               |           |       AX      |
                |-------|-------|           |-------|-------|
              SP|XXXXXXXXXXXXXXX|           |XXXXXXXXXXXXXXX|
                |-------|-------|           |-------|-------|
                |XXXXXXXXXXXXXXX|           |XXXXXXXXXXXXXXX|
                |-------|-------|           |-------|-------|
                |               |           |               |
                   BEFORE PUSHA                AFTER PUSHA


3.1.3  Type Conversion Instructions

The type conversion instructions convert bytes into duals, duals into
quads, and quads into 64-bit items (octo-somethings I guess). These
instructions are especially useful for converting signed integers, because
they automatically fill the extra bits of the larger item with the value of
the sign bit of the smaller item. This kind of conversion, illustrated by
Figure 3-5, is called sign extension.

There are two classes of type conversion instructions:

  1.  The forms CWD, CDQ, CBW, and CWDE which operate only on data in the
      A register.

  2.  The forms MOVSX and MOVZX, which permit one operand to be in any
      core register while permitting the other operand to be in memory or
      in a register.

I'll leave this description in INTeLese due to the dependance on INTeL
lingo in the instruction mnemonic itself. CWD (Convert Word to Doubleword)
and CDQ (Convert Doubleword to Quad-Word) double the size of the source
operand. CWD extends the sign of the word in register AX throughout
register DX. CDQ extends the sign of the doubleword in  A throughout D.
CWD can be used to produce a doubleword dividend from a word before a word
division, and CDQ can be used to produce a quad-word dividend from a
doubleword before doubleword division.

CBW (Convert Byte to Word) extends the sign of the byte in register AL
throughout AX.

CWDE (Convert Word to Doubleword Extended) extends the sign of the word in
register AX throughout  A.

MOVSX (Move with Sign Extension) sign-extends an 8-bit value to a 16-bit
value and a 8- or 16-bit value to 32-bit value.

MOVZX (Move with Zero Extension) extends an 8-bit value to a 16-bit value
and an 8- or 16-bit value to 32-bit value by inserting high-order zeros.




Figure 3-5.  Sign Extension

				    15                7             0
				    D-t--------------|----------------L
     BEFORE SIGN EXTENSION      /->>|S| N N N N N N N N N N N N N N N |
				|   `-+--------------|----------------'
			       sign bit
     AFTER SIGN EXTENSION
			       
    31               23             15              7             0
    D-t-------------|---------------|---------------|---------------L
    |S|S S S S S S S S S S S S S S S S N N N N N N N N N N N N N N N|
    `-+-------------|---------------|---------------|---------------'


3.2  Binary Arithmetic Instructions

The arithmetic instructions of the 80386 processor simplify the
manipulation of numeric data that is encoded in binary. Operations include
the standard add, subtract, multiply, and divide as well as increment,
decrement, compare, and change sign. Both signed and unsigned binary
integers are supported.

Many of the arithmetic instructions operate on both signed and unsigned
integers. These instructions update the flags ZF, CF, SF, and OF in such a
manner that subsequent instructions can interpret the results of the
arithmetic as either signed or unsigned. CF contains information relevant
to unsigned integers; SF and OF contain information relevant to signed
integers. ZF is relevant to both signed and unsigned integers; ZF is set
when all bits of the result (the value left in the destination) are zero.

If the integer is unsigned, CF may be tested after one of these arithmetic
operations to determine whether the operation required a carry or borrow of
a one-bit in the high-order position of the destination operand. CF is set
if a one-bit was carried out of the high-order position (addition
instructions ADD, ADC, AAA, and DAA) or if a one-bit was carried (i.e.
borrowed) into the high-order bit (subtraction instructions SUB, SBB, AAS,
DAS, CMP, and NEG).

If the integer is signed, both SF and OF should be tested. SF always has
the same value as the sign bit of the result. The most significant bit (msb)
of a signed integer is the bit next to the sign; bit 6 of a byte, bit 14 of
a dual, or bit 30 of a quad. OF is set in either of these cases:

  !  A one-bit was carried out of the MSB into the sign bit but no one bit
     was carried out of the sign bit (addition instructions ADD, ADC, INC,
     AAA, and DAA). In other words, the result was greater than the greatest
     positive number that could be contained in the destination operand.

  !  A one-bit was carried from the sign bit into the MSB but no one bit
     was carried into the sign bit (subtraction instructions SUB, SBB, DEC,
     AAS, DAS, CMP, and NEG). In other words, the result was smaller that
     the lowest negative number that could be contained in the destination
     operand.

These status flags are tested by executing one of the two families of
conditional instructions: Jcc (jump on condition cc) or SETcc (byte set on
condition).


3.2.1  Addition and Subtraction Instructions

ADD (Add Integers) replaces the destination operand with the sum of the
source and destination operands. Sets CF if overflow.

ADC (Add Integers with Carry) sums the operands, adds one if CF is set,
and replaces the destination operand with the result. If CF is cleared
(0), ADC performs the same operation as the ADD instruction. An ADD
followed by multiple ADC instructions can be used to add numbers longer
than 32 bits. 

INC (Increment) adds one to the destination operand. INC does not affect
CF. Use ADD with an immediate value of 1 if an increment that updates carry
(CF) is needed.

SUB (Subtract Integers) subtracts the source operand from the destination
operand and replaces the destination operand with the result. If a borrow
is required, the CF is set. The operands may be signed or unsigned bytes
or cells.

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. If CF is cleared, SBB performs the same operation as
SUB. SUB followed by multiple SBB instructions may be used to subtract
numbers longer than 32 bits. If CF is cleared, SBB performs the same
operation as SUB.

DEC (Decrement) subtracts 1 from the destination operand. DEC does not
update CF. Use SUB with an immediate value of 1 to perform a decrement that
affects carry.


3.2.2  Comparison and Sign Change Instruction

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. CMP and TEST are used to set flags for conditional
actions.

NEG (Negate) subtracts a signed integer operand from zero. The effect of
NEG is to reverse the sign of the operand from positive to negative or
from negative to positive, in twos-complement. Twos-complement negate is a
Boolean NOT followed by a carryless unsigned add of 1. This can be
visualized by what must happen to negate zero and get a result of zero.


3.2.3  Multiplication Instructions

The 80386 has separate multiply instructions for unsigned and signed
operands. MUL operates on unsigned numbers, while IMUL operates on signed
integers as well as unsigned.

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 dual, the processor multiplies it
by the contents of AX and returns the double-length result to DX and AX.
If the source operand is a quad, the processor multiplies it by the
contents of A and returns the 64-bit result in D and A. D is the
high-order half of the result. MUL sets CF and OF when the upper half of
the result is nonzero; otherwise, they are cleared.

IMUL (Signed Integer Multiply) performs a signed multiplication operation.
IMUL has three variations:

  1.  A one-operand form. The operand may be a byte or cell
      located in memory or in a core register. This instruction uses A
      and D as implicit operands in the same way as the MUL instruction.

  2.  A two-operand form. One of the source operands may be in any core
      register while the other may be either in memory or in a core
      register. The product replaces the core-register operand.

  3.  A three-operand form; two are source and one is the destination
      operand. One of the source operands is an immediate value stored in
      the instruction; the second may be in memory or in any core
      register. The product may be stored in any core register. The
      immediate operand is treated as signed. If the immediate operand is a
      byte, the processor automatically sign-extends it to the size of the
      second operand before performing the multiplication.

Three-operand instructions are very atypical of the x86, and my own
assembler and I believe GNU gas do not provide them. You can always
hand-assemble the bytes. The osimplay "scale" word uses MUL,
hand-assembled internally.

The three forms are similar in most respects:

  !  The length of the product is calculated to twice the length of the
     operands.

  !  The CF and OF flags are set when significant bits are carried into the
     high-order half of the result. CF and OF are cleared when the
     high-order half of the result is the sign-extension of the low-order
     half.

However, forms 2 and 3 differ in that the product is truncated to the
length of the operands before it is stored in the destination register.
Because of this truncation, OF should be tested to ensure that no
significant bits are lost. (For ways to test OF, refer to the INTO and PUSHF
instructions.)

Forms 2 and 3 of IMUL may also be used with unsigned operands because,
whether the operands are signed or unsigned, the low-order half of the
product is the same.


3.2.4  Division Instructions

The 80386 has separate division instructions for unsigned and signed
operands. DIV operates on unsigned numbers, while IDIV operates on signed
integers as well as unsigned. In either case, an exception (interrupt zero)
occurs if the divisor is zero or if the quotient is too large for AL, AX, or
A.

DIV (Unsigned Integer Divide) performs an unsigned division of the
accumulator by the source operand. The dividend (the accumulator) is twice
the size of the divisor (the source operand); the quotient and remainder
have the same size as the divisor, as the following table shows.

Size of Source Operand
      (divisor)             Dividend       Quotient      Remainder

Byte                        AX             AL            AH
dual                        DX:AX          AX            DX
quad                         D:A           A             D

Non-integral quotients are truncated to integers toward 0. The remainder is
always less than the divisor. For unsigned byte division, the largest
quotient is 255. For unsigned dual division, the largest quotient is 65,535.
For unsigned quad division the largest quotient is 2^(32) -1.

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 dual division, the maximum
positive quotient is +32,767, and the minimum negative quotient is
-32,768. For signed quad division the maximum positive quotient is 2^(31)
-1, the minimum negative quotient is -2^(31). Non-integral results are
truncated towards 0. The remainder always has the same sign as the
dividend and is less than the divisor in magnitude. I believe some other
machines truncate towards negative infinity.


3.4  Logical Instructions

The group of logical instructions includes:

  !  The Boolean operation instructions
  !  Bit test and modify instructions
  !  Bit scan instructions
  !  Rotate and shift instructions
  !  Byte set on condition


3.4.1  Boolean Operation Instructions

The logical operations are AND, OR, XOR, and NOT.

NOT (Not) inverts the bits in the specified operand to form a one's
complement of the operand. The NOT instruction is a unary operation that
uses a single operand in a register or memory. NOT has no effect on the
flags.

The AND, OR, and XOR instructions perform the standard logical operations
"and", "(inclusive) or", and "exclusive or". These instructions can use the
following combinations of operands:

  !  Two register operands

  !  A core register operand with a memory operand

  !  An immediate operand with either a core register operand or a
     memory operand.

AND, OR, and XOR clear OF and CF, leave AF undefined, and update SF, ZF,
and PF.


3.4.2  Bit Test and Modify Instructions

This group of instructions operates on a single bit which can be in memory
or in a core register. The location of the bit is specified as an offset
from the low-order end of the operand. The value of the offset either may
be given by an immediate byte in the instruction or may be contained in a
core register.

These instructions first assign the value of the selected bit to CF, the
carry flag. Then a new value is assigned to the selected bit, as
determined by the operation. OF, SF, ZF, AF, PF are left in an undefined
state. Table 3-1 defines these instructions. These instructions are
sometimes used with LOCK for system semaphores and so on.


Table 3-1. Bit Test and Modify Instructions

Instruction                      Effect on CF            Effect on
							 Selected Bit

Bit (Bit Test)                   CF <! BIT                (none)
BTS (Bit Test and Set)           CF <! BIT                BIT <! 1
BTR (Bit Test and Reset)         CF <! BIT                BIT <! 0
BTC (Bit Test and Complement)    CF <! BIT                BIT <! NOT(BIT)


3.4.3  Bit Scan Instructions

These instructions scan a cell for a one-bit and store the index of the
first set bit into a register.  The bit string being scanned may be either
in a register or in memory. The ZF flag is set if the entire cell is zero
(no set bits are found); ZF is cleared if a one-bit is found. If no set
bit is found, the value of the destination register is undefined.

BSF (Bit Scan Forward) scans from low-order to high-order (starting from
bit index zero).

BSR (Bit Scan Reverse) scans from high-order to low-order (starting from
bit index 15 of a dual or index 31 of a quad).


3.4.4  Shift and Rotate Instructions

The shift and rotate instructions reposition the bits within the specified
operand.

These instructions fall into the following classes:

  !  Shift instructions
  !  Double shift instructions
  !  Rotate instructions


3.4.4.1  Shift Instructions

The bits in bytes and cells may be shifted arithmetically or logically.
Depending on the value of a specified count, bits can be shifted up to 31
places. A 31-bit shift of any quad value results in zero. INTeL considers
higher-significance bits to be to the left of bit 0, which is typical, so
"left shift" is up-significance. 1 left-shifted by 2 is 8.

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 C. This last form allows the
shift count to be a variable that the program supplies during execution.
Only the low order 5 bits of C are used, giving a range sufficient to
shift all on-bits out of a quad, 0<->31.

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.

The shift instructions provide a convenient way to accomplish division or
multiplication by binary powers. Note however that division of signed
numbers by shifting right is not the same kind of division performed by
the IDIV instruction. Also note that arithmetic division is relatively
slow, and can not use the early-out algortithm arithmetic multiplication
uses.

SAL (Shift Arithmetic Left) shifts the destination byte or cell operand
left by one, or by the number of bits specified in the count operand (an
immediate value or the value contained in C). The processor shifts zeros
in from the right (low-order) side of the operand as bits "exit" from the
left (high-order) side. See Figure 3-6.

SHL (Shift Logical Left) is a synonym for SAL (refer to SAL).

SHR (Shift Logical Right) shifts the destination byte or cell operand
right by one or by the number of bits specified in the count operand (an
immediate value or the value contained in C). The processor shifts zeros
in from the left side of the operand as bits exit from the right side. See
Figure 3-7.

SAR (Shift Arithmetic Right) shifts the destination byte or cell 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
(high-order) side if the value is positive or by shifting by ones if the
value is negative. See Figure 3-8.

Even though this instruction can be used to divide integers by a power of
two, the type of division is not the same as that produced by the IDIV
instruction. The quotient of IDIV is rounded toward zero, whereas the
"quotient" of SAR is rounded toward negative infinity. This difference is
apparent only for negative numbers. For example, when IDIV is used to divide
-9 by 4, the result is -2 with a remainder of -1. If SAR is used to shift
-9 right by two bits, the result is -3. The "remainder" of this kind of
division is +3; however, the SAR instruction stores only the high-order bit
of the remainder (in CF). 

The code sequence in Figure 3-9 produces the same result as IDIV for any M
= 2^(N), where 0 < N < 32. This sequence takes about 12 to 18 clocks,
depending on whether the jump is taken; if C contains M, the corresponding
IDIV C instruction will take about 43 clocks.


Figure 3-6.  SAL and SHL

		     OF   CF                OPERAND

       BEFORE SHL    X    X     10001000100010001000100010001111
       OR SAL

       AFTER SHL     1    1 <<- 00010001000100010001000100011110 <<- 0
       OR SAL BY 1

       AFTER SHL     X    0 <<- 00100010001000100011110000000000 <<- 0
       OR SAL BY 10

SHL (WHICH HAS THE SYNONYM SAL) SHIFTS 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. SHL SHIFTS IN ZEROS
TO FILL THE VACATED BIT LOCATIONS. THESE INSTRUCTIONS OPERATE ON BYTE OR
CELL OPERANDS.


Figure 3-7.  SHR

				      OPERAND                  CF

       BEFORE SHR         10001000100010001000100010001111     X

       AFTER SHR    0..->>01000100010001000100010001000111..->>1
       BY 1

       AFTER SHR    0..->>00000000001000100010001000100010..->>O
       BY 10

SHR SHIFTS THE BITS OF 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.


Figure 3-8.  SAR

				  POSITIVE OPERAND             CF

       BEFORE SAR         01000100010001000100010001000111     X

       AFTER SAR    0..->>00100010001000100010001000100011..->>1
       BY 1

				  NEGATIVE OPERAND             CF

       BEFORE SAR         11000100010001000100010001000111     X

       AFTER SAR    0..->>11100010001000100010001000100011..->>1
       BY 1

SAR PRESERVES THE SIGN OF THE REGISTER OR MEMORY OPERAND AS IT SHIFTS THE
OPERAND TO THE RIGHT BY THE SPECIFIED NUMBER OF BIT POSITIONS. CF RECIEVES
THE LAST BIT SHIFTED OUT OF THE RIGHT OF THE OPERAND.


Figure 3-9.  Using SAR to Simulate IDIV

    ; assuming N is in C, and the dividend is in  A
    ;                                               CLOCKS
    CMP      A, 0      ; to set sign flag          2
    JGE     NoAdjust    ; jump if sign is zero      3 or 9
    ADD      A, C    ;                           2
    DEC      A         ;  A :=  A + (N-1)        2
NoAdjust:
    SAR      A, CL     ;                           3
    ;                       TOTAL CLOCKS           12 or 18]


3.4.4.2  Double-Shift Instructions

These instructions provide the basic operations needed to implement
operations on long unaligned bit strings. The double shifts operate either
on dual or quad operands, as follows:

  1.  Taking two dual operands as input and producing a dual output.

  2.  Taking two quad operands as input and producing a quad output.

Of the two input operands, one may either be in a core register or in
memory, while the other may only be in a core register. The results
replace the memory or register operand. The number of bits to be shifted
is specified either in the CL register or in an immediate byte of the
instruction.

Bits are shifted from the register operand into the memory or register
operand. CF is set to the value of the last bit shifted out of the
destination operand. SF, ZF, and PF are set according to the value of the
result. OF and AF are left undefined.

SHLD (Shift Left Double) shifts bits of the R/M field to the left, while
shifting high-order bits from the Reg field into the R/M field on the right
(see Figure 3-10). The result is stored back into the R/M operand. The Reg
field is not modified.

SHRD (Shift Right Double) shifts bits of the R/M field to the right, while
shifting low-order bits from the Reg field into the R/M field on the left
(see Figure 3-11). The result is stored back into the R/M operand. The Reg
field is not modified.


3.4.4.3  Rotate Instructions

Rotate instructions allow bits in bytes or cells 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 cell 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 exits from the left of the operand returns at the
right to become the new low-order bit of the operand. See Figure 3-12.

ROR (Rotate Right) rotates the byte or cell 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-13.

RCL (Rotate Through Carry Left) rotates bits in the byte or cell
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
one-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-14.

RCR (Rotate Through Carry Right) rotates bits in the byte or cell
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
one-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-15.


Figure 3-10.  Shift Left Double

		  31                   DESTINATION                 0
    r----L       r--------------------------------------------------L
    | CF |<<-....|                 MEMORY OF REGISTER               |<<-.\
    `----'       `--------------------------------------------------'    l
	     /...........................................................|
	     l    31                     SOURCE                    0
	     l   r--------------------------------------------------L
	     L...|                      REGISTER                    |
		 `--------------------------------------------------'


Figure 3-11.  Shift Right Double

	31                     SOURCE                    0
       r--------------------------------------------------t
       |                      REGISTER                    L...\
       `--------------------------------------------------'   l
   /..........................................................|
   l    31                   DESTINATION                 0
   l   r--------------------------------------------------t        r----L
   L->>|                 MEMORY OF REGISTER               L.....->>| CF |
       `--------------------------------------------------'        `----'


Figure 3-12.  ROL

		  31                   DESTINATION                 0
    r----L       r--------------------------------------------------t
    | CF |<<-.L..|                 MEMORY OF REGISTER               |<<-\
    `----'    l  `--------------------------------------------------'   l
	      L.........................................................|


Figure 3-13.  ROR

     /..........................................................\
     l    31                   DESTINATION                 0    l
     l   r--------------------------------------------------t   l    r----t
     L->>|                 MEMORY OF REGISTER               L...L.->>| CF |
	 `--------------------------------------------------'        `----'


Figure 3-14.  RCL

		  31                   DESTINATION                 0
    r----t       r--------------------------------------------------t
  ).| CF |<<-....|                 MEMORY OF REGISTER               |<<-\
  l `----'       `--------------------------------------------------'   l
  L.....................................................................|


Figure 3-15.  RCR

   /......................................................................\
   l    31                   DESTINATION                 0                l
   l   r--------------------------------------------------t        r----t l
   L->>|                 MEMORY OF REGISTER               L.....->>| CF L.|
       `--------------------------------------------------'        `----'


3.4.4.4  Fast "BIT BLT" Using Double Shift Instructions

One purpose of the double shifts is to implement a bit string move, with
arbitrary misalignment of the bit strings.  This is called a "bit blt"
(BIT BLock Transfer.)  This is particularly useful for bit-plane pixel
graphics. A simple example is to move a bit string from an arbitrary
offset into a quad-aligned byte string.  A left-to-right string is
moved 32 bits at a time if a double shift is used inside the move loop.

This is osimplay syntax with INTeL opcode mnemonics, but the algorithm is
as per the INTeL original.

     MOV   ScrAddr to SI
     MOV   DestAddr to DI
     MOV   WordCnt to BX
     MOV   RelOffset to CL      	# relative offset Dest-Src
     MOV   @ SI to DX      	        # load first word of source
     ADD   4 to SI  	           	# bump source address
L BltLoop
     LODS                    	# new low order part
     SHLD  D, A,CL        	# D overwritten with aligned stuff
     XCHG  D with A           	# Swap high/low order parts
     STOS                    	# Write out next aligned chunk
     DEC   B
     JA    BltLoop

This loop is simple yet allows the data to be moved in 32-bit pieces for
the highest possible performance. Without a double shift, the best that can
be achieved is 16 bits per loop iteration by using a 32-bit shift and
replacing the XCHG with a ROR by 16 to swap high and low order parts of
registers. A more general loop than shown above would require some extra
masking on the first quad moved (before the main loop), and on the
last quad moved (after the main loop), but would have the same basic
32-bits per loop iteration as the code above.


3.4.4.5  Fast Bit-String Insert and Extract

The double shift instructions also enable:

  !  Fast insertion of a bit string from a register into an arbitrary bit
     location in a larger bit string in memory without disturbing the bits
     on either side of the inserted bits.

  !  Fast extraction of a bits string into a register from an arbitrary bit
     location in a larger bit string in memory without disturbing the bits
     on either side of the extracted bits.



3.4.5  Byte-Set-On-Condition Instructions

This group of instructions sets a byte to zero or one depending on any of
the 16 conditions defined by the status flags. The byte may be in memory
or may be a one-byte core register. These instructions are especially
useful for implementing Boolean expressions in high-level languages such
as Pascal.

SETcc (Set Byte on Condition cc) set a byte to one if condition cc is true;
sets the byte to zero otherwise. Refer to Appendix D for a definition of
the possible conditions.


3.4.6  Test Instruction

TEST (Test) performs the logical "and" of the two operands, clears OF and
CF, leaves AF undefined, and updates SF, ZF, and PF. The flags can be tested
by conditional control transfer instructions or by the byte-set-on-condition
instructions. The operands may be cells or bytes.

The difference between TEST and AND is that TEST does not alter the
destination operand. TEST differs from BT in that TEST is useful for testing
the value of multiple bits in one operation, whereas BT tests a single bit.


3.5  Control Transfer Instructions

The 80386 provides both conditional and unconditional control transfer
instructions to direct the flow of execution. Conditional control transfers
depend on the results of operations that affect the flag register.
Unconditional control transfers are always executed.


3.5.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 (near control transfers) or in different code segments (far control
transfers). The variants of these instructions that transfer control to
other segments are discussed in a later section of this chapter. If the
model of memory organization used in a particular 80386 application does
not make segments visible to applications programmers, intersegment control
transfers will not be used.

Unconditional control transfers have various degrees of state-change that
usually don't impinge on applications, but bear mention. A near transfer
changes IP but has no segment effects. A far transfer loads a new CS, i.e.
changes code segments, if the system's protection scheme, if any, allows
the change. Interrupts and synchronous traps such as INT are far transfers
with a push of the flags onto the stack. Thus the stack frame for a near
CALL is just the address of the next instruction, while an INT pushes
FLAGS, CS and IP. These various types of call typically call something
that knows the type of return required, so the stack stays in order.  RET
can also push a dual value to drop the stack by, for dropping a stack
frame of up to 64k bytes, which could have been allocated by the routine
being returned from. In general, applications get by on near transfers.
Systems may have to deal with much more than the three types mentioned
here.

3.5.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 whether the address is specified directly within the
instruction or indirectly through a register or memory.

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.

Direct near JMP. A direct JMP uses a relative displacement value contained
in the instruction. The displacement is signed and the size of the
displacement may be a byte or cell. The processor forms an effective
address by adding this relative displacement to the address contained in
EIP. When the additions have been performed, EIP refers to the next
instruction to be executed.

Indirect near JMP. Indirect JMP instructions specify an absolute address in
one of several ways:

  1.  The program can JMP to a location specified by a core register
      other than SP. The processor moves this 32-bit value into IP and 
	resumes execution.

  2.  The processor can obtain the destination address from a memory
      operand specified in the instruction.

  3.  A register can modify the address of the memory pointer to select a
      destination address.


3.5.1.2  Call Instruction

CALL (Call Procedure) activates an out-of-line procedure, a subroutine,
saving on the stack the address of the instruction following the CALL for
later use by a RET (Return) instruction. CALL places the current value of
EIP on the stack. The RET instruction in the called procedure uses this
address to transfer control back to the calling program.

CALL instructions, like JMP instructions have relative, direct, and
indirect versions.

Indirect CALL instructions specify an absolute address in one of these
ways:

  1.  The program can CALL a location specified by a core register other 
      than SP. The processor moves this 32-bit value into IP.

  2.  The processor can obtain the destination address from a memory
      operand specified in the instruction.


3.5.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. RET restores the value of EIP that was
saved on the stack by the previous CALL instruction.

RET instructions may optionally specify an immediate operand. By adding
this constant to the new top-of-stack pointer, RET effectively removes any
arguments that the calling program pushed on the stack before the execution
of the CALL instruction.

IRET (Return From Interrupt) returns control to an interrupted procedure.
IRET differs from RET in that it also pops the flags from the stack into the
flags register. The flags are stored on the stack by the interrupt
mechanism.


3.5.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.


3.5.2.1  Conditional Jump Instructions

Table 3-2 shows the conditional transfer mnemonics and their
interpretations. 

Conditional jump instructions contain a displacement which is added to the
EIP register if the condition is true. The displacement may be a byte or
cell. The displacement is signed; therefore, it can be used to jump
forward or backward.


Table 3-2. Interpretation of Conditional Transfers

Unsigned Conditional Transfers

Mnemonic(s)       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) = 1           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.5.2.2  Loop Instructions

The loop instructions are conditional jumps that use a value placed in C
to specify the number of repetitions of a software loop. All loop
instructions automatically decrement C and terminate the loop when C=0.
Four of the five loop instructions specify a condition involving ZF that
terminates the loop before C reaches zero.

LOOP (Loop While C Not Zero) is a conditional transfer that automatically
decrements the C register before testing C for the branch condition. If
C 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 C to a value of
zero. If LOOP finds C=0, control transfers to the instruction immediately
following the LOOP instruction. If the value of C is initially zero, then
the LOOP executes 2^(32) times.

LOOPE (Loop While Equal) and LOOPZ (Loop While Zero) are synonyms for the
same instruction. These instructions automatically decrement the C
register before testing C and ZF for the branch conditions. If C is
non-zero and ZF=1, the program branches to the target label specified in the
instruction. If LOOPE or LOOPZ finds that C=0 or ZF=0, control transfers
to the instruction immediately following the LOOPE or LOOPZ instruction.

LOOPNE (Loop While Not Equal) and LOOPNZ (Loop While Not Zero) are synonyms
for the same instruction. These instructions automatically decrement the C
register before testing C and ZF for the branch conditions. If C is
non-zero and ZF=0, the program branches to the target label specified in the
instruction. If LOOPNE or LOOPNZ finds that C=0 or ZF=1, control transfers
to the instruction immediately following the LOOPNE or LOOPNZ instruction.


3.5.2.3  Executing a Loop or Repeat Zero Times

JCXZ (Jump if C Zero) branches to the label specified in the instruction
if it finds a value of zero in C. JCXZ is useful in combination with the
LOOP instruction and with the string scan and compare instructions, all of
which decrement C. Sometimes, it is desirable to design a loop that
executes zero times if the count variable in C is initialized to zero.
Because the LOOP instructions (and repeat prefixes) decrement C before
they test it, a loop will execute 2^(32) times if the program enters the
loop with a zero value in C. A programmer may conveniently overcome this
problem with JCXZ, which enables the program to branch around the code
within the loop if C is zero when JCXZ executes. When used with repeated
string scan and compare instructions, JCXZ can determine whether the
repetitions terminated due to zero in C or due to satisfaction of the
scan or compare conditions.


3.5.3  Software-Generated Interrupts

The INT n, INTO, and BOUND instructions allow the programmer to specify a
transfer to an interrupt service routine from within a program.

INT n (Software Interrupt) activates the interrupt service routine that
corresponds to the number coded within the instruction. The INT instruction
may specify any interrupt type. Programmers may use this flexibility to
implement multiple types of internal interrupts or to test the operation of
interrupt service routines. (Interrupts 0-31 are reserved by Intel.) The
interrupt service routine terminates with an IRET instruction that returns
control to the instruction that follows INT.

INTO (Interrupt on Overflow) invokes interrupt 4 if OF is set. Interrupt 4
is reserved for this purpose. OF is set by several arithmetic, logical, and
string instructions.

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 the upper limit and lower limit are in adjacent memory
locations. 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 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 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.

The upper and lower limit values may each be a dual or a quad.


3.6  String and Character Translation Instructions

The instructions in this category operate on strings rather than on logical
or numeric values. Refer also to the section on I/O for information about
the string I/O instructions (also known as block I/O).

The power of 80386 string operations derives from the following features of
the architecture:

1.  A set of primitive string operations

   MOVS   .. Move String
   CMPS   .. Compare string
   SCAS   .. Scan string
   LODS   .. Load string
   STOS   .. Store string

2.  Indirect, indexed addressing, with automatic incrementing or
    decrementing of the indexes.

   Indexes:

      SI    .. Source index register
      DI    .. Destination index register

   Control flag:

      DF     .. Direction flag

   Control flag instructions:

      CLD    .. Clear direction flag instruction
      STD    .. Set direction flag instruction

3.  Repeat prefixes

   REP          .. Repeat while C not xero
   REPE/REPZ    .. Repeat while equal or zero
   REPNE/REPNZ  .. Repeat while not equal or not zero

The primitive string operations operate on one element of a string. A
string element may be a byte or a cell. The string elements are addressed
by the registers SI and DI. After every primitive operation SI and/or DI
are automatically updated to point to the next element of the string. If
the direction flag is zero, the index registers are incremented; if one,
they are decremented. The amount of the increment or decrement is 1, 2, or
4 depending on the size of the string element.


3.6.1  Repeat Prefixes

The repeat prefixes REP (Repeat While C Not Zero), REPE/REPZ (Repeat
While Equal/Zero), and REPNE/REPNZ (Repeat While Not Equal/Not Zero) specify
repeated operation of a string primitive. This form of iteration allows the
CPU to process strings much faster than would be possible with a regular
software loop.

When a primitive string operation has a repeat prefix, the operation is
executed repeatedly, each time using a different element of the string. The
repetition terminates when one of the conditions specified by the prefix is
satisfied.

At each repetition of the primitive instruction, the string operation may
be suspended temporarily in order to handle an exception or external
interrupt. After the interruption, the string operation can be restarted
again where it left off. This method of handling strings allows operations
on strings of arbitrary length, without affecting interrupt response.

All three prefixes causes the hardware to automatically repeat the
associated string primitive until C=0. The differences among the repeat
prefixes have to do with the second termination condition. REPE/REPZ and
REPNE/REPNZ are used exclusively with the SCAS (Scan String) and CMPS
(Compare String) primitives. When these prefixes are used, repetition of the
next instruction depends on the zero flag (ZF) as well as the C register.
ZF does not require initialization before execution of a repeated string
instruction, because both SCAS and CMPS set ZF according to the results of
the comparisons they make. The differences are summarized in the
accompanying table.

Prefix                      Termination         Termination
			    Condition 1         Condition 2

REP                           C = 0             (none)
REPE/REPZ                     C = 0             ZF = 0
REPNE/REPNZ                   C = 0             ZF = 1


3.6.2  Indexing and Direction Flag Control

The addresses of the operands of string primitives are determined by the
SI and DI registers. SI points to source operands. By default, SI refers
to a location in the segment indicated by the DS segment register. A
segment-override prefix may be used, however, to cause SI to refer to CS,
SS, ES, FS, or GS. DI points to destination operands in the segment
indicated by ES; no segment override is possible. The use of two different
segment registers in one instruction allows movement of strings between
different segments.

This use of SI and DI has led to the descriptive names source index and
destination index for the SI and DI registers, respectively. In all cases
other than string instructions, however, the SI and DI registers may be
used as general-purpose registers.

When SI and DI are used in string primitives, they are automatically
incremented or decremented after to operation. The direction flag determines
whether they are incremented or decremented. The instruction CLD puts zero
in DF, causing the index registers to be incremented; the instruction STD
puts one in DF, causing the index registers to be decremented. Programmers
should always put a known value in DF before using string instructions in a
procedure.


3.6.3  String Instructions

MOVS (Move String) moves the string element pointed to by SI to the
location pointed to by DI. MOVSB operates on byte elements, MOVSW operates
on dual elements, and MOVSD operates on quads. The destination segment
register cannot be overridden by a segment override prefix, but the source
segment register can be overridden.

The MOVS instruction, when accompanied by the REP prefix, operates as a
memory-to-memory block transfer. To set up for this operation, the program
must initialize C and the register pairs SI and DI. C specifies the
number of bytes or cells in the block.

If DF=0, the program must point SI to the first element of the source
string and point DI to the destination address for the first element. If
DF=1, the program must point these two registers to the last element of the
source string and to the destination address for the last element,
respectively.

CMPS (Compare Strings) subtracts the destination string element (at ES:DI)
from the source string element (at 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. CMPSB compares bytes, and CMPSD compares cells. The segment
register used for the source address can be changed with a segment
override prefix while the destination segment register cannot be
overridden.

SCAS (Scan String) subtracts the destination string element at ES:DI from
 A, 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. SCASB scans bytes; SCASW scans
cells. The destination segment register (ES) cannot be overridden.

When either the REPE or REPNE prefix modifies either the SCAS or CMPS
primitives, the processor compares the value of the current string element
with the value in A for quad elements, in AX for dual elements, or
in AL for byte elements. Termination of the repeated operation depends on
the resulting state of ZF as well as on the value in C.

LODS (Load String) places the source string element at SI into A for quad
strings, into AX for dual strings, or into AL for byte strings. LODS
increments or decrements SI according to DF.

STOS (Store String) places the source string element from  A, AX, or AL
into the string at ES:DSI. STOS increments or decrements DI according to
DF.


3.7  Instructions for Block-Structured Languages

I haven't edited this section much because I've never figured out any use
for these curiosities. osimplay uses "enter" and "leave" for much simpler
constructs based on the frame-dropping return instruction with immediate
frame-size operand. These guys do a lot, and manage the stack coherently
for what they do, but they aren't particularly fast at it.

The instructions in this section provide machine-language support for
functions normally found in high-level languages. These instructions include
ENTER and LEAVE, which simplify the programming of procedures.

ENTER (Enter Procedure) creates a stack frame that may be used to implement
the scope rules of 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.

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
dual 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.

   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.

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
starting point 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.

The ENTER instruction can be used in two ways: 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 3-16 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
3-17). Figures 3-18 through 3-21 demonstrate the actions of the ENTER
instruction if the modules shown in Figure 3-17 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.
Referring to Figure 3-17 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 access to
variables for Figure 3-17.

  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 dual in the display
points to itself because there is no previous value for LEAVE to return to
 BP. See Figure 3-18.

After MAIN calls PROCEDURE A, ENTER creates a new display for PROCEDURE A
with the first dual pointing to the previous value of  BP (BPM for LEAVE to
return to the MAIN stack frame) and the second dual 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 are at a fixed offset from this value. See
Figure 3-19.

After PROCEDURE A calls PROCEDURE B, ENTER creates a new display for
PROCEDURE B with the first dual 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 dual 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 3-20.

After PROCEDURE B calls PROCEDURE C, ENTER creates a new display for
PROCEDURE C with the first dual pointing to the previous value of  BP, the
second word pointing to the value of  BP for MAIN, and the third dual
pointing to the  BP value for A and the third dual 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 3-21.

LEAVE (Leave Procedure) reverses the action of the previous ENTER
instruction. The LEAVE instruction does not include any operands. LEAVE
copies  BP to SP to release all stack space allocated to the procedure by
the most recent ENTER instruction. Then 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.


Figure 3-16.  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 - 4
	  Push the quad pointed to by  BP
      End repeat
      Push FRAME_PTR
End if
 BP <! FRAME_PTR
SP <! SP - first operand.


Figure 3-17.  Variable Access in Nested Procedures

      r----------------------------------------------------------------t
      |                MAIN PROCEDURE (LEXICAL LEVEL 1)                |
      |   r--------------------------------------------------------t   |
      |   |                                                        |   |
      |   |              PROCEDURE A (LEXICAL LEVEL 2)             |   |
      |   |                                                        |   |
      |   |  r--------------------------------------------------t  |   |
      |   |  |           PROCEDURE B (LEXICAL LEVEL 3)          |  |   |
      |   |  `--------------------------------------------------'  |   |
      |   |                                                        |   |
      |   |                                                        |   |
      |   |  r--------------------------------------------------t  |   |
      |   |  |           PROCEDURE C (LEXICAL LEVEL 3)          |  |   |
      |   |  |  r--------------------------------------------t  |  |   |
      |   |  |  |        PROCEDURE D (LEXICAL LEVEL 4)       |  |  |   |
      |   |  |  `--------------------------------------------'  |  |   |
      |   |  |                                                  |  |   |
      |   |  `--------------------------------------------------'  |   |
      |   |                                                        |   |
      |   `--------------------------------------------------------'   |
      |                                                                |
      `----------------------------------------------------------------'


Figure 3-18.  Stack Frame for MAIN at Level 1

				     A 31          0 A
		D  O                 |               |
		I  F              ). |-------|-------|
		R                 l  |    OLD SP    |
		E  E     DISPLAY .|  |-------|-------|<<- BP FOR
		C  X              l  |       BPM     |    MAIN
		T  P              !- |-------|-------|
		I  A              l  |               |
		O  N              l  |-------|-------|
		N  S     DYNAMIC .|  |               |
		   I     STORAGE  l  |-------|-------|
		 l O              l  |               |
		 l N              L. |-------|-------|<<-SP
		 l                   |               |
		 Z                   V               V


 BPM =  BP VALUE FOR MAIN    


Figure 3-19.  Stack Frame for Procedure A

				     A 31          0 A
		D  O                 |               |
		I  F                 |-------|-------|
		R                    |    OLD SP    |
		E  E                 |-------|-------|
		C  X                 |       BPM	 BPM =  BP VALUE FOR MAIN    |
		T  P                 |-------|-------|
		I  A                 |               |
		O  N                 |-------|-------|
		N  S                 |               |
		   I                 |-------|-------|
		 l O                 |               |
		 l N              ). |-------|-------|
		 l                l  |       BPM     |
		 Z                l  |-------|-------|<<- BP FOR A
			 DISPLAY .|  |       BPM     |
				  l  |-------|-------|
				  l  |       BPA
 BPA =  BP VALUE FOR PROCEDURE A    |
				  !- |-------|-------|
				  l  |               |
				  l  |-------|-------|
			 DYNAMIC .|  |               |
			 STORAGE  l  |-------|-------|
				  l  |               |
				  L. |-------|-------|<<-SP
				     |               |
				     V               Q


Figure 3-20.  Stack Frame for Procedure B at Level 3 Called from A

				     Q 31          0 Q
		D  O                 |               |
		I  F                 |-------|-------|
		R                    |    OLD SP    |
		E  E                 |-------|-------|
		C  X                 |       BPM
 BPM =  BP VALUE FOR MAIN    |
		T  P                 |-------|-------|
		I  A                 |               |
		O  N                 |-------|-------|
		N  S                 |               |
		   I                 |-------|-------|
		 l O                 |               |
		 l N                 |-------|-------|
		 l                   |       BPM     |
		 Z                   |-------|-------|
				     |       BPM     |
				     |-------|-------|
				     |       BPA     |
				     |-------|-------|
				     |               |
				     |-------|-------|
				     |               |
				     |-------|-------|
				     |               |
				  ). |-------|-------|
				  l  |       BPA     |
				  l  |-------|-------|<<- BP
				  l  |       BPM     |
			 DISPLAY .|  |-------|-------|
				  l  |       BPA     |
				  l  |-------|-------|
				  l  |       BPB
 BPB =  BP VALUE FOR PROCEDURE B    |
				  !- |-------|-------|
				  l  |               |
				  l  |-------|-------|
			 DYNAMIC .|  |               |
			 STORAGE  l  |-------|-------|
				  l  |               |
				  L. |-------|-------|<<-SP
				     |               |
				     V               Q


Figure 3-21.  Stack Frame for Procedure C at Level 3 Called from B

				     Q 31          0 Q
		D  O                 |               |
		I  F                 |-------|-------|
		R                    |    OLD SP    |
		E  E                 |-------|-------|
		C  X                 |       BPM
 BPM =  BP VALUE FOR MAIN    |
		T  P                 |-------|-------|
		I  A                 |               |
		O  N                 |-------|-------|
		N  S                 |               |
		   I                 |-------|-------|
		 l O                 |               |
		 l N                 |-------|-------|
		 l                   |       BPM     |
		 Z                   |-------|-------|
				     |       BPM     |
				     |-------|-------|
				     |       BPA
 BPA =  BP VALUE FOR PROCEDURE A    |
				     |-------|-------|
				     |               |
				     |-------|-------|
				     |               |
				     |-------|-------|
				     |               |
				  ). |-------|-------|
				  l  |       BPA     |
				  l  |-------|-------|<<- BP
				  l  |       BPM     |
			 DISPLAY .|  |-------|-------|
				  l  |       BPA     |
				  l  |-------|-------|
				  l  |       BPB
 BPB =  BP VALUE FOR PROCEDURE B    |
				  !- |-------|-------|
				  l  |               |
				  l  |-------|-------|
			 DYNAMIC .|  |               |
			 STORAGE  l  |-------|-------|
				  l  |               |
				  L. |-------|-------|<<-SP
				     |               |
				     V               Q


3.8  Flag Control Instructions

The flag control instructions provide a method for directly changing the
state of bits in the flag register.


3.8.1  Carry and Direction 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.

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 index registers, SI and DI, after each
execution of a string primitive. If DF=1, the processor decrements these
index registers. Programmers should use one of these instructions before any
procedure that uses string instructions to insure that DF is set properly.

Flag Control Instruction                  Effect

STC (Set Carry Flag)                      CF <! 1
CLC (Clear Carry Flag)                    CF <! 0
CMC (Complement Carry Flag)               CF <! NOT (CF)
CLD (Clear Direction Flag)                DF <! 0
STD (Set Direction Flag)                  DF <! 1


3.8.2  Flag Transfer Instructions

Though specific instructions exist to alter CF and DF, there is no direct
method of altering the other applications-oriented 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 instructions LAHF and SAHF deal with five of the status flags, which
are used primarily by the arithmetic and logical instructions.

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-22). The contents of the remaining bits
(5, 3, and 1) are undefined. The flags remain unaffected.

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-22).

The PUSHF and POPF instructions are not only useful for storing the flags
in memory where they can be examined and modified but are also useful for
preserving the state of the flags register while executing a procedure.

PUSHF (Push Flags) decrements SP by two and then transfers the low-order
dual of the flags register to the word at the top of stack pointed to by SP
(see Figure 3-23). The variant PUSHFD decrements SP by four, then
transfers both duals of the extended flags register to the top of the stack
pointed to by SP (the VM and RF flags are not moved, however).

POPF (Pop Flags) transfers specific bits from the dual at the top of stack
into the low-order byte of the flag register (see Figure 3-23), then
increments SP by two. The variant POPFD transfers specific bits from the
quad at the top of the stack into the extended flags register (the RF
and VM flags are not changed, however), then increments SP by four.


Figure 3-22.  LAHF and SAHF

		     7    6    5    4    3    2    1    0
		   r----t----t----t----t----t----t----t----t
		   | SF | ZF | UU | AF | UU | PF | UU | CF |
		   `----+----+----+----+----+----+----+----'

     LAHF LOADS FIVE FLAGS FROM THE FLAG REGISTER INTO REGISTER AH. SAHF
     STORES THESE SAME FIVE FLAGS 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 (MARKED UU) ARE RESERVED; DO NOT DEFINE.


3.9  Coprocessor Interface Instructions

A numerics coprocessor (e.g., the 80387 or 80287) provides an extension to
the instruction set of the base architecture. The coprocessor extends the
instruction set of the base architecture to support high-precision integer
and floating-point calculations. This extended instruction set includes
arithmetic, comparison, transcendental, and data transfer instructions. The
coprocessor also contains a set of useful constants to enhance the speed of
numeric calculations.

A program contains instructions for the coprocessor 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 coprocessor operates
concurrently with the CPU to provide maximum throughput for numeric
calculations.

The 80386 also has features to support emulation of the numerics
coprocessor when the coprocessor is absent. The software emulation of the
coprocessor is transparent to application software but requires more time
for execution. Refer to Chapter 11 for more information on coprocessor
emulation.

ESC (Escape) is a 5-bit sequence that begins the opcodes that identify
floating point numeric instructions. The ESC pattern tells the 80386 to send
the opcode and addresses of operands to the numerics coprocessor. The
numerics coprocessor uses the escape instructions to perform
high-performance, high-precision floating point arithmetic that conforms to
the IEEE floating point standard 754.

WAIT (Wait) is an 80386 instruction that suspends program execution until
the 80386 CPU detects that the BUSY pin is inactive. This condition
indicates that the coprocessor has completed its processing task and that
the CPU may obtain the results.


Figure 3-23.  Flag Format for PUSHF and POPF

				PUSHFD/POPFD
     /...............................L................................\

						  PUSHF/POPF
				     /................L...............\

      31              23             15                7             0
     r---------------|-----------,-,-,-,-,----,-,-,-,-,-,-,-,-,-,-,-,-t
     |                           lVlRl lNlID  lOlDlIlTlSlZl lAl lPl lC|
     |0 0 0 0 0 0 0 0 0 0 0 0 0 0l l l0l l    l l l l l l l0l l0l l1l |
     |                           lMlFl lTl  PLlFlFlFlFlFlFl lFl lFl lF|
     `---------------|-----------L-L-L-L-L----L-L-L-L-L-L-L-L-L-L-L-L-'

     BITS MARKED 0 AND 1 ARE RESERVED BY INTEL. DO NOT DEFINE.

   SYSTEMS FLAGS (INCLUDING THE IOPL FIELD, AND THE VM, RF, AND IF FLAGS)
   ARE PUSHED AND ARE VISIBLE TO APPLICATIONS PROGRAMS. HOWEVER, WHEN AN
   APPLICATIONS PROGRAM POPS THE FLAGS, THESE ITEMS ARE NOT CHANGED,
   REGARDLESS OF THE VALUES POPPED INTO THEM.


3.10  Segment Register Instructions

This category actually includes several distinct types of instructions.
These various types are grouped together here because, if systems designers
choose an unsegmented model of memory organization, none of these
instructions is used by applications programmers. The instructions that deal
with segment registers are:

1.  Segment-register transfer instructions.

   MOV SegReg, ...
   MOV ..., SegReg
   PUSH SegReg
   POP SegReg

2.  Control transfers to another executable segment.

   JMP far    ; direct and indirect
   CALL far
   RET far

3.  Data pointer instructions.

   LDS
   LES
   LFS
   LGS
   LSS

Note that the following interrupt-related instructions are different; all
are capable of transferring control to another segment, but the use of
segmentation is not apparent to the applications programmer.

INT n
INTO
BOUND
IRET


3.10.1  Segment-Register Transfer Instructions

The MOV, POP, and PUSH instructions also serve to load and store segment
registers. These variants operate similarly to their core-register
counterparts except that one operand can be a segment register. MOV cannot
move segment register to a segment register. Neither POP nor MOV can place
a value in the code-segment register CS; only the far control-transfer
instructions can change CS.


3.10.2  Far Control Transfer Instructions

The far control-transfer instructions transfer control to a location in
another segment by changing the content of the CS register.

Direct far JMP. Direct JMP instructions that specify a target location
outside the current code segment contain a far pointer. This pointer
consists of a selector for the new code segment and an offset within the new
segment.

Indirect far JMP. Indirect JMP instructions that specify a target location
outside the current code segment use a 48-bit variable to specify the far
pointer.

Far CALL. An intersegment CALL places both the value of EIP and CS on the
stack.

Far RET. An intersegment RET restores the values of both CS and EIP which
were saved on the stack by the previous intersegment CALL instruction.


3.10.3  Data Pointer Instructions

The data pointer instructions load a pointer (consisting of a segment
selector and an offset) to a segment register and a core register.

LDS (Load Pointer Using DS) transfers a 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 core register. DS
receives the segment-selector of the pointer. The destination register
receives the offset part of the pointer, which points to a specific location
within the segment.

Example: LDS SI, STRING_X

Loads DS with the selector identifying the segment pointed to by a
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 segment selector rather than DS.

Example: LES DESTINATION_X to DI

Loads ES with the selector 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.

LFS (Load Pointer Using FS) operates identically to LDS except that FS
receives the segment selector rather than DS.

LGS (Load Pointer Using GS) operates identically to LDS except that GS
receives the segment selector rather than DS.

LSS (Load Pointer Using SS) operates identically to LDS except that SS
receives the segment selector rather than DS.  This instruction is
especially important, because it allows the two registers that identify the
stack (SS:SP) to be changed in one uninterruptible operation.  Unlike the
other instructions which load SS, interrupts are not inhibited at the end
of the LSS instruction.  The other instructions (e.g., POP SS) inhibit
interrupts to permit the following instruction to load SP, thereby forming
an indivisible load of SS:SP.  Since both SS and SP can be loaded by LSS,
there is no need to inhibit interrupts.


3.11  Miscellaneous Instructions

The following instructions do not fit in any of the previous categories,
but are nonetheless useful.


3.11.1  Address Calculation Instruction

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 core register.
This instruction is especially useful for initializing registers before the
execution of the string primitives (SI, DI) or the XLAT instruction (B).
The LEA can perform any indexing or scaling that may be needed.

Example: LEA EBCDIC_TABLE to B

Causes the processor to place the address of the starting location of the
table labeled EBCDIC_TABLE into B.


3.11.2  No-Operation Instruction

NOP (No Operation) occupies a byte of storage but affects nothing but the
instruction pointer, EIP.


3.11.3  Translate Instruction

XLAT (Translate) replaced 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 B. XLAT changes the contents of
AL from table index to table entry. B 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.


			PART II  SYSTEMS PROGRAMMING                       



