# -'- coding: utf-8 -'-
import collections, struct
from .instruction import Instruction, RelBranchInstruction
# Procedure management instructions
#----------------------------------------
[docs]class push(Instruction):
"""Decrements the stack pointer and then stores the source operand on the
top of the stack.
=============== ====== ====== ======================================
src 32-bit 64-bit description
=============== ====== ====== ======================================
r/m8 X X Push src onto stack
r/m16 X X
r/m32 X
r/m64 X
imm8/32 X X
=============== ====== ====== ======================================
"""
name = 'push'
modes = {
('r/m16',): ['ff /6', 'm', True, True],
('r/m32',): ['ff /6', 'm', False, True],
('r/m64',): ['ff /6', 'm', True, False],
('r16',): ['50+rw', 'o', True, True],
('r32',): ['50+rd', 'o', False, True],
('r64',): ['50+rd', 'o', True, False],
('imm8',): ['6a ib', 'i', True, True],
#('imm16',): ['68 iw', 'i', True, True], # gnu as does not use this
('imm32',): ['68 id', 'i', True, True],
}
operand_enc = {
'm': ['ModRM:r/m (r)'],
'o': ['opcode +rd (r)'],
'i': ['imm8/16/32'],
}
def __init__(self, src): # set method signature
Instruction.__init__(self, src)
[docs]class pop(Instruction):
"""Loads the value from the top of the stack to the location specified with
the destination operand (or explicit opcode) and then increments the stack
pointer.
The destination operand can be a general-purpose register, memory location,
or segment register.
=============== ====== ====== ======================================
dst 32-bit 64-bit description
=============== ====== ====== ======================================
r/m8 X X Pop value from stack into dst
r/m16 X X
r/m32 X
r/m64 X
=============== ====== ====== ======================================
"""
name = 'pop'
modes = {
('r/m16',): ['8f /0', 'm', True, True],
('r/m32',): ['8f /0', 'm', False, True],
('r/m64',): ['8f /0', 'm', True, False],
('r16',): ['58+rw', 'o', True, True],
('r32',): ['58+rd', 'o', False, True],
('r64',): ['58+rd', 'o', True, False],
}
operand_enc = {
'm': ['ModRM:r/m (r)'],
'o': ['opcode +rd (r)'],
}
def __init__(self, dst): # set method signature
Instruction.__init__(self, dst)
[docs]class ret(Instruction):
""" RET
Return; pop a value from the stack and branch to that address.
Optionally, extra values may be popped from the stack after the return
address.
=============== ====== ====== ======================================
size 32-bit 64-bit description
=============== ====== ====== ======================================
(no operands) X X Return without touching stack
imm16 X X Pop *size* bytes from stack and return
=============== ====== ====== ======================================
"""
name = 'ret'
modes = collections.OrderedDict([
(('imm16',), ['c2 iw', 'i', True, True]),
((), ['c3', None, True, True]),
])
operand_enc = {
'i': ['imm16'],
}
[docs]class leave(Instruction):
""" LEAVE
High-level procedure exit. Accepts no operands.
Equivalent to::
mov(esp, ebp)
pop(ebp)
"""
name = 'leave'
modes = collections.OrderedDict([
((), ['c9', None, True, True]),
])
def __init__(self): # set method signature
Instruction.__init__(self)
[docs]class call(RelBranchInstruction):
"""Saves procedure linking information on the stack and branches to the
called procedure specified using the target operand.
The target operand specifies the address of the first instruction in the
called procedure. The operand can be an immediate value, a general-purpose
register, or a memory location.
=============== ====== ====== =============================================
dst 32-bit 64-bit description
=============== ====== ====== =============================================
rel32 X X Call address relative to this instruction
r/m16 X Call absolute address stored at r/m16/32/64
r/m32 X
r/m64 X
=============== ====== ====== =============================================
"""
name = "call"
# generate absolute call
modes = {
#('rel16',): ['e8', 'm', False, True],
('rel32',): ['e8', 'i', True, True],
('r/m16',): ['ff /2', 'm', False, True],
('r/m32',): ['ff /2', 'm', False, True],
('r/m64',): ['ff /2', 'm', True, False],
}
operand_enc = {
'm': ['ModRM:r/m (r)'],
'i': ['imm32'],
}
def __init__(self, addr): # set method signature
RelBranchInstruction.__init__(self, addr)
# Data moving instructions
#----------------------------------------
[docs]class mov(Instruction):
"""Copies the second operand (source operand) to the first operand
(destination operand).
The source operand can be an immediate value, general-purpose register,
segment register, or memory location; the destination register can be a
general-purpose register, segment register, or memory location. Both
operands must be the same size, which can be a byte, a word, a doubleword,
or a quadword.
====== ================= ====== ====== ======================================
dst src 32-bit 64-bit description
====== ================= ====== ====== ======================================
r/m8 r/m8, imm8 X X Copy src value to dst
r/m16 r/m16, imm16 X X
r/m32 r/m32, imm32 X X
r/m64 r/m64, imm32 X
r64 imm64 X
====== ================= ====== ====== ======================================
"""
name = 'mov'
modes = collections.OrderedDict([
(('r/m8', 'r8'), ['88 /r', 'mr', True, True]),
(('r/m16', 'r16'), ['89 /r', 'mr', True, True]),
(('r/m32', 'r32'), ['89 /r', 'mr', True, True]),
(('r/m64', 'r64'), ['REX.W + 89 /r', 'mr', True, False]),
(('r8', 'r/m8'), ['8a /r', 'rm', True, True]),
(('r16', 'r/m16'), ['8b /r', 'rm', True, True]),
(('r32', 'r/m32'), ['8b /r', 'rm', True, True]),
(('r64', 'r/m64'), ['REX.W + 8b /r', 'rm', True, False]),
(('r8', 'imm8'), ['b0+rb', 'oi', True, True]),
(('r16', 'imm16'), ['b8+rw', 'oi', True, True]),
(('r32', 'imm32'), ['b8+rd', 'oi', True, True]),
(('r64', 'imm64'), ['REX.W + b8+rq', 'oi', True, False]),
(('r/m8', 'imm8'), ['c6 /0', 'mi', True, True]),
(('r/m16', 'imm16'), ['c7 /0', 'mi', True, True]),
(('r/m32', 'imm32'), ['c7 /0', 'mi', True, True]),
(('r/m64', 'imm32'), ['REX.W + c7 /0', 'mi', True, False]),
])
operand_enc = {
'oi': ['opcode +rd (w)', 'imm8/16/32/64'],
'mi': ['ModRM:r/m (w)', 'imm8/16/32'],
'mr': ['ModRM:r/m (w)', 'ModRM:reg (r)'],
'rm': ['ModRM:reg (w)', 'ModRM:r/m (r)'],
}
def __init__(self, dst, src): # set method signature
Instruction.__init__(self, dst, src)
[docs]class movsd(Instruction):
"""MOVSD moves a scalar double-precision floating-point value from the
source operand (second operand) to the destination operand (first operand).
The source and destination operands can be XMM registers or 64-bit memory
locations. This instruction can be used to move a double-precision
floating-point value to and from the low quadword of an XMM register and a
64-bit memory location, or to move a double-precision floating-point value
between the low quadwords of two XMM registers. The instruction cannot be
used to transfer data between memory locations.
====== ================= ====== ====== ======================================
dst src 32-bit 64-bit description
====== ================= ====== ====== ======================================
xmm xmm, m64 X X Copy xmm or m64 to xmm
m64 xmm X X Copy xmm to m64
====== ================= ====== ====== ======================================
"""
name = 'movsd'
modes = collections.OrderedDict([
(('xmm1', 'xmm2/m64'), ['f20f10 /r', 'rm', True, True, 'sse2']),
(('m64', 'xmm1'), ['f20f11 /r', 'mr', True, True, 'sse2']),
])
operand_enc = {
'mr': ['ModRM:r/m (w)', 'ModRM:reg (r)'],
'rm': ['ModRM:reg (w)', 'ModRM:r/m (r)'],
}
def __init__(self, dst, src): # set method signature
Instruction.__init__(self, dst, src)
# Arithmetic instructions
#----------------------------------------
[docs]class add(Instruction):
"""Adds the destination operand (first operand) and the source operand
(second operand) and then stores the result in the destination operand.
The destination operand can be a register or a memory location; the source
operand can be an immediate, a register, or a memory location. (However,
two memory operands cannot be used in one instruction.) When an immediate
value is used as an operand, it is sign-extended to the length of the
destination operand format.
====== =============== ====== ====== ======================================
dst src 32-bit 64-bit description
====== =============== ====== ====== ======================================
r/m8 r/m8, imm8 X X dst += src
r/m16 r/m16, imm8/16 X X
r/m32 r/m32, imm8/32 X X
r/m64 r/m64, imm8/32 X
====== =============== ====== ====== ======================================
"""
name = 'add'
modes = collections.OrderedDict([
(('r/m8', 'imm8'), ['80 /0', 'mi', True, True]),
(('r/m16', 'imm16'), ['81 /0', 'mi', True, True]),
(('r/m32', 'imm32'), ['81 /0', 'mi', True, True]),
(('r/m64', 'imm32'), ['REX.W + 81 /0', 'mi', True, False]),
(('r/m16', 'imm8'), ['83 /0', 'mi', True, True]),
(('r/m32', 'imm8'), ['83 /0', 'mi', True, True]),
(('r/m64', 'imm8'), ['REX.W + 83 /0', 'mi', True, False]),
(('r/m8', 'r8'), ['00 /r', 'mr', True, True]),
(('r/m16', 'r16'), ['01 /r', 'mr', True, True]),
(('r/m32', 'r32'), ['01 /r', 'mr', True, True]),
(('r/m64', 'r64'), ['REX.W + 01 /r', 'mr', True, False]),
(('r8', 'r/m8'), ['02 /r', 'rm', True, True]),
(('r16', 'r/m16'), ['03 /r', 'rm', True, True]),
(('r32', 'r/m32'), ['03 /r', 'rm', True, True]),
(('r64', 'r/m64'), ['REX.W + 03 /r', 'rm', True, False]),
])
operand_enc = {
'mi': ['ModRM:r/m (r,w)', 'imm8/16/32'],
'mr': ['ModRM:r/m (r,w)', 'ModRM:reg (r)'],
'rm': ['ModRM:reg (r,w)', 'ModRM:r/m (r)'],
}
def __init__(self, dst, src): # set method signature
Instruction.__init__(self, dst, src)
[docs]class sub(Instruction):
"""Subtracts the second operand (source operand) from the first operand
(destination operand) and stores the result in the destination operand.
The destination operand can be a register or a memory location; the source
operand can be an immediate, register, or memory location. (However, two
memory operands cannot be used in one instruction.) When an immediate value
is used as an operand, it is sign-extended to the length of the destination
operand format.
====== =============== ====== ====== ======================================
dst src 32-bit 64-bit description
====== =============== ====== ====== ======================================
r/m8 r/m8, imm8 X X dst -= src
r/m16 r/m16, imm8/16 X X
r/m32 r/m32, imm8/32 X X
r/m64 r/m64, imm8/64 X
====== =============== ====== ====== ======================================
"""
name = 'sub'
modes = collections.OrderedDict([
(('r/m8', 'imm8'), ['80 /5', 'mi', True, True]),
(('r/m16', 'imm16'), ['81 /5', 'mi', True, True]),
(('r/m32', 'imm32'), ['81 /5', 'mi', True, True]),
(('r/m64', 'imm32'), ['REX.W + 81 /5', 'mi', True, False]),
(('r/m16', 'imm8'), ['83 /5', 'mi', True, True]),
(('r/m32', 'imm8'), ['83 /5', 'mi', True, True]),
(('r/m64', 'imm8'), ['REX.W + 85 /0', 'mi', True, False]),
(('r/m8', 'r8'), ['28 /r', 'mr', True, True]),
(('r/m16', 'r16'), ['29 /r', 'mr', True, True]),
(('r/m32', 'r32'), ['29 /r', 'mr', True, True]),
(('r/m64', 'r64'), ['REX.W + 29 /r', 'mr', True, False]),
(('r8', 'r/m8'), ['2a /r', 'rm', True, True]),
(('r16', 'r/m16'), ['2b /r', 'rm', True, True]),
(('r32', 'r/m32'), ['2b /r', 'rm', True, True]),
(('r64', 'r/m64'), ['REX.W + 2b /r', 'rm', True, False]),
])
operand_enc = {
'mi': ['ModRM:r/m (r,w)', 'imm8/16/32'],
'mr': ['ModRM:r/m (r,w)', 'ModRM:reg (r)'],
'rm': ['ModRM:reg (r,w)', 'ModRM:r/m (r)'],
}
def __init__(self, dst, src): # set method signature
Instruction.__init__(self, dst, src)
# NOTE: this is broken because lea uses a different interpretation of the 0x66
# and 0x67 prefixes.
[docs]class lea(Instruction):
"""Computes the effective address of the second operand (the source
operand) and stores it in the first operand (destination operand).
The source operand is a memory address (offset part) specified with one of
the processors addressing modes; the destination operand is a general-
purpose register.
========= =============== ====== ====== ======================================
dst src 32-bit 64-bit description
========= =============== ====== ====== ======================================
r16 m X X Store src address in dst.
r32 m X X
r64 m X
========= =============== ====== ====== ======================================
"""
name = "lea"
modes = collections.OrderedDict([
(('r16', 'm'), ['8d /r', 'rm', True, True]),
(('r32', 'm'), ['8d /r', 'rm', True, True]),
(('r64', 'm'), ['REX.W + 8d /r', 'rm', True, False]),
])
operand_enc = {
'rm': ['ModRM:reg (w)', 'ModRM:r/m (r)'],
}
def __init__(self, dst, src):
Instruction.__init__(self, dst, src)
[docs]class dec(Instruction):
"""Subtracts 1 from the destination operand, while preserving the state of
the CF flag.
The destination operand can be a register or a memory location. This
instruction allows a loop counter to be updated without disturbing the CF
flag. (To perform a decrement operation that updates the CF flag, use a SUB
instruction with an immediate operand of 1.)
====== ====== ====== ======================================
dst 32-bit 64-bit description
====== ====== ====== ======================================
r/m8 X X dst -= 1
r/m16 X X
r/m32 X X
r/m64 X
====== ====== ====== ======================================
"""
name = "dec"
modes = collections.OrderedDict([
(('r/m8',), ['fe /1', 'm', True, True]),
(('r/m16',), ['ff /1', 'm', True, True]),
(('r/m32',), ['ff /1', 'm', True, True]),
(('r/m64',), ['REX.W + ff /1', 'm', True, False]),
(('r16',), ['48+rw', 'o', False, True]),
(('r32',), ['48+rd', 'o', False, True]),
])
operand_enc = {
'm': ['ModRM:r/m (r,w)'],
'o': ['opcode +rd (r, w)'],
}
def __init__(self, dst): # set method signature
Instruction.__init__(self, dst)
[docs]class inc(Instruction):
"""Adds 1 to the destination operand, while preserving the state of the CF
flag.
The destination operand can be a register or a memory location. This
instruction allows a loop counter to be updated without disturbing the CF
flag. (Use a ADD instruction with an immediate operand of 1 to perform an
increment operation that does updates the CF flag.)
====== ====== ====== ======================================
dst 32-bit 64-bit description
====== ====== ====== ======================================
r/m8 X X dst += 1
r/m16 X X
r/m32 X X
r/m64 X
====== ====== ====== ======================================
"""
name = "inc"
modes = collections.OrderedDict([
(('r/m8',), ['fe /0', 'm', True, True]),
(('r/m16',), ['ff /0', 'm', True, True]),
(('r/m32',), ['ff /0', 'm', True, True]),
(('r/m64',), ['REX.W + ff /0', 'm', True, False]),
(('r16',), ['40+rw', 'o', False, True]),
(('r32',), ['40+rd', 'o', False, True]),
])
operand_enc = {
'm': ['ModRM:r/m (r,w)'],
'o': ['opcode +rd (r, w)'],
}
def __init__(self, dst): # set method signature
Instruction.__init__(self, dst)
[docs]class imul(Instruction):
"""Performs a signed multiplication of two operands. This instruction has
three forms, depending on the number of operands.
* One-operand form — **[Not currently supported by pycca]**
This form is identical to that used by the MUL
instruction. Here, the source operand (in a general-purpose register or
memory location) is multiplied by the value in the AL, AX, EAX, or RAX
register (depending on the operand size) and the product (twice the size
of the input operand) is stored in the AX, DX:AX, EDX:EAX, or RDX:RAX
registers, respectively.
* Two-operand form — With this form the destination operand (the first
operand) is multiplied by the source operand (second operand). The
destination operand is a general-purpose register and the source operand
is an immediate value, a general-purpose register, or a memory location.
The intermediate product (twice the size of the input operand) is
truncated and stored in the destination operand location.
====== =============== ====== ====== ======================================
dst src 32-bit 64-bit description
====== =============== ====== ====== ======================================
r16 r/m16 X X dst \*= src
r32 r/m32 X X
r64 r/m64 X
====== =============== ====== ====== ======================================
* Three-operand form — This form requires a destination operand (the first
operand) and two source operands (the second and the third operands).
Here, the first source operand (which can be a general-purpose register
or a memory location) is multiplied by the second source operand (an
immediate value). The intermediate product (twice the size of the first
source operand) is truncated and stored in the destination operand (a
general-purpose register).
====== ======= ======= ====== ====== ======================================
dst src1 src2 32-bit 64-bit description
====== ======= ======= ====== ====== ======================================
r16 r/m16 imm8/16 X X dst = src1 \* src2
r32 r/m32 imm8/32 X X
r64 r/m64 imm8/64 X
====== ======= ======= ====== ====== ======================================
"""
name = "imul"
modes = collections.OrderedDict([
(('r16', 'r/m16'), ['0faf /r', 'rm', True, True]),
(('r32', 'r/m32'), ['0faf /r', 'rm', True, True]),
(('r64', 'r/m64'), ['REX.W + 0faf /r', 'rm', True, False]),
(('r16', 'r/m16', 'imm8'), ['6b /r ib', 'rmi', True, True]),
(('r32', 'r/m32', 'imm8'), ['6b /r ib', 'rmi', True, True]),
(('r64', 'r/m64', 'imm8'), ['REX.W + 6b /r ib', 'rmi', True, False]),
(('r16', 'r/m16', 'imm16'), ['69 /r iw', 'rmi', True, True]),
(('r32', 'r/m32', 'imm32'), ['69 /r id', 'rmi', True, True]),
(('r64', 'r/m64', 'imm32'), ['REX.W + 69 /r id', 'rmi', True, False]),
])
operand_enc = {
'rm': ['ModRM:reg (r,w)', 'ModRM:r/m (r)'],
'rmi': ['ModRM:reg (r,w)', 'ModRM:r/m (r)', 'imm8/16/32'],
}
[docs]class idiv(Instruction):
"""Divides the (signed) value in the AX, DX:AX, or EDX:EAX (dividend) by
the source operand (divisor) and stores the result in the AX (AH:AL),
DX:AX, or EDX:EAX registers. The source operand can be a general-purpose
register or a memory location. The action of this instruction depends on
the operand size (dividend/divisor).
======= ====== ====== ======================================================
src 32-bit 64-bit description
======= ====== ====== ======================================================
r/m8 X X Divide AX by src, set AL=quotient, AH=remainder
r/m16 X X Divide DX:AX by src, set AX=quotient, DX=remainder
r/m32 X X Divide EDX:EAX by src, set EAX=quotient, EDX=remainder
r/m64 X Divide RDX:RAX by src, set RAX=quotient, RDX=remainder
======= ====== ====== ======================================================
"""
name = "idiv"
modes = collections.OrderedDict([
(('r/m8',), ('f6 /7', 'm', True, True)),
(('r/m16',), ('f7 /7', 'm', True, True)),
(('r/m32',), ('f7 /7', 'm', True, True)),
(('r/m64',), ('REX.W + f6 /7', 'm', True, False)),
])
operand_enc = {
'm': ['ModRM:r/m (r)'],
}
def __init__(self, src): # set method signature
Instruction.__init__(self, src)
[docs]class fld(Instruction):
"""Pushes the source operand onto the FPU register stack.
The source
operand can be in single-precision, double-precision, or double
extended-precision floating-point format. If the source operand is in
single-precision or double-precision floating-point format, it is
automatically converted to the double extended-precision floating-point
format before being pushed on the stack.
======= ====== ====== ======================================================
src 32-bit 64-bit description
======= ====== ====== ======================================================
m32 X X Push 32 bit float at src onto FPU stack
m64 X X Push 64 bit float at src onto FPU stack
m80 X X Push 80 bit float at src onto FPU stack
ST(i) X X Push float at ST(i) onto FPU stack
======= ====== ====== ======================================================
"""
name = 'fld'
modes = collections.OrderedDict([
(('m32fp',), ('d9 /0', 'm', True, True)),
(('m64fp',), ('dd /0', 'm', True, True)),
(('m80fp',), ('db /5', 'm', True, True)),
(('ST(i)',), ('d9c0+i', 'o', True, True)),
])
operand_enc = {
'm': ['ModRM:r/m (r)'],
'o': ['opcode +rd (r)'],
}
def __init__(self, src): # set method signature
Instruction.__init__(self, src)
[docs]class fst(Instruction):
"""The FST instruction copies the value in the ST(0) register to the
destination operand, which can be a memory location or another register in
the FPU register stack.
When storing the value in memory, the value is converted to
single-precision or double-precision floating-point format.
======= ====== ====== ======================================================
dst 32-bit 64-bit description
======= ====== ====== ======================================================
m32 X X Store ST(0) to 32 bit float at dst
m64 X X Store ST(0) to 64 bit float at dst
m80 X X Store ST(0) to 80 bit float at dst
ST(i) X Store ST(0) to ST(i)
======= ====== ====== ======================================================
"""
name = 'fst'
modes = collections.OrderedDict([
(('m32fp',), ('d9 /2', 'm', True, True)),
(('m64fp',), ('dd /2', 'm', True, True)),
(('m80fp',), ('db /7', 'm', True, True)),
(('ST(i)',), ('ddd0+i', 'o', True, True)),
])
operand_enc = {
'm': ['ModRM:r/m (r)'],
'o': ['opcode +rd (r)'],
}
def __init__(self, dst): # set method signature
Instruction.__init__(self, dst)
[docs]class fstp(Instruction):
"""The FSTP instruction performs the same operation as the FST instruction
and then pops the register stack.
To pop the register stack, the processor marks the ST(0) register as empty
and increments the stack pointer (TOP) by 1. The FSTP instruction can also
store values in memory in double extended-precision floating-point format.
======= ====== ====== ======================================================
dst 32-bit 64-bit description
======= ====== ====== ======================================================
m32 X X Pop ST(0) to 32 bit float at dst
m64 X X Pop ST(0) to 64 bit float at dst
m80 X X Pop ST(0) to 80 bit float at dst
ST(i) X Pop ST(0) to ST(i)
======= ====== ====== ======================================================
"""
name = 'fstp'
modes = collections.OrderedDict([
(('m32fp',), ('d9 /3', 'm', True, True)),
(('m64fp',), ('dd /3', 'm', True, True)),
(('m80fp',), ('db /7', 'm', True, True)),
(('ST(i)',), ('ddd8+i', 'o', True, True)),
])
operand_enc = {
'm': ['ModRM:r/m (r)'],
'o': ['opcode +rd (r)'],
}
def __init__(self, dst): # set method signature
Instruction.__init__(self, dst)
[docs]class fild(Instruction):
"""Converts the signed-integer source operand into double
extended-precision floating-point format and pushes the value onto the FPU
register stack.
The source operand can be a word, doubleword, or quadword integer. It is
loaded without rounding errors. The sign of the source operand is
preserved.
======= ====== ====== ======================================================
src 32-bit 64-bit description
======= ====== ====== ======================================================
m16 X X Push 16 bit int at src onto FPU stack
m32 X X Push 32 bit int at src onto FPU stack
m64 X X Push 64 bit int at src onto FPU stack
======= ====== ====== ======================================================
"""
name = 'fild'
modes = collections.OrderedDict([
(('m16int',), ('df /0', 'm', True, True)),
(('m32int',), ('db /0', 'm', True, True)),
(('m64int',), ('df /5', 'm', True, True)),
])
operand_enc = {
'm': ['ModRM:r/m (r)'],
}
def generate_code(self):
# Don't need 66h prefix for this instruction.
# todo: could this have been deduced from the 'm16int' sig?
if b'\x66' in self.prefixes:
self.prefixes.remove(b'\x66')
Instruction.generate_code(self)
def __init__(self, src): # set method signature
Instruction.__init__(self, src)
[docs]class fist(Instruction):
"""The FIST instruction converts the value in the ST(0) register to a
signed integer and stores the result in the destination operand.
Values can be stored in word or doubleword integer format. The destination
operand specifies the address where the first byte of the destination value
is to be stored.
======= ====== ====== ======================================================
dst 32-bit 64-bit description
======= ====== ====== ======================================================
m16 X X Store ST(0) to 16 bit signed int at dst
m32 X X Store ST(0) to 32 bit signed int at dst
======= ====== ====== ======================================================
"""
name = 'fist'
modes = collections.OrderedDict([
(('m16int',), ('df /2', 'm', True, True)),
(('m32int',), ('db /2', 'm', True, True)),
])
operand_enc = {
'm': ['ModRM:r/m (r)'],
}
def generate_code(self):
# Don't need 66h prefix for this instruction.
# todo: could this have been deduced from the 'm16int' sig?
if b'\x66' in self.prefixes:
self.prefixes.remove(b'\x66')
Instruction.generate_code(self)
def __init__(self, dst): # set method signature
Instruction.__init__(self, dst)
[docs]class fistp(Instruction):
"""The FISTP instruction performs the same operation as the FIST
instruction and then pops the register stack.
To pop the register stack, the processor marks the ST(0) register as empty
and increments the stack pointer (TOP) by 1. The FISTP instruction also
stores values in quadword integer format.
======= ====== ====== ======================================================
dst 32-bit 64-bit description
======= ====== ====== ======================================================
m16 X X Store ST(0) to 16 bit signed int at dst
m32 X X Store ST(0) to 32 bit signed int at dst
m64 X X Store ST(0) to 64 bit signed int at dst
======= ====== ====== ======================================================
"""
name = 'fistp'
modes = collections.OrderedDict([
(('m16int',), ('df /3', 'm', True, True)),
(('m32int',), ('db /3', 'm', True, True)),
(('m64int',), ('df /7', 'm', True, True)),
])
operand_enc = {
'm': ['ModRM:r/m (r)'],
}
def generate_code(self):
# Don't need 66h prefix for this instruction.
# todo: could this have been deduced from the 'm16int' sig?
if b'\x66' in self.prefixes:
self.prefixes.remove(b'\x66')
Instruction.generate_code(self)
def __init__(self, src): # set method signature
Instruction.__init__(self, src)
[docs]class fabs(Instruction):
"""Clears the sign bit of ST(0) to create the absolute value of the
operand. Accepts no operands.
"""
name = 'fabs'
modes = collections.OrderedDict([
((), ('d9e1', None, True, True))
])
def __init__(self): # set method signature
Instruction.__init__(self)
[docs]class fadd(Instruction):
"""Adds the destination and source operands and stores the sum in the
destination location.
The destination operand is always an FPU register; the source operand can
be a register or a memory location. Source operands in memory can be in
single-precision or double-precision floating-point format.
====== ======= ====== ====== ======================================================
dst src 32-bit 64-bit description
====== ======= ====== ====== ======================================================
m32 X X ST(0) += src
m64 X X
st(j) st(i) X X dst += src (at least one operand must be st(0))
====== ======= ====== ====== ======================================================
"""
name = 'fadd'
modes = collections.OrderedDict([
(('m32fp',), ('d8 /0', 'm', True, True)),
(('m64fp',), ('dc /0', 'm', True, True)),
(('st(0)', 'st(i)'), ('d8c0+i', '-o', True, True)),
(('st(i)', 'st(0)'), ('dcc0+i', 'o-', True, True)),
((), ('dec1', None, True, True)), # no-operand version is same as faddp
])
operand_enc = {
'm': ['ModRM:r/m (r)'],
'o-': ['opcode +rd (r)', None],
'-o': [None, 'opcode +rd (r)'],
}
[docs]class faddp(Instruction):
"""Adds the destination and source operands and stores the sum in the
destination location.
The FADDP instructions perform the additional operation of popping the FPU
register stack after storing the result. To pop the register stack, the
processor marks the ST(0) register as empty and increments the stack
pointer (TOP) by 1.
====== ======= ====== ====== ==============================================
dst src 32-bit 64-bit description
====== ======= ====== ====== ==============================================
st(i) st(0) X X dst += st(0), pop st(0) from FP stack
X X st(1) += st(0), pop st(0) from FP stack
====== ======= ====== ====== ==============================================
"""
name = 'faddp'
modes = collections.OrderedDict([
(('st(i)', 'st(0)'), ('dec0+i', 'o-', True, True)),
((), ('dec1', None, True, True)),
])
operand_enc = {
'o-': ['opcode +rd (r)', None],
}
[docs]class fiadd(Instruction):
"""The FIADD instructions are similar to FADD, but convert an integer
source operand to double extended-precision floating-point format before
performing the addition.
======= ====== ====== ======================================================
src 32-bit 64-bit description
======= ====== ====== ======================================================
m32 X X ST(0) += src
m64 X X
======= ====== ====== ======================================================
"""
name = 'fiadd'
modes = collections.OrderedDict([
(('m32int',), ('da /0', 'm', True, True)),
(('m16int',), ('de /0', 'm', True, True)),
])
operand_enc = {
'm': ['ModRM:r/m (r)'],
}
def generate_code(self):
# Don't need 66h prefix for this instruction.
# todo: could this have been deduced from the 'm16int' sig?
if b'\x66' in self.prefixes:
self.prefixes.remove(b'\x66')
Instruction.generate_code(self)
def __init__(self, src): # set method signature
Instruction.__init__(self, src)
[docs]class fsub(Instruction):
"""Subtracts the source operand from the destination operand and stores the
difference in the destination location. The destination operand is always
an FPU data register; the source operand can be a register or a memory
location. Source operands in memory can be in single-precision or
double-precision floating-point format.
====== ======= ====== ====== ================================================
dst src 32-bit 64-bit description
====== ======= ====== ====== ================================================
m32 X X ST(0) -= src
m64 X X
st(j) st(i) X X dst -= src (at least one operand must be st(0))
====== ======= ====== ====== ================================================
"""
name = 'fsub'
modes = collections.OrderedDict([
(('m32fp',), ('d8 /4', 'm', True, True)),
(('m64fp',), ('dc /4', 'm', True, True)),
(('st(0)', 'st(i)'), ('d8e0+i', '-o', True, True)),
(('st(i)', 'st(0)'), ('dce8+i', 'o-', True, True)),
((), ('dee9', None, True, True)), # no-operand version is same as fsubp
])
operand_enc = {
'm': ['ModRM:r/m (r)'],
'o-': ['opcode +rd (r)', None],
'-o': [None, 'opcode +rd (r)'],
}
[docs]class fsubp(Instruction):
"""The FSUBP instructions are similar to FSUB but perform the additional
operation of popping the FPU register stack following the subtraction. To
pop the register stack, the processor marks the ST(0) register as empty and
increments the stack pointer (TOP) by 1.
====== ======= ====== ====== ==============================================
dst src 32-bit 64-bit description
====== ======= ====== ====== ==============================================
st(i) st(0) X X dst -= st(0), pop st(0) from FP stack
X X st(1) -= st(0), pop st(0) from FP stack
====== ======= ====== ====== ==============================================
"""
name = 'fsubp'
modes = collections.OrderedDict([
(('st(i)', 'st(0)'), ('dee8+i', 'o-', True, True)),
((), ('dee9', None, True, True)),
])
operand_enc = {
'o-': ['opcode +rd (r)', None],
}
[docs]class fisub(Instruction):
"""Subtracts the source operand from the destination operand and stores the
difference in the destination location. The destination operand is always
an FPU data register; the source operand can be a register or a memory
location. Source operands in memory can be in word or doubleword integer
format.
======= ====== ====== ======================================================
src 32-bit 64-bit description
======= ====== ====== ======================================================
m32 X X ST(0) -= src
m64 X X
======= ====== ====== ======================================================
"""
name = 'fisub'
modes = collections.OrderedDict([
(('m32int',), ('da /4', 'm', True, True)),
(('m16int',), ('de /4', 'm', True, True)),
])
operand_enc = {
'm': ['ModRM:r/m (r)'],
}
def generate_code(self):
# Don't need 66h prefix for this instruction.
# todo: could this have been deduced from the 'm16int' sig?
if b'\x66' in self.prefixes:
self.prefixes.remove(b'\x66')
Instruction.generate_code(self)
def __init__(self, src): # set method signature
Instruction.__init__(self, src)
[docs]class fmul(Instruction):
"""Multiplies the destination and source operands and stores the product in
the destination location. The destination operand is always an FPU data
register; the source operand can be an FPU data register or a memory
location. Source operands in memory can be in single-precision or
double-precision floating-point format.
====== ======= ====== ====== =================================================
dst src 32-bit 64-bit description
====== ======= ====== ====== =================================================
m32 X X ST(0) \*= src
m64 X X
st(j) st(i) X X dst \*= src (at least one operand must be st(0))
====== ======= ====== ====== =================================================
"""
name = 'fmul'
modes = collections.OrderedDict([
(('m32fp',), ('d8 /1', 'm', True, True)),
(('m64fp',), ('dc /1', 'm', True, True)),
(('st(0)', 'st(i)'), ('d8c8+i', '-o', True, True)),
(('st(i)', 'st(0)'), ('dcc8+i', 'o-', True, True)),
((), ('dec9', None, True, True)), # no-operand version is same as fmulp
])
operand_enc = {
'm': ['ModRM:r/m (r)'],
'o-': ['opcode +rd (r)', None],
'-o': [None, 'opcode +rd (r)'],
}
[docs]class fmulp(Instruction):
"""The FMULP instructions are similar to FMUL but perform the additional
operation of popping the FPU register stack after storing the product. To
pop the register stack, the processor marks the ST(0) register as empty and
increments the stack pointer (TOP) by 1.
====== ======= ====== ====== ==============================================
dst src 32-bit 64-bit description
====== ======= ====== ====== ==============================================
st(i) st(0) X X dst \*= st(0), pop st(0) from FP stack
X X st(1) \*= st(0), pop st(0) from FP stack
====== ======= ====== ====== ==============================================
"""
name = 'fmulp'
modes = collections.OrderedDict([
(('st(i)', 'st(0)'), ('dec8+i', 'o-', True, True)),
((), ('dec9', None, True, True)),
])
operand_enc = {
'o-': ['opcode +rd (r)', None],
}
[docs]class fimul(Instruction):
"""Multiplies the destination and source operands and stores the product in
the destination location. The destination operand is always an FPU data
register; the source operand can be an FPU data register or a memory
location. Source operands in memory can be in word or doubleword integer
format.
======= ====== ====== ======================================================
src 32-bit 64-bit description
======= ====== ====== ======================================================
m32 X X ST(0) \*= src
m64 X X
======= ====== ====== ======================================================
"""
name = 'fimul'
modes = collections.OrderedDict([
(('m32int',), ('da /1', 'm', True, True)),
(('m16int',), ('de /1', 'm', True, True)),
])
operand_enc = {
'm': ['ModRM:r/m (r)'],
}
def generate_code(self):
# Don't need 66h prefix for this instruction.
# todo: could this have been deduced from the 'm16int' sig?
if b'\x66' in self.prefixes:
self.prefixes.remove(b'\x66')
Instruction.generate_code(self)
def __init__(self, src): # set method signature
Instruction.__init__(self, src)
[docs]class fdiv(Instruction):
"""Divides the destination operand by the source operand and stores the
result in the destination location. The destination operand (dividend) is
always in an FPU register; the source operand (divisor) can be a register
or a memory location. Source operands in memory can be in single-precision
or double-precision floating-point format.
====== ======= ====== ====== ================================================
dst src 32-bit 64-bit description
====== ======= ====== ====== ================================================
m32 X X ST(0) /= src
m64 X X
st(j) st(i) X X dst /= src (at least one operand must be st(0))
====== ======= ====== ====== ================================================
"""
name = 'fdiv'
modes = collections.OrderedDict([
(('m32fp',), ('d8 /6', 'm', True, True)),
(('m64fp',), ('dc /6', 'm', True, True)),
(('st(0)', 'st(i)'), ('d8f0+i', '-o', True, True)),
(('st(i)', 'st(0)'), ('dcf8+i', 'o-', True, True)),
((), ('def9', None, True, True)), # no-operand version is same as fmulp
])
operand_enc = {
'm': ['ModRM:r/m (r)'],
'o-': ['opcode +rd (r)', None],
'-o': [None, 'opcode +rd (r)'],
}
[docs]class fdivp(Instruction):
"""The FDIVP instructions are similar to FDIV but perform the additional
operation of popping the FPU register stack after storing the result. To
pop the register stack, the processor marks the ST(0) register as empty and
increments the stack pointer (TOP) by 1.
====== ======= ====== ====== ==============================================
dst src 32-bit 64-bit description
====== ======= ====== ====== ==============================================
st(i) st(0) X X dst /= st(0), pop st(0) from FP stack
X X st(1) /= st(0), pop st(0) from FP stack
====== ======= ====== ====== ==============================================
"""
name = 'fdivp'
modes = collections.OrderedDict([
(('st(i)', 'st(0)'), ('def8+i', 'o-', True, True)),
((), ('def9', None, True, True)),
])
operand_enc = {
'o-': ['opcode +rd (r)', None],
}
[docs]class fidiv(Instruction):
"""Divides the destination operand by the source operand and stores the
result in the destination location. The destination operand (dividend) is
always in an FPU register; the source operand (divisor) can be a register
or a memory location. Source operands in memory can be in word or
doubleword integer format.
======= ====== ====== ======================================================
src 32-bit 64-bit description
======= ====== ====== ======================================================
m32 X X ST(0) /= src
m64 X X
======= ====== ====== ======================================================
"""
name = 'fidiv'
modes = collections.OrderedDict([
(('m32int',), ('da /6', 'm', True, True)),
(('m16int',), ('de /6', 'm', True, True)),
])
operand_enc = {
'm': ['ModRM:r/m (r)'],
}
def generate_code(self):
# Don't need 66h prefix for this instruction.
# todo: could this have been deduced from the 'm16int' sig?
if b'\x66' in self.prefixes:
self.prefixes.remove(b'\x66')
Instruction.generate_code(self)
def __init__(self, src): # set method signature
Instruction.__init__(self, src)
[docs]class fcomi(Instruction):
"""Performs an unordered comparison of the contents of registers ST(0) and
ST(i) and sets the status flags ZF, PF, and CF in the EFLAGS register
according to the results (see the table below). The sign of zero is ignored
for comparisons, so that -0.0 is equal to +0.0.
================== ==== ==== ====
Comparison ZF PF CF
================== ==== ==== ====
st(0) > st(i) 0 0 0
st(0) < st(i) 0 0 1
st(0) = st(i) 1 0 0
unordered 1 1 1
================== ==== ==== ====
======= ====== ====== ====== ==============================================
src1 src2 32-bit 64-bit description
======= ====== ====== ====== ==============================================
st(0) st(i) X X
======= ====== ====== ====== ==============================================
"""
name = 'fcomi'
modes = collections.OrderedDict([
(('st(0)', 'st(i)'), ('dbf0+i', '-o', True, True)),
])
operand_enc = {
'-o': [None, 'opcode +rd (r)'],
}
def __init__(self, src1, src2): # set method signature
Instruction.__init__(self, src1, src2)
[docs]class fcomip(Instruction):
"""The FCOMIP instruction is similar to FCOMI but also pops the register
stack following the comparison operation. To pop the register stack, the
processor marks the ST(0) register as empty and increments the stack
pointer (TOP) by 1.
======= ====== ====== ====== ==============================================
src1 src2 32-bit 64-bit description
======= ====== ====== ====== ==============================================
st(0) st(i) X X
======= ====== ====== ====== ==============================================
"""
name = 'fcomip'
modes = collections.OrderedDict([
(('st(0)', 'st(i)'), ('dff0+i', '-o', True, True)),
])
operand_enc = {
'-o': [None, 'opcode +rd (r)'],
}
def __init__(self, src1, src2): # set method signature
Instruction.__init__(self, src1, src2)
[docs]class fucomi(Instruction):
"""The FUCOMI instruction performs the same operation as the FCOMI
instruction. The only difference is that the FUCOMI instruction raises the
invalid-arithmetic-operand exception (#IA) only when either or both
operands are an SNaN or are in an unsupported format; QNaNs cause the
condition code flags to be set to unordered, but do not cause an exception
to be generated.
======= ====== ====== ====== ==============================================
src1 src2 32-bit 64-bit description
======= ====== ====== ====== ==============================================
st(0) st(i) X X
======= ====== ====== ====== ==============================================
"""
name = 'fucomi'
modes = collections.OrderedDict([
(('st(0)', 'st(i)'), ('dbe8+i', '-o', True, True)),
])
operand_enc = {
'-o': [None, 'opcode +rd (r)'],
}
def __init__(self, src1, src2): # set method signature
Instruction.__init__(self, src1, src2)
[docs]class fucomip(Instruction):
"""The FUCOMIP instruction is similar to FUCOMI but also pops the register
stack following the comparison operation. To pop the register stack, the
processor marks the ST(0) register as empty and increments the stack
pointer (TOP) by 1.
======= ====== ====== ====== ==============================================
src1 src2 32-bit 64-bit description
======= ====== ====== ====== ==============================================
st(0) st(i) X X
======= ====== ====== ====== ==============================================
"""
name = 'fucomip'
modes = collections.OrderedDict([
(('st(0)', 'st(i)'), ('dfe8+i', '-o', True, True)),
])
operand_enc = {
'-o': [None, 'opcode +rd (r)'],
}
def __init__(self, src1, src2): # set method signature
Instruction.__init__(self, src1, src2)
# Need:
# fchs, fucompi, fxch
# fsin, fcos, fptan, fpatan, fcom,
# mul, or, and, andn, not, xor
# avx/sse2 instructions
# addsd, subsd, mulsd, divsd, ...
# movdq2q, movq2dq
# Testing instructions
#----------------------------------------
[docs]class cmp(Instruction):
"""Compares the first source operand with the second source operand and
sets the status flags in the EFLAGS register according to the results.
The comparison is performed by subtracting the second operand from the
first operand and then setting the status flags in the same manner as the
SUB instruction. When an immediate value is used as an operand, it is
sign-extended to the length of the first operand.
====== =============== ====== ====== ======================================
src1 src2 32-bit 64-bit description
====== =============== ====== ====== ======================================
r/m8 r/m8, imm8 X X
r/m16 r/m16, imm8/16 X X
r/m32 r/m32, imm8/32 X X
r/m64 r/m64, imm8/32 X
====== =============== ====== ====== ======================================
"""
name = "cmp"
modes = collections.OrderedDict([
(('r/m8', 'imm8'), ('80 /7', 'mi', True, True)),
(('r/m16', 'imm16'), ('81 /7', 'mi', True, True)),
(('r/m32', 'imm32'), ('81 /7', 'mi', True, True)),
(('r/m64', 'imm32'), ('REX.W + 81 /7', 'mi', True, False)),
(('r/m16', 'imm8'), ('83 /7', 'mi', True, True)),
(('r/m32', 'imm8'), ('83 /7', 'mi', True, True)),
(('r/m64', 'imm8'), ('REX.W + 83 /7', 'mi', True, False)),
(('r/m8', 'r8'), ('38 /r', 'mr', True, True)),
(('r/m16', 'r16'), ('39 /r', 'mr', True, True)),
(('r/m32', 'r32'), ('39 /r', 'mr', True, True)),
(('r/m64', 'r64'), ('REX.W + 39 /r', 'mr', True, False)),
(('r8', 'r/m8'), ('3a /r', 'rm', True, True)),
(('r16', 'r/m16'), ('3b /r', 'rm', True, True)),
(('r32', 'r/m32'), ('3b /r', 'rm', True, True)),
(('r64', 'r/m64'), ('REX.W + 3b /r', 'rm', True, False)),
])
operand_enc = {
'rm': ['ModRM:reg (r,w)', 'ModRM:r/m (r)'],
'mr': ['ModRM:r/m (r,w)', 'ModRM:reg (r)'],
'mi': ['ModRM:r/m (r,w)', 'imm8/16/32'],
}
def __init__(self, src1, src2): # set method signature
Instruction.__init__(self, src1, src2)
[docs]class test(Instruction):
"""Computes the bit-wise logical AND of first operand (source 1 operand)
and the second operand (source 2 operand) and sets the SF, ZF, and PF
status flags according to the result. The result is then discarded.
====== =============== ====== ====== ======================================
src1 src2 32-bit 64-bit description
====== =============== ====== ====== ======================================
r/m8 r8, imm8 X X
r/m16 r16, imm8/16 X X
r/m32 r32, imm8/32 X X
r/m64 r64, imm8/32 X
====== =============== ====== ====== ======================================
"""
name = "test"
modes = collections.OrderedDict([
(('r/m8', 'imm8'), ('f6 /0', 'mi', True, True)),
(('r/m16', 'imm16'), ('f7 /0', 'mi', True, True)),
(('r/m32', 'imm32'), ('f7 /0', 'mi', True, True)),
(('r/m64', 'imm32'), ('REX.W + f7 /0', 'mi', True, False)),
(('r/m8', 'r8'), ('84 /r', 'mr', True, True)),
(('r/m16', 'r16'), ('85 /r', 'mr', True, True)),
(('r/m32', 'r32'), ('85 /r', 'mr', True, True)),
(('r/m64', 'r64'), ('REX.W + 85 /r', 'mr', True, False)),
])
operand_enc = {
'mr': ['ModRM:r/m (r,w)', 'ModRM:reg (r)'],
'mi': ['ModRM:r/m (r,w)', 'imm8/16/32'],
}
def __init__(self, a, b): # set method signature
Instruction.__init__(self, a, b)
# Branching instructions
#----------------------------------------
[docs]class jmp(RelBranchInstruction):
"""Transfers program control to a different point in the instruction stream
without recording return information. The destination (target) operand
specifies the address of the instruction being jumped to. This operand can
be an immediate value, a general-purpose register, or a memory location.
====== ====== ====== ===============================================
dst 32-bit 64-bit description
====== ====== ====== ===============================================
imm8 X X Jump to address relative to current instruction
imm16 X
imm32 X X
r/m16 X Jump to absolute address stored in r/m
r/m32 X
r/m64 X
====== ====== ====== ===============================================
"""
name = "jmp"
modes = {
('rel8',): ['eb', 'i', True, True],
('rel16',): ['e9', 'i', False, True],
('rel32',): ['e9', 'i', True, True],
('r/m16',): ['ff /4', 'm', False, True],
('r/m32',): ['ff /4', 'm', False, True],
('r/m64',): ['ff /4', 'm', True, False],
}
operand_enc = {
'm': ['ModRM:r/m (r)'],
'i': ['imm32'],
}
def __init__(self, addr): # set method signature
RelBranchInstruction.__init__(self, addr)
def _jcc(name, opcode, doc):
"""Create a jcc instruction class.
"""
modes = {
('rel8',): [opcode, 'i', True, True],
('rel16',): [opcode, 'i', False, True],
('rel32',): [opcode, 'i', True, True],
}
op_enc = {
'i': ['imm32'],
}
d = " Accepts an immediate address relative to the current instruction."
return type(name, (RelBranchInstruction,), {'modes': modes,
'operand_enc': op_enc,
'__doc__': doc + d})
ja = _jcc('ja', '0f87', """Jump near if above (CF=0 and ZF=0).""")
jae = _jcc('jae', '0f83', """Jump near if above or equal (CF=0).""")
jb = _jcc('jb', '0f82', """Jump near if below (CF=1).""")
jbe = _jcc('jbe', '0f86', """Jump near if below or equal (CF=1 or ZF=1).""")
jc = _jcc('jc', '0f82', """Jump near if carry (CF=1).""")
je = _jcc('je', '0f84', """Jump near if equal (ZF=1).""")
jz = _jcc('jz', '0f84', """Jump near if 0 (ZF=1).""")
jg = _jcc('jg', '0f8f', """Jump near if greater (ZF=0 and SF=OF).""")
jge = _jcc('jge', '0f8d', """Jump near if greater or equal (SF=OF).""")
jl = _jcc('jl', '0f8c', """Jump near if less (SF≠ OF).""")
jle = _jcc('jle', '0f8e', """Jump near if less or equal (ZF=1 or SF≠ OF).""")
jna = _jcc('jna', '0f86', """Jump near if not above (CF=1 or ZF=1).""")
jnae = _jcc('jnae', '0f82', """Jump near if not above or equal (CF=1).""")
jnb = _jcc('jnb', '0f83', """Jump near if not below (CF=0).""")
jnbe = _jcc('jnbe', '0f87', """Jump near if not below or equal (CF=0 and ZF=0).""")
jnc = _jcc('jnc', '0f83', """Jump near if not carry (CF=0).""")
jne = _jcc('jne', '0f85', """Jump near if not equal (ZF=0).""")
jng = _jcc('jng', '0f8e', """Jump near if not greater (ZF=1 or SF≠ OF).""")
jnge = _jcc('jnge', '0f8c', """Jump near if not greater or equal (SF ≠ OF).""")
jnl = _jcc('jnl', '0f8d', """Jump near if not less (SF=OF).""")
jnle = _jcc('jnle', '0f8f', """Jump near if not less or equal (ZF=0 and SF=OF).""")
jno = _jcc('jno', '0f81', """Jump near if not overflow (OF=0).""")
jnp = _jcc('jnp', '0f8b', """Jump near if not parity (PF=0).""")
jns = _jcc('jns', '0f89', """Jump near if not sign (SF=0).""")
jnz = _jcc('jnz', '0f85', """Jump near if not zero (ZF=0).""")
jo = _jcc('jo', '0f80', """Jump near if overflow (OF=1).""")
jp = _jcc('jp', '0f8a', """Jump near if parity (PF=1).""")
jpe = _jcc('jpe', '0f8a', """Jump near if parity even (PF=1).""")
jpo = _jcc('jpo', '0f8b', """Jump near if parity odd (PF=0).""")
js = _jcc('js', '0f88', """Jump near if sign (SF=1).""")
# OS instructions
#----------------------------------------
[docs]class int_(Instruction):
"""The INT n instruction generates a call to the interrupt or exception
handler specified with the destination operand. The destination operand
specifies a vector from 0 to 255, encoded as an 8-bit unsigned intermediate
value. Each vector provides an index to a gate descriptor in the IDT. The
first 32 vectors are reserved by Intel for system use. Some of these
vectors are used for internally generated exceptions.
====== ====== ====== ======================================
dst 32-bit 64-bit description
====== ====== ====== ======================================
imm8 X X
====== ====== ====== ======================================
"""
name = 'int'
modes = collections.OrderedDict([
(('imm8',), ['cd ib', 'i', True, True]),
])
operand_enc = {
'i': ['imm8']
}
def __init__(self, code): # set method signature
Instruction.__init__(self, code)
[docs]class syscall(Instruction):
"""SYSCALL invokes an OS system-call handler at privilege level 0. It does
so by loading RIP from the IA32_LSTAR MSR (after saving the address of the
instruction following SYSCALL into RCX). (The WRMSR instruction ensures
that the IA32_LSTAR MSR always contain a canonical address.)
SYSCALL also saves RFLAGS into R11 and then masks RFLAGS using the
IA32_FMASK MSR (MSR address C0000084H); specifically, the processor clears
in RFLAGS every bit corresponding to a bit that is set in the IA32_FMASK
MSR.
Accepts no operands.
"""
name = 'syscall'
modes = collections.OrderedDict([
((), ['0f05', None, True, True]),
])
def __init__(self): # set method signature
Instruction.__init__(self)