by Rajesh Kothandapani
Instruction formats
GENERAL INSTRUCTION FORMAT
All Intel Architecture instruction encoding are subsets of the general instruction format shown in Figure 2-1. Instructions consist of optional instruction prefixes (in any order), one or two primary opcode bytes, an addressing-form specifier (if required) consisting of the ModR/M byte and sometimes the SIB (Scale-Index-Base) byte, a displacement (if required), and an immediate data field (if required).
Generalities:
-- Many (most?) of the instructions have exactly 2 operands.If there are 2 operands, then one of them will be required to use register mode, and the other will have no restrictions on its addressing mode.
-- There are most often ways of specifying the same instruction for 8-, 16-, or 32-bit oeprands. I left out the 16-bit ones to reduce presentation of the instruction set. Note that on a 32-bit machine, with newly written code, the 16-bit form will never be used.
Meanings of the operand specifications:
reg - register mode operand, 32-bit register
reg8 - register mode operand, 8-bit register
r/m - general addressing mode, 32-bit
r/m8 - general addressing mode, 8-bit
immed - 32-bit immediate is in the instruction
immed8 - 8-bit immediate is in the instruction
m - symbol (label) in the instruction is the effective address
Data Movement
--------------------------
mov reg, r/m ; copy data
r/m, reg
reg, immed
r/m, immed
movsx reg, r/m8 ; sign extend and copy data
movzx reg, r/m8 ; zero extend and copy data
lea reg, m ; get effective address
(A newer instruction, so its format is much restricted over the other ones.)
EXAMPLES:
mov EAX, 23 ; places 32-bit 2's complement immediate 23
; into register EAX
movsx ECX, AL ; sign extends the 8-bit quantity in register
; AL to 32 bits, and places it in ECX
mov [esp], -1 ; places value -1 into memory, address given
; by contents of esp
lea EBX, loop_top ; put the address assigned (by the assembler)
; to label loop_top into register EBX
Integer Arithmetic
-----------------------------
add reg, r/m ; two's complement addition
r/m, reg
reg, immed
r/m, immed
inc reg ; add 1 to operand
r/m
sub reg, r/m ; two's complement subtraction
r/m, reg
reg, immed
r/m, immed
dec reg ; subtract 1 from operand
r/m
neg r/m ; get additive inverse of operand
mul eax, r/m ; unsigned multiplication
; edx||eax <- data-blogger-escaped--="" data-blogger-escaped-2="" data-blogger-escaped-based="" data-blogger-escaped-before="" data-blogger-escaped-cmp="" data-blogger-escaped-comp.="" data-blogger-escaped-complement="" data-blogger-escaped-div="" data-blogger-escaped-division="" data-blogger-escaped-does="" data-blogger-escaped-eax="" data-blogger-escaped-edx="" data-blogger-escaped-eflags="" data-blogger-escaped-extends="" data-blogger-escaped-first="" data-blogger-escaped-idiv="" data-blogger-escaped-immed8="" data-blogger-escaped-immed="" data-blogger-escaped-imul="" data-blogger-escaped-m8="" data-blogger-escaped-m="" data-blogger-escaped-multiplication="" data-blogger-escaped-on="" data-blogger-escaped-operand="" data-blogger-escaped-quotient="" data-blogger-escaped-r="" data-blogger-escaped-reg="" data-blogger-escaped-remainder="" data-blogger-escaped-s="" data-blogger-escaped-second="" data-blogger-escaped-sets="" data-blogger-escaped-sign="" data-blogger-escaped-span="" data-blogger-escaped-subtract="" data-blogger-escaped-unsigned="" style="font-weight: bold;">EXAMPLES:
neg [eax + 4] ; takes doubleword at address eax+4
; and finds its additive inverse, then places
; the additive inverse back at that address
; the instruction should probably be
; neg dword ptr [eax + 4]
inc ecx ; adds one to contents of register ecx, and
; result goes back to ecx
Logical
--------------
not r/m ; logical not
and reg, r/m ; logical and
reg8, r/m8
r/m, reg
r/m8, reg8
r/m, immed
r/m8, immed8
or reg, r/m ; logical or
reg8, r/m8
r/m, reg
r/m8, reg8
r/m, immed
r/m8, immed8
xor reg, r/m ; logical exclusive or
reg8, r/m8
r/m, reg
r/m8, reg8
r/m, immed
r/m8, immed8
test r/m, reg ; logical and to set EFLAGS
r/m8, reg8
r/m, immed
r/m8, immed8
EXAMPLES:
and edx, 00330000h ; logical and of contents of register
; edx (bitwise) with 0x00330000,
; result goes back to edx
Floating Point Arithmetic
--------------------------------
Since the newer architectures have room for floating point hardware on chip, Intel defined a simple-to-implement extension to the architecture to do floating point arithmetic. In their usual zeal, they have included MANY instructions to do floating point operations.
The mechanism is simple. A set of 8 registers are organized and maintained (by hardware) as a stack of floating point values. ST refers to the stack top. ST(1) refers to the register within the stack that is next to ST. ST and ST(0) are synonyms.
There are separate instructions to test and compare the values of floating point variables.
finit ; initialize the FPU
fld m32 ; load floating point value
m64
ST(i)
fldz ; load floating point value 0.0
fst m32 ; store floating point value
m64
ST(i)
fstp m32 ; store floating point value
m64 ; and pop ST
ST(i)
fadd m32 ; floating point addition
m64
ST, ST(i)
ST(i), ST
faddp ST(i), ST ; floating point addition
; and pop ST
ETC.
I/O
------
The only instructions which actually allow the reading and writing of I/O devices are priviledged. The OS must handle these things. But, in writing programs that do something useful, we need input and output. Therefore, there are some simple macros defined to help us do I/O.
These are used just like instructions.
put_ch r/m ; print character in the least significant
; byte of 32-bit operand
get_ch r/m ; character will be in AL
put_str m ; print null terminated string given
; by label m
Control Instructions
-------------------------
These are the same control instructions that all started with the character 'b' in SASM.
jmp m ; unconditional jump
jg m ; jump if greater than 0
jge m ; jump if greater than or equal to 0
jl m ; jump if less than 0
jle m ; jump if less than or equal to 0
INSTRUCTION PREFIXES
The instruction prefixes are divided into four groups, each with a set of allowable prefix codes:
· Lock and repeat prefixes.
— F0H—LOCK prefix.
— F2H—REPNE/REPNZ prefix (used only with string instructions).
— F3H—REP prefix (used only with string instructions).
— F3H—REPE/REPZ prefix (used only with string instructions).
— F3H—Streaming SIMD Extensions prefix.
· Segment override.
— 2EH—CS segment override prefix.
— 36H—SS segment override prefix.
— 3EH—DS segment override prefix.
— 26H—ES segment override prefix.
— 64H—FS segment override prefix.
— 65H—GS segment override prefix.
· Operand-size override, 66H
· Address-size override, 67H
For each instruction, one prefix may be used from each of these groups and be placed in any order. The effect of redundant prefixes (more than one prefix from a group) is undefined and may vary from processor to processor.
· Streaming SIMD Extensions prefix, 0FH
The nature of Streaming SIMD Extensions allows the use of existing instruction formats. Instructions use the ModR/M format and are preceded by the 0F prefix byte. In general, operations are not duplicated to provide two directions (i.e. separate load and store variants).
OPCODE
The primary OPCODE is either 1 or 2 bytes. An additional 3-bit OPCODE field is sometimes encoded in the ModR/M byte. Smaller encoding fields can be defined within the primary OPCODE. These fields define the direction of the operation, the size of displacements, the register encoding, condition codes, or sign extension. The encoding of fields in the OPCODE varies, depending on the class of operation.
MODR/M AND SIB BYTES
Most instructions that refer to an operand in memory have an addressing-form specifier byte (called the ModR/M byte) following the primary OPCODE. The ModR/M byte contains three fields of information:
· The mod field combines with the r/m field to form 32 possible values: eight registers and 24 addressing modes.
· The reg/opcode field specifies either a register number or three more bits of opcode information. The purpose of the reg/opcode field is specified in the primary opcode.
· The r/m field can specify a register as an operand or can be combined with the mod field to encode an addressing mode.
Certain encoding of the ModR/M byte require a second addressing byte, the SIB byte, to fully specify the addressing form. The base-plus-index and scale-plus-index forms of 32-bit addressing require the SIB byte. The SIB byte includes the following fields:
· The scale field specifies the scale factor.
· The index field specifies the register number of the index register.
· The base field specifies the register number of the base register.
DISPLACEMENT AND IMMEDIATE BYTES
Some addressing forms include a displacement immediately following either the ModR/M or SIB byte. If a displacement is required, it can be 1, 2, or 4 bytes. If the instruction specifies an immediate operand, the operand always follows any displacement bytes. An immediate operand can be 1, 2, or 4 bytes.
CMC—Complement Carry Flag
OPCODE COLUMN
The “OPCODE” column gives the complete object code produced for each form of the instruction. When possible, the codes are given as hexadecimal bytes, in the same order in which they appear in memory. Definitions of entries other than hexadecimal bytes are as follows:
• /digit—A digit between 0 and 7 indicates that the ModR/M byte of the instruction uses
only the r/m (register or memory) operand. The reg field contains the digit that provides an extension to the instruction's opcode.
• /r—Indicates that the ModR/M byte of the instruction contains both a register operand and an r/m operand.
• cb, cw, cd, cp—A 1-byte (cb), 2-byte (cw), 4-byte (cd), or 6-byte (cp) value following the opcode that is used to specify a code offset and possibly a new value for the code segment register.
• ib, iw, id—A 1-byte (ib), 2-byte (iw), or 4-byte (id) immediate operand to the instruction
that follows the opcode, ModR/M bytes or scale-indexing bytes. The opcode determines if the operand is a signed value. All words and double words are given with the low-order
byte first.
• +rb, +rw, +rd—A register code, from 0 through 7, added to the hexadecimal byte given at the left of the plus sign to form a single opcode byte.
• +i—A number used in floating-point instructions when one of the operands is ST(i) from
the FPU register stack. The number i (which can range from 0 to 7) is added to the
hexadecimal byte given at the left of the plus sign to form a single opcode byte.
Opcode Instruction Description
F5 CMC Complement carry flag
INSTRUCTION COLUMN
The “Instruction” column gives the syntax of the instruction statement as it would appear in an ASM386 program. The following is a list of the symbols used to represent operands in the instruction statements:
• rel8—A relative address in the range from 128 bytes before the end of the instruction to 127 bytes after the end of the instruction.
• rel16 and rel32—A relative address within the same code segment as the instruction
assembled. The rel16 symbol applies to instructions with an operand-size attribute of 16
bits; the rel32 symbol applies to instructions with an operand-size attribute of 32 bits.
• ptr16:16 and ptr16:32—A far pointer, typically in a code segment different from that of
the instruction. The notation 16:16 indicates that the value of the pointer has two parts. The value to the left of the colon is a 16-bit selector or value destined for the code segment register. The value to the right corresponds to the offset within the destination segment. The ptr16:16 symbol is used when the instruction's operand-size attribute is 16 bits; the ptr16:32 symbol is used when the operand-size attribute is 32 bits.
• r8—One of the byte general-purpose registers AL, CL, DL, BL, AH, CH, DH, or BH.
• r16—One of the word general-purpose registers AX, CX, DX, BX, SP, BP, SI, or DI.
• r32—One of the doubleword general-purpose registers EAX, ECX, EDX, EBX, ESP, EBP,ESI, or EDI.
• imm8—An immediate byte value. The imm8 symbol is a signed number between –128
and +127 inclusive. For instructions in which imm8 is combined with a word or
double word operand, the immediate value is sign-extended to form a word or double word. The upper byte of the word is filled with the topmost bit of the immediate value.
• imm16—An immediate word value used for instructions whose operand-size attribute is 16 bits. This is a number between –32,768 and +32,767 inclusive.
• imm32—An immediate double word value used for instructions whose operand-size
attribute is 32 bits. It allows the use of a number between +2,147,483,647 and
–2,147,483,648 inclusive.
• r/m8—A byte operand that is either the contents of a byte general-purpose register (AL,BL, CL, DL, AH, BH, CH, and DH), or a byte from memory.
• r/m16—A word general-purpose register or memory operand used for instructions whose operand-size attribute is 16 bits. The word general-purpose registers are: AX, BX, CX,DX, SP, BP, SI, and DI. The contents of memory are found at the address provided by the effective address computation.
• r/m32—A double word general-purpose register or memory operand used for instructions whose operand-size attribute is 32 bits. The double word general-purpose registers are :EAX, EBX, ECX, EDX, ESP, EBP, ESI, and EDI. The contents of memory are found at the address provided by the effective address computation.
• m—A 16- or 32-bit operand in memory.
• m8—A byte operand in memory, usually expressed as a variable or array name, but
pointed to by the DS:(E)SI or ES:(E)DI registers. This nomenclature is used only with the
string instructions and the XLAT instruction.
• m16—A word operand in memory, usually expressed as a variable or array name, but
pointed to by the DS:(E)SI or ES:(E)DI registers. This nomenclature is used only with the
string instructions.
• m32—A double word operand in memory, usually expressed as a variable or array name, but pointed to by the DS:(E)SI or ES:(E)DI registers. This nomenclature is used only with the string instructions.
• m64—A memory quadword operand in memory. This nomenclature is used only with the CMPXCHG8B instruction.
• m128—A memory double quadword operand in memory. This nomenclature is used only with the Streaming SIMD Extensions.
• m16:16, m16:32—A memory operand containing a far pointer composed of two numbers. The number to the left of the colon corresponds to the pointer's segment selector. The number to the right corresponds to its offset.
• m16&32, m16&16, m32&32—A memory operand consisting of data item pairs whose
sizes are indicated on the left and the right side of the ampersand. All memory addressing modes are allowed. The m16&16 and m32&32 operands are used by the BOUND instruction to provide an operand containing an upper and lower bounds for array indices. The m16&32 operand is used by LIDT and LGDT to provide a word with which to load the limit field, and a double word with which to load the base field of the corresponding GDTR and IDTR registers.
• moffs8, moffs16, moffs32—A simple memory variable (memory offset) of type byte,
word, or double word used by some variants of the MOV instruction. The actual address is given by a simple offset relative to the segment base. No ModR/M byte is used in the
instruction. The number shown with moffs indicates its size, which is determined by the
address-size attribute of the instruction.
• Sreg—A segment register. The segment register bit assignments are ES=0, CS=1, SS=2,DS=3, FS=4, and GS=5.
• m32real, m64real, m80real—A single-, double-, and extended-real (respectively)
floating-point operand in memory.
• m16int, m32int, m64int—A word-, short-, and long-integer (respectively) floating-point
operand in memory.
• ST or ST(0)—The top element of the FPU register stack.
• ST(i)—The i th element from the top of the FPU register stack. (i = 0 through 7)
• mm—An MMX™ technology register. The 64-bit MMX™ technology registers are:
MM0 through MM7.
• xmm—A SIMD floating-point register. The 128-bit SIMD floating-point registers are:
XMM0 through XMM7.
• mm/m32—The low order 32 bits of an MMX™ technology register or a 32-bit memory
operand. The 64-bit MMX™ technology registers are: MM0 through MM7. The contents
of memory are found at the address provided by the effective address computation.
• mm/m64—An MMX™ technology register or a 64-bit memory operand. The 64-bit
MMX™ technology registers are: MM0 through MM7. The contents of memory are found
at the address provided by the effective address computation.
• xmm/m32—A SIMD floating-points register or a 32-bit memory operand. The 128-bit
SIMD floating-point registers are XMM0 through XMM7. The contents of memory are
found at the address provided by the effective address computation.
• xmm/m64—A SIMD floating-point register or a 64-bit memory operand. The 64-bit
SIMD floating-point registers are XMM0 through XMM7. The contents of memory are
found at the address provided by the effective address computation.
• xmm/m128—A SIMD floating-point register or a 128-bit memory operand. The 128-bit
SIMD floating-point registers are XMM0 through XMM7. The contents of memory are
found at the address provided by the effective address computation.
DESCRIPTION COLUMN
The “Description” column following the “Instruction” column briefly explains the various
forms of the instruction. The following “Description” and “Operation” sections contain more details of the instruction's operation.
DESCRIPTION
The “Description” section describes the purpose of the instructions and the required operands. It also discusses the effect of the instruction on flags.
Operation
The “Operation” section contains an algorithmic description (written in pseudo-code) of the instruction. The pseudo-code uses a notation similar to the Algol or Pascal language. The algorithms are composed of the following elements:
• Comments are enclosed within the symbol pairs “(*” and “*)”.
• Compound statements are enclosed in keywords, such as IF, THEN, ELSE, and FI for an if statement, DO and OD for a do statement, or CASE ... OF and ESAC for a case statement.
• A register name implies the contents of the register. A register name enclosed in brackets implies the contents of the location whose address is contained in that register. For example, ES:[DI] indicates the contents of the location whose ES segment relative address is in register DI. [SI] indicates the contents of the address contained in register SI relative to SI’s default segment (DS) or overridden segment.
• Parentheses around the “E” in a general-purpose register name, such as (E)SI, indicates that an offset is read from the SI register if the current address-size attribute is 16 or is read from the ESI register if the address-size attribute is 32.
• Brackets are also used for memory operands, where they mean that the contents of the
memory location is a segment-relative offset. For example, [SRC] indicates that the
contents of the source operand is a segment-relative offset.
• A ¬ B; indicates that the value of B is assigned to A.
• The symbols =, ¹, ³, and £ are relational operators used to compare two values, meaning equal, not equal, greater or equal, less or equal, respectively. A relational expression such as A = B is TRUE if the value of A is equal to B; otherwise it is FALSE.
• The expression “<<>> COUNT” indicates that the destination operand
should be shifted left or right, respectively, by the number of bits indicated by the count
operand. The following identifiers are used in the algorithmic descriptions:
• OperandSize and AddressSize—The OperandSize identifier represents the operand-size attribute of the instruction, which is either 16 or 32 bits. The AddressSize identifier
represents the address-size attribute, which is either 16 or 32 bits. For example, the
following pseudo-code indicates that the operand-size attribute depends on the form of the CMPS instruction used.
IF instruction = CMPSW
THEN OperandSize ¬ 16;
ELSE
IF instruction = CMPSD
THEN OperandSize ¬ 32;
FI;
FI;
StackAddrSize—Represents the stack address-size attribute associated with the
instruction, which has a value of 16 or 32 bits.
• SRC—Represents the source operand.
• DEST—Represents the destination operand.
The following functions are used in the algorithmic descriptions:
• ZeroExtend(value)—Returns a value zero-extended to the operand-size attribute of the instruction. For example, if the operand-size attribute is 32, zero extending a byte value of –10 converts the byte from F6H to a doubleword value of 000000F6H. If the value passed to the ZeroExtend function and the operand-size attribute are the same size, ZeroExtend returns the value unaltered.
• SignExtend(value)—Returns a value sign-extended to the operand-size attribute of the instruction. For example, if the operand-size attribute is 32, sign extending a byte
containing the value –10 converts the byte from F6H to a doubleword value of
FFFFFFF6H. If the value passed to the SignExtend function and the operand-size attribute are the same size, SignExtend returns the value unaltered.
• SaturateSignedWordToSignedByte—Converts a signed 16-bit value to a signed 8-bit
value. If the signed 16-bit value is less than –128, it is represented by the saturated value –128 (80H); if it is greater than 127, it is represented by the saturated value 127 (7FH).
• SaturateSignedDwordToSignedWord—Converts a signed 32-bit value to a signed 16-bit value. If the signed 32-bit value is less than –32768, it is represented by the saturated value –32768 (8000H); if it is greater than 32767, it is represented by the saturated value 32767 (7FFFH).
• SaturateSignedWordToUnsignedByte—Converts a signed 16-bit value to an unsigned 8-bit value. If the signed 16-bit value is less than zero, it is represented by the saturated value zero (00H); if it is greater than 255, it is represented by the saturated value 255 (FFH).
• SaturateToSignedByte—Represents the result of an operation as a signed 8-bit value. If the result is less than –128, it is represented by the saturated value –128 (80H); if it is greater than 127, it is represented by the saturated value 127 (7FH).
• SaturateToSignedWord—Represents the result of an operation as a signed 16-bit value. If the result is less than –32768, it is represented by the saturated value –32768 (8000H); if it is greater than 32767, it is represented by the saturated value 32767 (7FFFH).
• SaturateToUnsignedByte—Represents the result of an operation as a signed 8-bit value. If the result is less than zero it is represented by the saturated value zero (00H); if it is greater than 255, it is represented by the saturated value 255 (FFH).
SaturateToUnsignedWord—Represents the result of an operation as a signed 16-bit
value. If the result is less than zero it is represented by the saturated value zero (00H); if it is greater than 65535, it is represented by the saturated value 65535 (FFFFH).
• LowOrderWord(DEST * SRC)—Multiplies a word operand by a word operand and
stores the least significant word of the doubleword result in the destination operand.
• HighOrderWord(DEST * SRC)—Multiplies a word operand by a word operand and
stores the most significant word of the doubleword result in the destination operand.
• Push(value)—Pushes a value onto the stack. The number of bytes pushed is determined by the operand-size attribute of the instruction. Refer to the “Operation” section in “PUSH—Push Word or Doubleword Onto the Stack” in this chapter for more information on the push operation.
• Pop() removes the value from the top of the stack and returns it. The statement EAX ¬
Pop(); assigns to EAX the 32-bit value from the top of the stack. Pop will return either a
word or a doubleword depending on the operand-size attribute. Refer to the “Operation”
section in “POP—Pop a Value from the Stack” in this chapter for more information on the
pop operation.
• PopRegisterStack—Marks the FPU ST(0) register as empty and increments the FPU
register stack pointer (TOP) by 1.
• Switch-Tasks—Performs a task switch.
• Bit(BitBase, BitOffset)—Returns the value of a bit within a bit string, which is a sequence of bits in memory or a register. Bits are numbered from low-order to high-order within registers and within memory bytes. If the base operand is a register, the offset can be in the range 0..31. This offset addresses a bit within the indicated register.