- •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
INC Increment 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:
INC r8 |
|
INC m8 |
|
INC r16 |
|
INC m16 |
386+ |
INC r32 |
|
INC m32 |
386+ |
Examples:
INC AL |
|
|
|
|
|
|
|
INC |
BX |
|
|
|
|
|
|
INC |
EDX |
; |
Increments |
the |
BYTE |
at |
[BP] |
INC |
BYTE [BP] |
||||||
INC |
WORD [BX] |
; |
Increments |
the |
WORD |
at |
[BX] |
INC DWORD [ESI] ; Increments the DWORD at [ESI]
Notes:
Remember that segment registers cannot be incremented with INC. All register-half (r8) opcodes are 2 bytes in length, but all 16-bit register (r16) opcodes are 1 byte in length. If you can increment 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
INT Software Interrupt
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:
INT3 |
NASM-specific shorthand for INT 3 |
INT i8
Examples:
INT3 |
; NASM requires this to generate an INT 3 instruction |
INT 10H
Notes:
INT triggers a software interrupt to one of 256 vectors in the first 1,024 bytes of memory. The operand specifies which vector, from 0 to 255. When an interrupt is called, the Flags register is pushed on the stack along with the return address. The IF flag is cleared, which prevents further interrupts (either hardware or software) from being recognized until IF is set again. TF is also cleared.
A special form of the instruction allows calling Interrupt 3 with a single-byte instruction. Debuggers use Interrupt 3 to set breakpoints in code by replacing an instruction with the single-byte opcode for calling Interrupt 3. NASM does not recognize this, and if you want to use INT 3 for some reason (and that instruction form isn't of much use unless you're writing a debugger), you must use a special mnemonic form INT3 rather than INT 3. This is advanced stuff; be careful.
Virtually all your applications of INT will use the other form, which takes an 8-bit immediate numeric value.
Always return from a software interrupt service routine with the IRET instruction. IRET restores the flags that were pushed onto the stack by INT, and in doing so clears IF, allowing further interrupts.
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
IRET Return from Interrupt
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:
IRET
Examples:
IRET
Notes:
IRET must be used to exit from interrupt service routines called through INT or through interrupt hardware such as serial ports and the like. IRET pops the return address from the top of the stack into CS and IP, and then pops the next word from the stack into the Flags register. All flags are affected.
If the interrupt was triggered by hardware, there may be additional steps to be taken to prepare the hardware for another interrupt before IRET is executed. Consult your hardware documentation.
When using NASM, the actual opcode generated for IRET depends on the setting of the BITS setting, and governs whether a 16-bit return or 32-bit return is generated.
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
J? Jump on Condition
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 |
<none> IF: Interrupt flag ZF: Zero flag CF: Carry flag
Legal forms:
JA/JNBE d |
Descriptions |
Jump if flags |
|
(Jump If Above/Jump If Not Below or Equal) |
CF=0 AND ZF=0 |
||
JAE/JNB d |
(Jump If Above or Equal/Jump If Not Below) |
CF=0 |
|
JB/JNAE d |
(Jump If Below/Jump If Not Above or Equal) |
CF=1 |
|
JBE/JNA d |
(Jump If Below or Equal/Jump If Not Above) |
CF=1 OR ZF=1 |
|
JE/JZ |
d |
(Jump If Equal/Jump If Zero) |
ZF=1 |
JNE/JNZ d |
(Jump If Not Equal/Jump If Not Zero) |
ZF=0 |
|
JG/JNLE d |
(Jump If Greater/Jump If Not Less or Equal) |
ZF=0 OR SF=OF |
|
JGE/JNL d |
(Jump If Greater or Equal/Jump If Not Less) |
SF=OF |
|
JL/JNGE d |
(Jump If Less/Jump If Not Greater or Equal) |
SFOF |
|
JLE/JNG d |
(Jump If Less or Equal/Jump If Not Greater) |
ZF=1 OR SFOF |
|
JC |
d |
(Jump If Carry flag set) |
CF=1 |
JNC |
d |
(Jump If Carry flag Not set) |
CF=0 |
JO |
d |
(Jump If Overflow flag set) |
OF=1 |
JNO |
d |
(Jump If Overflow flag Not set) |
OF=0 |
JP/JPE |
d |
(Jump If PF set/Jump if Parity Even) |
PF=1 |
JNP/JPO d |
(Jump If PF Not set/Jump if Parity Odd) |
PF=0 |
|
JS |
d |
(Jump If Sign flag set) |
SF=1 |
JNS |
d |
(Jump If Sign flag Not set) |
SF=0 |
d without NEAR = 8-bit signed displacement; use NEAR before d to specif segment-wide displacement.
Examples:
JB HalfSplit |
;Jumps if CF=1 |
|
JLE TooLow |
;Jumps if either ZF=1 or SFOF |
|
JG NEAR WayOut |
;Jumps if |
greater to 16-bit displacement |
|
; in real |
mode or 32-bit displacement in |
|
; 32-bit protected mode. |
Notes:
By default all these instructions make a short jump (127 bytes forward or 128 bytes back) if some condition is true, or fall through if the condition is not true. The conditions all involve flags, and the flag conditions in question are given to the right of the mnemonic and its description.
The mnemonics incorporating "above" or "below" are for use after unsigned comparisons, whereas the mnemonics incorporating "less" or "greater" are for use after signed comparisons. "Equal" and "Zero" may be used after unsigned or signed comparisons.
NASM allows use of the segmentwide form by inserting the NEAR keyword after the instruction mnemonic. In real mode this allows the use of a 16-bit signed displacement, and in 32-bit protected mode this allows the use of a 32-bit signed displacement. Use of NEAR is only supported with 386 and newer CPUs.
r8 |
= |
AL |
AH |
BL |
BH |
CL |
CH |
DL DH |
r16 |
= |
AX BX CX DX |
BP SP SI DI |
ESI E |
sr |
= |
CS |
DS |
SS |
ES |
FS |
GS |
|
r32 |
= |
EAX EBX ECX |
EDX EBP ESP |
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 |
|
|
|
|
|
JCXZ Jump If CX = 0
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 |
|
|
|
<none> |
IF: Interrupt |
flag ZF: Zero |
flag |
CF: Carry flag |
Legal forms:
JCXZ <short displacement>
Examples:
JCXZ AllDone |
;Label AllDone must be within 127 bytes! |
Notes:
Many instructions use CX as a count register, and JCXZ allows you to test and jump to see if CX has become 0. The jump may only be a short jump (that is, no more than 127 bytes forward or 128 bytes back) and will be taken if CX = 0 at the time the instruction is executed. If CX is any other value than 0, execution falls through to the next instruction. See also the Jump on Condition instructions.
JCXZ is most often used to bypass the CX = 0 condition when using the LOOP instruction. Because LOOP decrements CX before testing for CX = 0, if you enter a loop governed by LOOP with CX = 0, you will end up iterating the loop 65,536 times, hence JCXZ.
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
JECXZ Jump If ECX = 0
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 |
|
|
|
<none> |
IF: Interrupt |
flag ZF: Zero |
flag |
CF: Carry flag |
Legal forms:
JECXZ <short displacement> |
386+ |
Examples:
JECXZ AllDone ;Label AllDone must be within 127 bytes!
Notes:
This instruction operates identically to JCXZ, except that the register tested is ECX, and not CX.
JECXZ is most often used to bypass the ECX = 0 condition when using the LOOP instruction. Because LOOP decrements ECX before testing for ECX = 0, if you enter a loop governed by LOOP with ECX = 0, you will end up iterating the loop 2,147,483,648 times, hence JECXZ.
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