## The Art of Assembly Language Programming

### Forward Why Would Anyone Learn This Stuff?

1 What's Wrong With Assembly Language
2 What's Right With Assembly Language?
3 Organization of This Text and Pedagogical Concerns
4 Obtaining Program Source Listings and Other Materials in This Text

## Section One: Machine Organization

Art of Assembly Language: Chapter One
Chapter One - Data Representation
1.0 - Chapter Overview
1.1 - Numbering Systems
1.1.1 - A Review of the Decimal System
1.1.2 - The Binary Numbering System
1.1.3 - Binary Formats
1.2 - Data Organization
1.2.1 - Bits
1.2.2 - Nibbles
1.2.3 - Bytes
1.2.4 - Words
1.2.5 - Double Words
1.3 - The Hexadecimal Numbering System
1.4 - Arithmetic Operations on Binary and Hexadecimal Numbers
1.5 - Logical Operations on Bits
1.6 - Logical Operations on Binary Numbers and Bit Strings
1.7 - Signed and Unsigned Numbers
1.8 - Sign and Zero Extension
1.9 - Shifts and Rotates
1.10 - Bit Fields and Packed Data
1.11 - The ASCII Character Set
1.12 Summary
1.13 Laboratory Exercises
1.13.1 Installing the Software
1.13.2 Data Conversion Exercises
1.13.3 Logical Operations Exercises
1.13.4 Sign and Zero Extension Exercises
1.13.5 Packed Data Exercises
1.14 Questions
1.15 Programming Projects

Chapter Two - Boolean Algebra
2.0 - Chapter Overview
2.1 - Boolean Algebra
2.2 - Boolean Functions and Truth Tables
2.3 - Algebraic Manipulation of Boolean Expressions
2.4 - Canonical Forms
2.5 - Simplification of Boolean Functions
2.6 - What Does This Have To Do With Computers, Anyway?
2.6.1 - Correspondence Between Electronic Circuits and Boolean Functions
2.6.2 - Combinatorial Circuits
2.6.3 - Sequential and Clocked Logic
2.7 - Okay, What Does It Have To Do With Programming, Then?
2.8 - Generic Boolean Functions
2.9 Laboratory Exercises
2.9.1 Truth Tables and Logic Equations Exercises
2.9.2 Canonical Logic Equations Exercises
2.9.3 Optimization Exercises
2.9.4 Logic Evaluation Exercises
2.10 Programming Projects
2.11 Summary
2.12 Questions

Chapter Three - System Organization
3.0 - Chapter Overview
3.1 - The Basic System Components
3.1.1 - The System Bus
3.1.1.1 - The Data Bus
3.1.1.2 - The Address Bus
3.1.1.3 - The Control Bus
3.1.2 - The Memory Subsystem
3.1.3 - The I/O Subsystem
3.2 - System Timing
3.2.1 - The System Clock
3.2.2 - Memory Access and the System Clock
3.2.3 - Wait States
3.2.4 - Cache Memory
3.3 - The 886, 8286, 8486, and 8686 "Hypothetical" Processors
3.3.1 - CPU Registers
3.3.2 - The Arithmetic & Logical Unit
3.3.3 - The Bus Interface Unit
3.3.4 - The Control Unit and Instruction Sets
3.3.5 - The x86 Instruction Set
3.3.6 - Addressing Modes on the x86
3.3.7 - Encoding x86 Instructions
3.3.8 - Step-by-Step Instruction Execution
3.3.9 - The Differences Between the x86 Processors
3.3.10 - The 886 Processor
3.3.11 - The 8286 Processor
3.3.12 - The 8486 Processor
3.3.12.1 - The 8486 Pipeline
3.3.12.2 - Stalls in a Pipeline
3.3.12.3 - Cache, the Prefetch Queue, and the 8486
3.3.12.4 - Hazards on the 8486
3.3.13 - The 8686 Processor
3.4 - I/O (Input/Output)
3.5 - Interrupts and Polled I/O

3.6 Laboratory Exercises
3.6.1 The SIMx86 Program - Some Simple x86 Programs
3.6.2 Simple I/O-Mapped Input/Output Operations
3.6.3 Memory Mapped I/O
3.6.4 DMA Exercises
3.6.5 Interrupt Driven I/O Exercises
3.6.6 Machine Language Programming & Instruction Encoding Exercises
3.6.7 Self Modifying Code Exercises
3.7 Programming Projects
3.8 Summary
3.9 Questions

Chapter Four - Memory Layout and Access
4.0 - Chapter Overview
4.1 - The 80x86 CPUs:A Programmer's View
4.1.1 - 8086 General Purpose Registers
4.1.2 - 8086 Segment Registers
4.1.3 - 8086 Special Purpose Registers
4.1.4 - 80286 Registers
4.1.5 - 80386/80486 Registers
4.2 - 80x86 Physical Memory Organization
4.3 - Segments on the 80x86
4.4 - Normalized Addresses on the 80x86
4.5 - Segment Registers on the 80x86
4.6 - The 80x86 Addressing Modes
4.6.1 - 8086 Register Addressing Modes
4.6.2 - 8086 Memory Addressing Modes
4.6.2.1 - The Displacement Only Addressing Mode
4.6.2.2 - The Register Indirect Addressing Modes
4.6.2.3 - Indexed Addressing Modes
4.6.2.4 - Based Indexed Addressing Modes
4.6.2.5 - Based Indexed Plus Displacement Addressing Mode
4.6.2.6 - MASM Syntax for 8086 Memory Addressing Modes
4.6.2.7 - An Easy Way to Remember the 8086 Memory Addressing Modes
4.6.2.8 - Some Final Comments About 8086 Addressing Modes
4.6.3 - 80386 Register Addressing Modes
4.6.4 - 80386 Memory Addressing Modes
4.6.4.1 - Register Indirect Addressing Modes
4.6.4.2 - 80386 Indexed, Base/Indexed, and Base/Indexed/Disp Addressing Modes
4.6.4.3 - 80386 Scaled Indexed Addressing Modes
4.6.4.4 - Some Final Notes About the 80386 Memory Addressing Modes
4.7 - The 80x86 MOV Instruction
4.8 - Some Final Comments on the MOV Instructions
4.9 Laboratory Exercises
4.9.1 The UCR Standard Library for 80x86 Assembly Language Programmers
4.9.2 Editing Your Source Files
4.9.3 The SHELL.ASM File
4.9.4 Assembling Your Code with MASM
4.9.5 Debuggers and CodeView'
4.9.5.1 A Quick Look at CodeView
4.9.5.2 The Source Window
4.9.5.3 The Memory Window
4.9.5.4 The Register Window
4.9.5.5 The Command Window
4.9.5.6 The Output Menu Item
4.9.5.7 The CodeView Command Window
4.9.5.7.1 The Radix Command (N)
4.9.5.7.2 The Assemble Command
4.9.5.7.3 The Compare Memory Command
4.9.5.7.4 The Dump Memory Command
4.9.5.7.5 The Enter Command
4.9.5.7.6 The Fill Memory Command
4.9.5.7.7 The Move Memory Command
4.9.5.7.8 The Input Command
4.9.5.7.9 The Output Command
4.9.5.7.10 The Quit Command
4.9.5.7.11 The Register Command
4.9.5.7.12 The Unassemble Command
4.9.5.8 CodeView Function Keys
4.9.5.9 Some Comments on CodeView Addresses
4.9.5.10 A Wrap on CodeView
4.9.6 Laboratory Tasks
4.10 Programming Projects
4.11 Summary
4.12 Questions

## Section Two: Basic Assembly Language

Chapter Five - Variables and Data Structures
5.0 - Chapter Overview
5.1 - Some Additional Instructions: LEA, LES, ADD, and MUL
5.2 - Declaring Variables in an Assembly Language Program
5.3 - Declaring and Accessing Scalar Variables
5.3.1 - Declaring and using BYTE Variables
5.3.2 - Declaring and using WORD Variables
5.3.3 - Declaring and using DWORD Variables
5.3.4 - Declaring and using FWORD, QWORD, and TBYTE Variables
5.3.5 - Declaring Floating Point Variables with REAL4, REAL8, and REAL10
5.4 - Creating Your Own Type Names with TYPEDEF
5.5 - Pointer Data Types
5.6 - Composite Data Types
5.6.1 - Arrays
5.6.1.1 - Declaring Arrays in Your Data Segment
5.6.1.2 - Accessing Elements of a Single Dimension Array
5.6.2 - Multidimensional Arrays
5.6.2.1 - Row Major Ordering
5.6.2.2 - Column Major Ordering
5.6.2.3 - Allocating Storage for Multidimensional Arrays
5.6.2.4 - Accessing Multidimensional Array Elements in Assembly Language
5.6.3 - Structures
5.6.4 - Arrays of Structures and Arrays/Structures as Structure Fields
5.6.5 - Pointers to Structures
5.7 - Sample Programs
5.7.1 - Simple Variable Declarations
5.7.2 - Using Pointer Variables
5.7.3 - Single Dimension Array Access
5.7.4 - Multidimensional Array Access
5.7.5 - Simple Structure Access
5.7.6 - Arrays of Structures
5.7.7 - Structures and Arrays as Fields of Another Structure
5.7.8 - Pointers to Structures and Arrays of Structure

5.8 Laboratory Exercises
5.9 Programming Projects
5.10 Summary
5.11 Questions

Chapter Six - The 80x86 Instruction Set
6.0 - Chapter Overview
6.1 - The Processor Status Register (Flags)
6.2 - Instruction Encodings
6.3 - Data Movement Instructions
6.3.1 - The MOV Instruction
6.3.2 - The XCHG Instruction
6.3.3 - The LDS, LES, LFS, LGS, and LSS Instructions
6.3.4 - The LEA Instruction
6.3.5 - The PUSH and POP Instructions
6.3.6 - The LAHF and SAHF Instructions
6.4 - Conversions
6.4.1 - The MOVZX, MOVSX, CBW, CWD, CWDE, and CDQ Instructions
6.4.2 - The BSWAP Instruction
6.4.3 - The XLAT Instruction
6.5 - Arithmetic Instructions
6.5.1 - The Addition Instructions: ADD, ADC, INC, XADD, AAA, and DAA
6.5.1.1 - The ADD and ADC Instructions
6.5.1.2 - The INC Instruction
6.5.1.3 - The XADD Instruction
6.5.1.4 - The AAA and DAA Instructions
6.5.2 - The Subtraction Instructions: SUB, SBB, DEC, AAS, and DAS
6.5.3 - The CMP Instruction
6.5.4 - The CMPXCHG, and CMPXCHG8B Instructions
6.5.5 - The NEG Instruction
6.5.6 - The Multiplication Instructions: MUL, IMUL, and AAM
6.5.7 - The Division Instructions: DIV, IDIV, and AAD
6.6 - Logical, Shift, Rotate and Bit Instructions
6.6.1 - The Logical Instructions: AND, OR, XOR, and NOT
6.6.2 - The Shift Instructions: SHL/SAL, SHR, SAR, SHLD, and SHRD
6.6.2.1 - SHL/SAL
6.6.2.2 - SAR
6.6.2.3 - SHR
6.6.2.4 - The SHLD and SHRD Instructions
6.6.3 - The Rotate Instructions: RCL, RCR, ROL, and ROR
6.6.3.1 - RCL
6.6.3.2 - RCR
6.6.3.3 - ROL
6.6.3.4 - ROR
6.6.4 - The Bit Operations
6.6.4.1 - TEST
6.6.4.2 - The Bit Test Instructions: BT, BTS, BTR, and BTC
6.6.4.3 - Bit Scanning: BSF and BSR
6.6.5 - The "Set on Condition" Instructions
6.7 - I/O Instructions
6.8 - String Instructions
6.9 - Program Flow Control Instructions
6.9.1 - Unconditional Jumps
6.9.2 - The CALL and RET Instructions
6.9.3 - The INT, INTO, BOUND, and IRET Instructions
6.9.4 - The Conditional Jump Instructions
6.9.5 - The JCXZ/JECXZ Instructions
6.9.6 - The LOOP Instruction
6.9.7 - The LOOPE/LOOPZ Instruction
6.9.8 - The LOOPNE/LOOPNZ Instruction
6.10 - Miscellaneous Instructions
6.11 - Sample Programs
6.11.1 - Simple Arithmetic I
6.11.2 - Simple Arithmetic II
6.11.3 - Logical Operations
6.11.4 - Shift and Rotate Operations
6.11.5 - Bit Operations and SETcc Instructions
6.11.6 - String Operations
6.11.7 - Conditional Jumps
6.11.8 - CALL and INT Instructions
6.11.9 - Conditional Jumps I
6.11.10 - Conditional Jump Instructions II

6.12 Laboratory Exercises
6.12.1 The IBM/L System
6.12.2 IBM/L Exercises
6.13 Programming Projects
6.14 Summary
6.15 Questions

Chapter Seven - The UCR Standard Library
7.0 - Chapter Overview
7.1 - An Introduction to the UCR Standard Library
7.1.1 - Memory Management Routines: MEMINIT, MALLOC, and FREE
7.1.2 - The Standard Input Routines: GETC, GETS, GETSM
7.1.3 - The Standard Output Routines: PUTC, PUTCR, PUTS, PUTH, PUTI, PRINT, and PRINTF
7.1.4 - Formatted Output Routines: Putisize, Putusize, Putlsize, and Putulsize
7.1.5 - Output Field Size Routines: Isize, Usize, and Lsize
7.1.6 - Conversion Routines: ATOx, and xTOA
7.1.7 - Routines that Test Characters for Set Membership
7.1.8 - Character Conversion Routines: ToUpper, ToLower
7.1.9 - Random Number Generation: Random, Randomize
7.1.10 - Constants, Macros, and other Miscellany
7.1.11 - Plus more!
7.2 - Sample Programs
7.2.1 - Stripped SHELL.ASM File
7.2.2 - Numeric I/O

7.3 Laboratory Exercises
7.3.1 Obtaining the UCR Standard Library
7.3.2 Unpacking the Standard Library
7.3.3 Using the Standard Library
7.3.4 The Standard Library Documentation Files
7.4 Programming Projects
7.5 Summary
7.6 Questions

Chapter Eight - MASM: Directives & Pseudo-Opcodes
8.0 - Chapter Overview
8.1 - Assembly Language Statements
8.2 - The Location Counter
8.3 - Symbols
8.4 - Literal Constants
8.4.1 - Integer Constants
8.4.2 - String Constants
8.4.3 - Real Constants
8.4.4 - Text Constants
8.5 - Declaring Manifest Constants Using Equates
8.6 - Processor Directives
8.7 - Procedures
8.8 - Segments
8.8.1 - Segment Names
8.8.2 - Segment Loading Order
8.8.3 - Segment Operands
8.8.3.1 - The ALIGN Type
8.8.3.2 - The COMBINE Type
8.8.4 - The CLASS Type
8.8.5 - The Read-only Operand
8.8.6 - The USE16, USE32, and FLAT Options
8.8.7 - Typical Segment Definitions
8.8.8 - Why You Would Want to Control the Loading Order
8.8.9 - Segment Prefixes
8.8.10 - Controlling Segments with the ASSUME Directive
8.8.11 - Combining Segments: The GROUP Directive
8.8.12 - Why Even Bother With Segments?
8.9 - The END Directive
8.10 - Variables
8.11 - Label Types
8.11.1 - How to Give a Symbol a Particular Type
8.11.2 - Label Values
8.11.3 - Type Conflicts
8.12 - Address Expressions
8.12.1 - Symbol Types and Addressing Modes
8.12.2 - Arithmetic and Logical Operators
8.12.3 - Coercion
8.12.4 - Type Operators
8.12.5 - Operator Precedence
8.13 - Conditional Assembly
8.13.1 - IF Directive
8.13.2 - IFE directive
8.13.3 - IFDEF and IFNDEF
8.13.4 - IFB, IFNB
8.13.5 - IFIDN, IFDIF, IFIDNI, and IFDIFI
8.14 - Macros
8.14.1 - Procedural Macros
8.14.2 - Macros vs. 80x86 Procedures
8.14.3 - The LOCAL Directive
8.14.4 - The EXITM Directive
8.14.5 - Macro Parameter Expansion and Macro Operators
8.14.6 - A Sample Macro to Implement For Loops
8.14.7 - Macro Functions
8.14.8 - Predefined Macros, Macro Functions, and Symbols
8.14.9 - Macros vs. Text Equates
8.14.10 - Macros: Good and Bad News
8.15 - Repeat Operations
8.16 - The FOR and FORC Macro Operations
8.17 - The WHILE Macro Operation
8.18 - Macro Parameters
8.19 - Controlling the Listing
8.19.1 - The ECHO and %OUT Directives
8.19.2 - The TITLE Directive
8.19.3 - The SUBTTL Directive
8.19.4 - The PAGE Directive
8.19.5 - The .LIST, .NOLIST, and .XLIST Directives
8.19.6 - Other Listing Directives
8.20 - Managing Large Programs
8.20.1 - The INCLUDE Directive
8.20.2 - The PUBLIC, EXTERN, and EXTRN Directives
8.20.3 - The EXTERNDEF Directive
8.21 - Make Files
8.22 - Sample Program
8.22.1 - EX8.MAK
8.22.2 - Matrix.A
8.22.3 - EX8.ASM
8.22.4 - GETI.ASM
8.22.5 - GetArray.ASM
8.22.6 - XProduct.ASM

8.23 Laboratory Exercises
8.23.1 Near vs. Far Procedures
8.23.2 Data Alignment Exercises
8.23.3 Equate Exercise
8.23.4 IFDEF Exercise
8.23.5 Make File Exercise
8.24 Programming Projects
8.25 Summary
8.26 Questions

Chapter Nine - Arithmetic and Logical Operations
9.0 - Chapter Overview
9.1 - Arithmetic Expressions
9.1.1 - Simple Assignments
9.1.2 - Simple Expressions
9.1.3 - Complex Expressions
9.1.4 - Commutative Operators
9.2 - Logical (Boolean) Expressions
9.3 - Multiprecision Operations
9.3.1 - Multiprecision Addition Operations
9.3.2 - Multiprecision Subtraction Operations
9.3.3 - Extended Precision Comparisons
9.3.4 - Extended Precision Multiplication
9.3.5 - Extended Precision Division
9.3.6 - Extended Precision NEG Operations
9.3.7 - Extended Precision AND Operations
9.3.8 - Extended Precision OR Operations
9.3.9 - Extended Precision XOR Operations
9.3.10 - Extended Precision NOT Operations
9.3.11 - Extended Precision Shift Operations
9.3.12 - Extended Precision Rotate Operations
9.4 - Operating on Different Sized Operands
9.5 - Machine and Arithmetic Idioms
9.5.1 - Multiplying Without MUL and IMUL
9.5.2 - Division Without DIV and IDIV
9.5.3 - Using AND to Compute Remainders
9.5.4 - Implementing Modulo-n Counters with AND
9.5.5 - Testing an Extended Precision Value for 0FFFF..FFh
9.5.6 - TEST Operations
9.5.7 - Testing Signs with the XOR Instruction
9.6 - Masking Operations
9.6.1 - Masking Operations with the AND Instruction
9.6.2 - Masking Operations with the OR Instruction
9.7 - Packing and Unpacking Data Types
9.8 - Tables
9.8.1 - Function Computation via Table Look Up
9.8.2 - Domain Conditioning
9.8.3 - Generating Tables
9.9 - Sample Programs
9.9.1 - Converting Arithmetic Expressions to Assembly Language
9.9.2 - Boolean Operations Example
9.9.3 - 64-bit Integer I/O
9.9.4 - Packing and Unpacking Date Data Types

9.10 Laboratory Exercises
9.10.1 Debugging Programs with CodeView
9.10.2 Debugging Strategies
9.10.2.1 Locating Infinite Loops
9.10.2.2 Incorrect Computations
9.10.2.3 Illegal Instructions/Infinite Loops Part II
9.10.3 Debug Exercise I: Using CodeView to Find Bugs in a Calculation
9.10.4 Software Delay Loop Exercises
9.11 Programming Projects
9.12 Summary
9.13 Questions

Chapter 10 - Control Structures
10.0 - Chapter Overview
10.1 - Introduction to Decisions
10.2 - IF..THEN..ELSE Sequences
10.3 - CASE Statements
10.4 - State Machines and Indirect Jumps
10.5 - Spaghetti Code
10.6 - Loops
10.6.1 - While Loops
10.6.2 - Repeat..Until Loops
10.6.3 - LOOP..ENDLOOP Loops
10.6.4 - FOR Loops
10.7 - Register Usage and Loops
10.8 - Performance Improvements
10.8.1 - Moving the Termination Condition to the End of a Loop
10.8.2 - Executing the Loop Backwards
10.8.3 - Loop Invariant Computations
10.8.4 - Unraveling Loops
10.8.5 - Induction Variables
10.8.6 - Other Performance Improvements
10.9 - Nested Statements
10.10 - Timing Delay Loops
10.11 - Sample Program

10.12 Laboratory Exercises
10.12.1 The Physics of Sound
10.12.2 The Fundamentals of Music
10.12.3 The Physics of Music
10.12.4 The 8253/8254 Timer Chip
10.12.5 Programming the Timer Chip to Produce Musical Tones
10.12.6 Putting it All Together
10.12.7 Amazing Grace Exercise
10.13 Programming Projects
10.14 Summary
10.15 Questions

Chapter Eleven - Procedures and Functions
11.0 - Chapter Overview
11.1 - Procedures
11.2 - Near and Far Procedures
11.2.1 - Forcing NEAR or FAR CALLs and Returns
11.2.2 - Nested Procedures
11.3 - Functions
11.4 - Saving the State of the Machine
11.5 - Parameters
11.5.1 - Pass by Value
11.5.2 - Pass by Reference
11.5.3 - Pass by Value-Returned
11.5.4 - Pass by Result
11.5.5 - Pass by Name
11.5.6 - Pass by Lazy-Evaluation
11.5.7 - Passing Parameters in Registers
11.5.8 - Passing Parameters in Global Variables
11.5.9 - Passing Parameters on the Stack
11.5.10 - Passing Parameters in the Code Stream
11.5.11 - Passing Parameters via a Parameter Block
11.6 - Function Results
11.6.1 - Returning Function Results in a Register
11.6.2 - Returning Function Results on the Stack
11.6.3 - Returning Function Results in Memory Locations
11.7 - Side Effects
11.8 - Local Variable Storage
11.9 - Recursion
11.10 - Sample Program
11.11 Laboratory Exercises
11.11.1 Ex11_1.cpp
11.11.2 Ex11_1.asm
11.11.3 EX11_1a.asm
11.12 Programming Projects
11.13 Summary
11.14 Questions

## Section Three: Intermediate Level Assembly Language Programming

Chapter 12 - Procedures: Advanced Topics
12.0 - Chapter Overview
12.1 - Lexical Nesting, Static Links, and Displays
12.1.1 - Scope
12.1.2 - Unit Activation, Address Binding, and Variable Lifetime
12.1.3 - Static Links
12.1.4 - Accessing Non-Local Variables Using Static Links
12.1.5 - The Display
12.1.6 - The 80286 ENTER and LEAVE Instructions
12.2 - Passing Variables at Different Lex Levels as Parameters.
12.2.1 - Passing Parameters by Value in a Block Structured Language
12.2.2 - Passing Parameters by Reference, Result, and Value-Result in a Block Structured Language
12.2.3 - Passing Parameters by Name and Lazy-Evaluation in a Block Structured Language
12.3 - Passing Parameters as Parameters to Another Procedure
12.3.1 - Passing Reference Parameters to Other Procedures
12.3.2 - Passing Value-Result and Result Parameters as Parameters
12.3.3 - Passing Name Parameters to Other Procedures
12.3.4 - Passing Lazy Evaluation Parameters as Parameters
12.3.5 - Parameter Passing Summary
12.4 - Passing Procedures as Parameters
12.5 - Iterators
12.5.1 - Implementing Iterators Using In-Line Expansion
12.5.2 - Implementing Iterators with Resume Frames
12.6 - Sample Programs
12.6.1 - An Example of an Iterator
12.6.2 - Another Iterator Example

12.7 Laboratory Exercises
12.7.1 Iterator Exercise
12.7.2 The 80x86 Enter and Leave Instructions
12.7.3 Parameter Passing Exercises
12.8 Programming Projects
12.9 Summary
12.10 Questions

Chapter 13 - MS-DOS, PC-BIOS, and File I/O
13.0 - Chapter Overview
13.1 - The IBM PC BIOS
13.2 - An Introduction to the BIOS' Services
13.2.1 - INT 5- Print Screen
13.2.2 - INT 10h - Video Services
13.2.3 - INT 11h - Equipment Installed
13.2.4 - INT 12h - Memory Available
13.2.5 - INT 13h - Low Level Disk Services
13.2.6 - INT 14h - Serial I/O
13.2.6.1 - AH=0: Serial Port Initialization
13.2.6.2 - AH=1: Transmit a Character to the Serial Port
13.2.6.3 - AH=2: Receive a Character from the Serial Port
13.2.6.4 - AH=3: Serial Port Status
13.2.7 - INT 15h - Miscellaneous Services
13.2.8 - INT 16h - Keyboard Services
13.2.8.1 - AH=0: Read a Key From the Keyboard
13.2.8.2 - AH=1: See if a Key is Available at the Keyboard
13.2.8.3 - AH=2: Return Keyboard Shift Key Status
13.2.9 - INT 17h - Printer Services
13.2.9.1 - AH=0: Print a Character
13.2.9.2 - AH=1: Initialize Printer
13.2.9.3 - AH=2: Return Printer Status
13.2.10 - INT 18h - Run BASIC
13.2.11 - INT 19h - Reboot Computer
13.2.12 - INT 1Ah - Real Time Clock
13.2.12.1 - AH=0: Read the Real Time Clock
13.2.12.2 - AH=1: Setting the Real Time Clock
13.3 - An Introduction to MS-DOS'
13.3.1 - MS-DOS Calling Sequence
13.3.2 - MS-DOS Character Oriented Functions
13.3.3 - MS-DOS Drive Commands
13.3.4 - MS-DOS "Obsolete" Filing Calls
13.3.5 - MS-DOS Date and Time Functions
13.3.6 - MS-DOS Memory Management Functions
13.3.6.1 - Allocate Memory
13.3.6.2 - Deallocate Memory
13.3.6.3 - Modify Memory Allocation
13.3.6.4 - Advanced Memory Management Functions
13.3.7 - MS-DOS Process Control Functions
13.3.7.1 - Terminate Program Execution
13.3.7.2 - Terminate, but Stay Resident
13.3.7.3 - Execute a Program
13.3.8 - MS-DOS "New" Filing Calls
13.3.8.1 - Open File
13.3.8.2 - Create File
13.3.8.3 - Close File
13.3.8.4 - Read From a File
13.3.8.5 - Write to a File
13.3.8.6 - Seek (Move File Pointer)
13.3.8.7 - Set Disk Transfer Address (DTA)
13.3.8.8 - Find First File
13.3.8.9 - Find Next File
13.3.8.10 - Delete File
13.3.8.11 - Rename File
13.3.8.12 - Change/Get File Attributes
13.3.8.13 - Get/Set File Date and Time
13.3.8.14 - Other DOS Calls
13.3.9 - File I/O Examples
13.3.9.1 - Example #1: A Hex Dump Utility
13.3.9.2 - Example #2: Upper Case Conversion
13.3.10 - Blocked File I/O
13.3.11 - The Program Segment Prefix (PSP)
13.3.12 - Accessing Command Line Parameters
13.3.13 - ARGC and ARGV
13.4 - UCR Standard Library File I/O Routines
13.4.1 - Fopen
13.4.2 - Fcreate
13.4.3 - Fclose
13.4.4 - Fflush
13.4.5 - Fgetc
13.4.6 - Fread
13.4.7 - Fputc
13.4.8 - Fwrite
13.4.9 - Redirecting I/O Through the StdLib File I/O Routines
13.4.10 - A File I/O Example
13.5 - Sample Program
13.6 Laboratory Exercises
13.7 Programming Projects
13.8 Summary
13.9 Questions

Chapter 14 - Floating Point Arithmetic
14.0 - Chapter Overview
14.1 - The Mathematics of Floating Point Arithmetic
14.2 - IEEE Floating Point Formats
14.3 - The UCR Standard Library Floating Point Routines
14.3.1 - Load and Store Routines
14.3.2 - Integer/Floating Point Conversion
14.3.3 - Floating Point Arithmetic
14.3.4 - Float/Text Conversion and Printff
14.4 - The 80x87 Floating Point Coprocessors
14.4.1 - FPU Registers
14.4.1.1 - The FPU Data Registers
14.4.1.2 - The FPU Control Register
14.4.1.3 - The FPU Status Register
14.4.2 - FPU Data Types
14.4.3 - The FPU Instruction Set
14.4.4 - FPU Data Movement Instructions
14.4.4.1 - The FLD Instruction
14.4.4.2 - The FST and FSTP Instructions
14.4.4.3 - The FXCH Instruction
14.4.5 - Conversions
14.4.5.1 - The FILD Instruction
14.4.5.2 - The FIST and FISTP Instructions
14.4.5.3 - The FBLD and FBSTP Instructions
14.4.6 - Arithmetic Instructions
14.4.6.1 - The FADD and FADDP Instructions
14.4.6.2 - The FSUB, FSUBP, FSUBR, and FSUBRP Instructions
14.4.6.3 - The FMUL and FMULP Instructions
14.4.6.4 - The FDIV, FDIVP, FDIVR, and FDIVRP Instructions
14.4.6.5 - The FSQRT Instruction
14.4.6.6 - The FSCALE Instruction
14.4.6.7 - The FPREM and FPREM1 Instructions
14.4.6.8 - The FRNDINT Instruction
14.4.6.9 - The FXTRACT Instruction
14.4.6.10 - The FABS Instruction
14.4.6.11 - The FCHS Instruction
14.4.7 - Comparison Instructions
14.4.7.1 - The FCOM, FCOMP, and FCOMPP Instructions
14.4.7.2 - The FUCOM, FUCOMP, and FUCOMPP Instructions
14.4.7.3 - The FTST Instruction
14.4.7.4 - The FXAM Instruction
14.4.8 - Constant Instructions
14.4.9 - Transcendental Instructions
14.4.9.1 - The F2XM1 Instruction
14.4.9.2 - The FSIN, FCOS, and FSINCOS Instructions
14.4.9.3 - The FPTAN Instruction
14.4.9.4 - The FPATAN Instruction
14.4.9.5 - The FYL2X and FYL2XP1 Instructions
14.4.10 - Miscellaneous instructions
14.4.10.1 - The FINIT and FNINIT Instructions
14.4.10.2 - The FWAIT Instruction
14.4.10.3 - The FLDCW and FSTCW Instructions
14.4.10.4 - The FCLEX and FNCLEX Instructions
14.4.10.5 - The FLDENV, FSTENV, and FNSTENV Instructions
14.4.10.6 - The FSAVE, FNSAVE, and FRSTOR Instructions
14.4.10.7 - The FSTSW and FNSTSW Instructions
14.4.10.8 - The FINCSTP and FDECSTP Instructions
14.4.10.9 - The FNOP Instruction
14.4.10.10 - The FFREE Instruction
14.4.11 - Integer Operations
14.5 - Sample Program: Additional Trigonometric Functions
14.6 Laboratory Exercises
14.6.1 FPU vs StdLib Accuracy
14.7 Programming Projects
14.8 Summary
14.9 Questions

Chapter 15 - Strings and Character Sets
15.0 - Chapter Overview
15.1 - The 80x86 String Instructions
15.1.1 - How the String Instructions Operate
15.1.2 - The REP/REPE/REPZ and REPNZ/REPNE Prefixes
15.1.3 - The Direction Flag
15.1.4 - The MOVS Instruction
15.1.5 - The CMPS Instruction
15.1.6 - The SCAS Instruction
15.1.7 - The STOS Instruction
15.1.8 - The LODS Instruction
15.1.9 - Building Complex String Functions from LODS and STOS
15.1.10 - Prefixes and the String Instructions
15.2 - Character Strings
15.2.1 - Types of Strings
15.2.2 - String Assignment
15.2.3 - String Comparison
15.3 - Character String Functions
15.3.1 - Substr
15.3.2 - Index
15.3.3 - Repeat
15.3.4 - Insert
15.3.5 - Delete
15.3.6 - Concatenation
15.4 - String Functions in the UCR Standard Library
15.4.1 - StrBDel, StrBDelm
15.4.2 - Strcat, Strcatl, Strcatm, Strcatml
15.4.3 - Strchr
15.4.4 - Strcmp, Strcmpl, Stricmp, Stricmpl
15.4.5 - Strcpy, Strcpyl, Strdup, Strdupl
15.4.6 - Strdel, Strdelm
15.4.7 - Strins, Strinsl, Strinsm, Strinsml
15.4.8 - Strlen
15.4.9 - Strlwr, Strlwrm, Strupr, Struprm
15.4.10 - Strrev, Strrevm
15.4.11 - Strset, Strsetm
15.4.12 - Strspan, Strspanl, Strcspan, Strcspanl
15.4.13 - Strstr, Strstrl
15.4.14 - Strtrim, Strtrimm
15.4.15 - Other String Routines in the UCR Standard Library
15.5 - The Character Set Routines in the UCR Standard Library
15.6 - Using the String Instructions on Other Data Types
15.6.1 - Multi-precision Integer Strings
15.6.2 - Dealing with Whole Arrays and Records
15.7 - Sample Programs
15.7.1 - Find.asm
15.7.2 - StrDemo.asm
15.7.3 - Fcmp.asm

15.8 Laboratory Exercises
15.8.1 MOVS Performance Exercise #1
15.8.2 MOVS Performance Exercise #2
15.8.3 Memory Performance Exercise
15.8.4 The Performance of Length-Prefixed vs. Zero-Terminated Strings
15.9 Programming Projects
15.10 Summary
15.11 Questions

Chapter 16 - Pattern Matching
16.1 - An Introduction to Formal Language (Automata) Theory
16.1.1 - Machines vs. Languages
16.1.2 - Regular Languages
16.1.2.1 - Regular Expressions
16.1.2.2 - Nondeterministic Finite State Automata (NFAs)
16.1.2.3 - Converting Regular Expressions to NFAs
16.1.2.4 - Converting an NFA to Assembly Language
16.1.2.5 - Deterministic Finite State Automata (DFAs)
16.1.2.6 - Converting a DFA to Assembly Language
16.1.3 - Context Free Languages
16.1.4 - Eliminating Left Recursion and Left Factoring CFGs
16.1.5 - Converting REs to CFGs
16.1.6 - Converting CFGs to Assembly Language
16.1.7 - Some Final Comments on CFGs
16.1.8 - Beyond Context Free Languages
16.2 - The UCR Standard Library Pattern Matching Routines
16.3 - The Standard Library Pattern Matching Functions
16.3.1 - Spancset
16.3.2 - Brkcset
16.3.3 - Anycset
16.3.4 - Notanycset
16.3.5 - MatchStr
16.3.6 - MatchiStr
16.3.7 - MatchToStr
16.3.8 - MatchChar
16.3.9 - MatchToChar
16.3.10 - MatchChars
16.3.11 - MatchToPat
16.3.12 - EOS
16.3.13 - ARB
16.3.14 - ARBNUM
16.3.15 - Skip
16.3.16 - Pos
16.3.17 - RPos
16.3.18 - GotoPos
16.3.19 - RGotoPos
16.3.20 - SL_Match2
16.4 - Designing Your Own Pattern Matching Routines
16.5 - Extracting Substrings from Matched Patterns
16.6 - Semantic Rules and Actions
16.7 - Constructing Patterns for the MATCH Routine
16.8 - Some Sample Pattern Matching Applications
16.8.1 - Converting Written Numbers to Integers
16.8.2 - Processing Dates
16.8.3 - Evaluating Arithmetic Expressions
16.8.4 - A Tiny Assembler
16.8.5 - The "MADVENTURE" Game
16.9 - Laboratory Exercises
16.9.1 - Checking for Stack Overflow (Infinite Loops)
16.9.2 - Printing Diagnostic Messages from a Pattern

16.10 Programming Projects
16.11 Summary
16.12 Questions

## Section Four: Advanced Assembly Language Programming

Chapter 17 - Interrupts, Traps, and Exceptions
17.1 - 80x86 Interrupt Structure and Interrupt Service Routines (ISRs)
17.2 - Traps
17.3 - Exceptions
17.3.1 - Divide Error Exception (INT 0)
17.3.2 - Single Step (Trace) Exception (INT 1)
17.3.3 - Breakpoint Exception (INT 3)
17.3.4 - Overflow Exception (INT 4/INTO)
17.3.5 - Bounds Exception (INT 5/BOUND)
17.3.6 - Invalid Opcode Exception (INT 6)
17.3.7 - Coprocessor Not Available (INT 7)
17.4 - Hardware Interrupts
17.4.1 - The 8259A Programmable Interrupt Controller (PIC)
17.4.2 - The Timer Interrupt (INT 8)
17.4.3 - The Keyboard Interrupt (INT 9)
17.4.4 - The Serial Port Interrupts (INT 0Bh and INT 0Ch)
17.4.5 - The Parallel Port Interrupts (INT 0Dh and INT 0Fh)
17.4.6 - The Diskette and Hard Drive Interrupts (INT 0Eh and INT 76h)
17.4.7 - The Real-Time Clock Interrupt (INT 70h)
17.4.8 - The FPU Interrupt (INT 75h)
17.4.9 - Nonmaskable Interrupts (INT 2)
17.4.10 - Other Interrupts
17.5 - Chaining Interrupt Service Routines
17.6 - Reentrancy Problems
17.7 - The Efficiency of an Interrupt Driven System
17.7.1 - Interrupt Driven I/O vs. Polling
17.7.2 - Interrupt Service Time
17.7.3 - Interrupt Latency
17.7.4 - Prioritized Interrupts
17.8 - Debugging ISRs

17.9 Summary

Chapter 18 - Resident Programs
18.1 - DOS Memory Usage and TSRs
18.2 - Active vs. Passive TSRs
18.3 - Reentrancy
18.3.1 - Reentrancy Problems with DOS
18.3.2 - Reentrancy Problems with BIOS
18.3.3 - Reentrancy Problems with Other Code
18.4 - The Multiplex Interrupt (INT 2Fh)
18.5 - Installing a TSR
18.6 - Removing a TSR
18.7 - Other DOS Related Issues
18.8 - A Keyboard Monitor TSR
18.9 - Semiresident Programs

18.10 Summary

Chapter 19 - Processes, Coroutines, and Concurrency
19.1 - DOS Processes
19.1.1 - Child Processes in DOS
19.1.1.1 - Load and Execute
19.1.1.2 - Load Program
19.1.1.3 - Loading Overlays
19.1.1.4 - Terminating a Process
19.1.1.5 - Obtaining the Child Process Return Code
19.1.2 - Exception Handling in DOS: The Break Handler
19.1.3 - Exception Handling in DOS: The Critical Error Handler
19.1.4 - Exception Handling in DOS: Traps
19.1.5 - Redirection of I/O for Child Processes
19.2 - Shared Memory
19.2.1 - Static Shared Memory
19.2.2 - Dynamic Shared Memory
19.3 - Coroutines
19.3.1 - AMAZE.ASM
19.3.2 - 32-bit Coroutines
19.4 - Multitasking
19.4.1 - Lightweight and HeavyWeight Processes
19.4.2 - The UCR Standard Library Processes Package
19.4.3 - Problems with Multitasking
19.4.4 - A Sample Program with Threads
19.5 - Synchronization
19.5.1 - Atomic Operations, Test & Set, and Busy-Waiting
19.5.2 - Semaphores
19.5.3 - The UCR Standard Library Semaphore Support
19.5.4 - Using Semaphores to Protect Critical Regions
19.5.5 - Using Semaphores for Barrier Synchronization
19.6 - Deadlock

19.7 Summary

## Section Five: The PC's I/O Ports

Chapter 20 - The PC Keyboard
20.1 - Keyboard Basics
20.2 - The Keyboard Hardware Interface
20.3 - The Keyboard DOS Interface
20.4 - The Keyboard BIOS Interface
20.5 - The Keyboard Interrupt Service Routine
20.6 - Patching into the INT 9 Interrupt Service Routine
20.7 - Simulating Keystrokes
20.7.1 - Stuffing Characters in the Type Ahead Buffer
20.7.2 - Using the 80x86 Trace Flag to Simulate IN AL, 60H Instructions
20.7.3 - Using the 8042 Microcontroller to Simulate Keystrokes

20.8 Summary

Chapter 21 - The PC Parallel Ports
21.1 - Basic Parallel Port Information
21.2 - The Parallel Port Hardware
21.3 - Controlling a Printer Through the Parallel Port
21.3.1 - Printing via DOS
21.3.2 - Printing via BIOS
21.3.3 - An INT 17h Interrupt Service Routine
21.4 - Inter-Computer Communications on the Parallel Port

21.5 Summary

Chapter 22 - The PC Serial Ports
22.1 - The 8250 Serial Communications Chip
22.1.1 - The Data Register (Transmit/Receive Register)
22.1.2 - The Interrupt Enable Register (IER)
22.1.3 - The Baud Rate Divisor
22.1.4 - The Interrupt Identification Register (IIR)
22.1.5 - The Line Control Register
22.1.6 - The Modem Control Register
22.1.7 - The Line Status Register (LSR)
22.1.8 - The Modem Status Register (MSR)
22.1.9 - The Auxiliary Input Register
22.2 - The UCR Standard Library Serial Communications Support Routines
22.3 - Programming the 8250 (Examples from the Standard Library)
22.4 Summary

Chapter 23 - The PC Video Display
23.1 - Memory Mapped Video
23.2 - The Video Attribute Byte
23.3 - Programming the Text Display

23.4 Summary

Chapter 24 - The PC Game Adapter
24.1 - Typical Game Devices
24.2 - The Game Adapter Hardware
24.3 - Using BIOS' Game I/O Functions
24.4 - Writing Your Own Game I/O Routines
24.5 - The Standard Game Device Interface (SGDI)
24.5.1 - Application Programmer's Interface (API)
24.5.2 - Read4Sw
24.5.3 - Read4Pots:
24.5.4 - ReadPot
24.5.5 - Read4:
24.5.6 - CalibratePot
24.5.7 - TestPotCalibration
24.5.8 - ReadRaw
24.5.9 - ReadSwitch
24.5.10 - Read16Sw
24.5.11 - Remove
24.5.12 - TestPresence
24.5.13 - An SGDI Driver for the Standard Game Adapter Card
24.6 - An SGDI Driver for the CH Products' Flight Stick Pro'
24.7 - Patching Existing Games

24.8 Summary

## Section Six: Optimization

25.1 - When to Optimize, When Not to Optimize
25.2 - How Do You Find the Slow Code in Your Programs?
25.3 - Is Optimization Necessary?
25.4 - The Three Types of Optimization
25.5 - Improving the Implementation of an Algorithm

25.6 Summary

## Appendix D: Instruction Set Reference

Section D1

Section D2

Section D3

Section D4

The Art of Assembly Language Programming - 30 SEP 1996

[Randall Hyde]