- •Table of Contents
- •Foreword
- •Do Not Pass GO
- •Counting in Martian
- •Octal: How the Grinch Stole Eight and Nine
- •Hexadecimal: Solving the Digit Shortage
- •From Hex to Decimal and from Decimal to Hex
- •Arithmetic in Hex
- •Binary
- •Hexadecimal as Shorthand for Binary
- •Switches, Transistors, and Memory
- •The Shop Foreman and the Assembly Line
- •The Box That Follows a Plan
- •DOS and DOS files
- •Compilers and Assemblers
- •The Assembly Language Development Process
- •DEBUG and How to Use It
- •Chapter 5: NASM-IDE: A Place to Stand Give me a lever long enough, and a place to stand, and I will move the Earth.
- •NASM-IDE's Place to Stand
- •Using NASM-IDE's Tools
- •NASM-IDE's Editor in Detail
- •Other NASM-IDE Features
- •The Nature of Segments
- •16-Bit and 32-Bit Registers
- •The Three Major Assembly Programming Models
- •Reading and Changing Registers with DEBUG
- •Assembling and Executing Machine Instructions with DEBUG
- •Machine Instructions and Their Operands
- •Reading and Using an Assembly Language Reference
- •Rally Round the Flags, Boys!
- •Using Type Specifiers
- •The Bones of an Assembly Language Program
- •Assembling and Running EAT.ASM
- •One Program, Three Segments
- •Last In, First Out via the Stack
- •Using DOS Services through INT
- •Boxes within Boxes
- •Using BIOS Services
- •Building External Libraries of Procedures
- •Creating and Using Macros
- •Bits Is Bits (and Bytes Is Bits)
- •Shifting Bits
- •Flags, Tests, and Branches
- •Assembly Odds 'n Ends
- •The Notion of an Assembly Language String
- •REP STOSW, the Software Machine Gun
- •The Semiautomatic Weapon: STOSW without REP
- •Storing Data to Discontinuous Strings
- •Chapter 12: The Programmer's View of Linux Tools and Skills to Help You Write Assembly Code under a True 32-Bit OS
- •Prerequisites-Yukkh!
- •NASM for Linux
- •What's GNU?
- •The make Utility and Dependencies
- •Using the GNU Debugger
- •Your Work Strategy
- •Genuflecting to the C Culture
- •A Framework to Build On
- •The Perks of Protected Mode
- •Characters Out
- •Characters In
- •Be a Time Lord
- •Generating Random Numbers
- •Accessing Command-Line Arguments
- •Simple File I/O
- •Conclusion: Not the End, But Only the Beginning
- •Where to Now?
- •Stepping off Square One
- •Notes on the Instruction Set Reference
- •AAA Adjust AL after BCD Addition
- •ADC Arithmetic Addition with Carry
- •ADD Arithmetic Addition
- •AND Logical AND
- •BT Bit Test (386+)
- •CALL Call Procedure
- •CLC Clear Carry Flag (CF)
- •CLD Clear Direction Flag (DF)
- •CMP Arithmetic Comparison
- •DEC Decrement Operand
- •IMUL Signed Integer Multiplication
- •INC Increment Operand
- •INT Software Interrupt
- •IRET Return from Interrupt
- •J? Jump on Condition
- •JMP Unconditional Jump
- •LEA Load Effective Address
- •MOV Move (Copy) Right Operand into Left Operand
- •NOP No Operation
- •NOT Logical NOT (One's Complement)
- •OR Logical OR
- •POP Pop Top of Stack into Operand
- •POPA Pop All 16-Bit Registers (286+)
- •POPF Pop Top of Stack into Flags
- •POPFD Pop Top of Stack into EFlags (386+)
- •PUSH Push Operand onto Top of Stack
- •PUSHA Push All 16-Bit GP Registers (286+)
- •PUSHAD Push All 32-Bit GP Registers (386+)
- •PUSHF Push 16-Bit Flags onto Stack
- •PUSHFD Push 32-Bit EFlags onto Stack (386+)
- •RET Return from Procedure
- •ROL Rotate Left
- •ROR Rotate Right
- •SBB Arithmetic Subtraction with Borrow
- •SHL Shift Left
- •SHR Shift Right
- •STC Set Carry Flag (CF)
- •STD Set Direction Flag (DF)
- •STOS Store String
- •SUB Arithmetic Subtraction
- •XCHG Exchange Operands
- •XOR Exclusive Or
- •Appendix C: Web URLs for Assembly Programmers
- •Appendix D: Segment Register Assumptions
- •Appendix E: What's on the CD-ROM?
- •Index
- •List of Figures
- •List of Tables
CMP Arithmetic Comparison
Flags affected:
O |
D |
I |
T |
S |
Z |
A |
P |
C |
OF: |
Overflow flag TF: |
Trap |
flag |
AF: |
Aux carry |
F |
F |
F |
F |
F |
F |
F |
F |
F |
DF: |
Direction flag SF: |
Sign |
flag |
PF: |
Parity flag |
** * * * * IF: Interrupt flag ZF: Zero flag CF: Carry flag
Legal forms:
CMP r8,r8 |
|
CMP m8,r8 |
|
CMP r8,m8 |
|
CMP r16,r16 |
|
CMP m16,r16 |
|
CMP r16,16 |
386+ |
CMP r32,r32 |
|
CMP m32,r32 |
386+ |
CMP r32,m32 |
386+ |
CMP r8,i8 |
|
CMP m8,i8 |
|
CMP r16,i16 |
|
CMP m16,i16 |
386+ |
CMP r32,i32 |
|
CMP m32,i32 |
386+ |
CMP r16,i8 |
|
CMP m16,i8 |
386+ |
CMP r32,i8 |
|
CMP m32,i8 |
386+ |
CMP AL,i8 |
|
CMP AX,i16 |
386+ |
CMP EAX,i32 |
Examples:
CMP BX,DI |
|
CMP EAX,5 |
;Uses single-byte opcode |
CMP AX,0FFFFH |
|
CMP AL,42H |
;Uses single-byte opcode |
CMP BP,17H |
|
CMP WORD [BX+SI+Inset],5 |
|
CMP WORD ES:[BX],0B800H |
|
Notes:
CMP compares its two operations, and sets the flags to indicate the results of the comparison. The destination operand is not affected. The operation itself is identical to subtraction of the source from the destination without borrow (SUB), save that the result does not replace the destination. Typically, CMP is followed by one of the conditional jump instructions; that is, JE to jump if the operands were equal; JNE if they were unequal; and so forth.
r8 |
= |
AL |
AH |
BL BH |
CL |
CH |
DL DH |
r16 |
= AX BX CX DX |
BP SP SI DI |
||||
sr = |
CS |
DS SS ES |
FS GS |
|
r32 |
= EAX EBX ECX |
EDX EBP ESP ESI E |
|||||||
m8 |
= |
= |
8-bit |
memory data |
|
m16 |
= |
16-bit |
memory data |
|||||
m32 |
|
32-bit |
memory |
data |
i8 = 8-bit immediate data |
|||||||||
i16 |
|
= |
16-bit |
immediate |
data |
i32 |
= |
32-bit |
immediate data |
d8 = 8-bit signed displacement |
d16 = 16-bit signed displacement |
d32 = 32-bit unsigned displacement
DEC Decrement Operand
Flags affected:
O |
D |
I |
T |
S |
Z |
A |
P |
C |
OF: |
Overflow flag TF: |
Trap |
flag |
AF: |
Aux carry |
F |
F |
F |
F |
F |
F |
F |
F |
F |
DF: |
Direction flag SF: |
Sign |
flag |
PF: |
Parity flag |
** * * * IF: Interrupt flag ZF: Zero flag CF: Carry flag
Legal forms:
DEC m8
DEC m16
DEC m32
DEC r8
DEC r16
DEC r32
Examples:
DEC AL |
|
|
|
|
|
|
|
DEC |
CX |
|
|
|
|
|
|
DEC |
EBX |
; |
Decrements |
the |
BYTE |
at |
[BP] |
DEC |
BYTE [BP] |
||||||
DEC |
WORD [BX] |
; |
Decrements |
the |
WORD |
at |
[BX] |
DEC DWORD [EDX] ; Decrements the DWORD at [EDX]
Notes:
Remember that segment registers cannot be decremented with DEC. All register-half opcodes are 2 bytes in length, but all 16-bit register opcodes are 1 byte in length. If you can decrement an entire register of which only the lower half contains data, use the 16-bit opcode and save a byte.
As with all instructions that act on memory, memory data forms must be used with a data size specifier such as BYTE, WORD, and DWORD! NASM doesn't assume anything!
r8 = AL AH BL BH CL CH DL DH sr = CS DS SS ES FS GS
m8 = 8-bit memory data
m32 = 32-bit memory data
i16 = 16-bit immediate data
d8 = 8-bit signed displacement
d32 = 32-bit unsigned displacement
r16 = AX BX CX DX BP SP SI DI
r32 = EAX EBX ECX EDX EBP ESP ESI E m16 = 16-bit memory data
i8 = 8-bit immediate data
i32 = 32-bit immediate data
d16 = 16-bit signed displacement
IMUL Signed Integer Multiplication
Flags affected:
O D |
I |
T |
S |
Z |
A |
P |
C |
OF: Overflow flag TF: Trap flag AF: Aux carry |
||||
F |
F |
F |
F |
F |
F |
F |
F |
F |
DF: Direction |
flag SF: Sign |
flag |
PF: Parity flag |
* |
|
|
|
|
|
|
|
* IF: Interrupt |
flag ZF: Zero |
flag |
CF: Carry flag |
Legal forms:
IMUL r8 |
|
IMUL m8 |
|
IMUL r16 |
|
IMUL m16 |
386+ |
IMUL r32 |
|
IMUL i32 |
386+ |
IMUL r16,i8 |
286+ |
IMUL r16,i16 |
286+ |
IMUL r32,i8 |
386+ |
IMUL r32,i16 |
386+ |
IMUL r16,r16 |
386+ |
IMUL r16,m16 |
386+ |
IMUL r32,r32 |
386+ |
IMUL r32,m32 |
386+ |
IMUL r16,r16,i8 |
286+ |
IMUL r16,m16,i8 |
286+ |
IMUL r16,r16,i16 |
286+ |
IMUL r16,m16,i16 |
286+ |
IMUL r32,r32,i8 |
386+ |
IMUL r32,m32,i8 |
386+ |
IMUL r32,r32,i32 |
386+ |
IMUL r32,m32,i32 |
386+ |
Examples:
IMUL CH |
; AL * CH --> AX |
IMUL BX |
; AX * BX --> DX:AX |
IMUL ECX |
; EAX * ECX --> EDX:EAX |
IMUL WORD [BX+DI] |
; AX * DS:[BX+DI] --> DX:AX |
IMUL EAX,ECX |
; EAX * ECX --> EAX |
IMUL ECX,EAX,15 |
; EAX * 15 --> ECX |
Notes:
In its oldest, single-operand form (usable on all processors), IMUL multiplies its operand by AL, AX, or EAX, and the result is placed in AX, in DX:AX, or in EDX:EAX. If IMUL is given an 8-bit operand (either an 8-bit register or an 8-bit memory operand), the results will be placed in AX. This means that AH will be affected, even if the results will fit entirely in AL.
Similarly, if IMUL is given a 16-bit operand, the results will be placed in DX:AX, even if the entire result will fit in AX! It's easy to forget that IMUL affects DX on 16-bit multiples, and EDX in 32-bit multiples. Keep that in mind!
In both the twoand three-operand forms, the product replaces the contents of the first operand. In the twooperand form, the two operands are multiplied together, and the product replaces the first operand. In this it is like most other arithmetic and logical instructions. In the three-operand form, the second and third operand are multiplied, and the product replaces the first operand.
Note that with the twoand three-operand forms, there is the possibility that the product will not entirely fit in the destination register. When using those forms, the CF and OF flags will both be 0 (cleared) only if the product fits entirely in the destination. It's best to use the original forms in cases where you aren't sure of the range the product might take.
r8 = AL AH BL BH CL CH DL DH sr = CS DS SS ES FS GS
m8 = 8-bit memory data
m32 = 32-bit memory data
i16 = 16-bit immediate data
d8 = 8-bit signed displacement
d32 = 32-bit unsigned displacement
r16 = AX BX CX DX BP SP SI DI
r32 = EAX EBX ECX EDX EBP ESP ESI E m16 = 16-bit memory data
i8 = 8-bit immediate data
i32 = 32-bit immediate data
d16 = 16-bit signed displacement