1920px-Netwide_Assembler.svg.png
汇编指令不是机器指令,汇编指令是一种文本。需要经过汇编器编译成机器指令才可以在处理器上执行。汇编语言指令与机器指令总体上是1:N。汇编语言允许程序员直接创建指令码程序,而无需担心处理器上众多的指令码的组合,汇编语言使用助记符表示指令,助记符使程序员可以使用英语样式的词表示各个指令,这样汇编器很容易地把汇编语言翻译成原始的机器指令。

x86 nasm汇编指令格式为。

  1. [label]: mnemonic [operands] [;commemt]

指令包含的操作数可以是0,1,2,3个。操作数可以有三种类型。

  1. 立即操作数(immediate operand):使用数字文本表示
  2. 寄存器操作数(register):使用cpu内已命名的寄存器
  3. 内存操作数(memory): 引用内存的位置。

使用汇编语言可以不了解指令码的每个字节的详细信息,使用更简单的助记符来表示指令。不同的汇编器使用不同的助记符表示指令码。应用比较广泛的有MSVCMASM, AT&Tintel,还有本章节讨论的NASM。

  1. MASM: 只能在windows系统下使用。
  2. AT&T: gcc编译器使用了AT&T作为默认的汇编器,也可以通过配置替换。AT&T是一个跨平台的汇编器,可以在多个系统下使用。
  3. INTEL: intel出的汇编格式。MASM和NAMS的汇编格式和intel类似。
  4. NASM: 跨平台,使用简单。

    数据传送指令

    mov指令

    mov destination,source
    将源操作数复制到目的操作数
  • 两个操作数必须是同样的大小
  • 两个操作数不能同时为内存操作数
  • 指令指针寄存器(IP,EIP,RIP)不能作为目标操作数

mov指令不能直接将较小的操作数复制到较大的操作数。当可以使用寄存器的地位进行操作实现。

mov eax,0
mov ax,bx
mov reg,reg
mov mem,reg
mov reg,men
mov mem,imm
mov reg,imm

movzx指令

** movzx destination,source**
将操作数复制到目的操作数,并把目的操作数0扩展到16位或32位或64位。这条指令只能用于无符号整数。

movzx reg32, reg/mem8
movzx reg32, reg/mem16
movzx reg16, reg/mem8

movsx指令

** movzx destination,source**
将操作数复制到目的操作数,并把目的操作数扩展到16位或32位或64位。这条指令只能用于有符号整数。

movsx reg32, reg/mem8
movsx reg32, reg/mem16
movsx reg16, reg/mem8

xchg指令

xchg destination,source
指令交换两个操作数内容。xcha的要求和mov指令操作数要求一样

xchg reg,reg
xchg reg,mem
xchg mem,reg

xadd指令

先交换仔累加

cmpxchg指令

比较并交换寄存器里的字节的顺序

bawap指令

交换32位寄存器里的字节顺序

lahf指令

标志寄存器传递到ah寄存器上

sahf指令

标记寄存器传送。把ah内容装入标记寄存器

算术运算指令

inc/dec 指令

inc/dec destination
int/dec指令分别表示寄存器或者内存操作数+1或者-1

inc reg/mem
dec reg/mem

add指令

** add destination ,source **
将长度相同的源操作数和目的操作数进行相加

add reg, reg
add mem,reg
add regm men
add mem,imm
add reg,imm

sub指令

sub destionation, source
从目的操作数减去源操作数。指令对操作数的要求和ADD,MOV指令相同

sub reg, reg
sub mem,reg
sub regm men
sub mem,imm
sub reg,imm

neg(非)

neg destionation
neg指令通过把操作数转换为二进制补码,将操作数的符号取反。(将目标操作数按位取反再加1,就可以得到这个数的二进制补码)

neg reg
neg mem

mul指令

mul source
mul用于无符号整数的乘法指令,操作数不能使用立即数,默认使用al/ax/eax/rax寄存器作为目的操作数。有四种类型。

  • 指令执行8位操作数与AL寄存器的乘法,并把乘积过存放AX寄存器中。
  • 指令执行16位操作数与AX寄存器的乘法,并把乘积存放在DX:AX寄存器中。
  • 指令执行32位操作数与EAX寄存器的乘积,并不结果存放在EDX:EAX寄存器中
  • 指令执行62位操作数与RAX寄存器的乘积,并不结果存放在RDX:RAX寄存器中 | 被乘数 | 乘数 | 乘积 | | :—-: | :—-: | :—-: | | AL | reg/mem8 | AX | | AX | reg/mem16 | DX:AX | | EAX | reg/mem32 | EDX:EAX | | RAX | reg.mem32 | RDX:RAX |
mul reg/mem8
mul reg/mem16
mul reg/mem32
mul reg/mem64

imul指令

imul ``destination
imul用于有符号的整数相乘,与mul指令不同,imul会保留乘积的符号。x86指令集支持三种格式的imul的指令。单操作数,双操作数,三操作数。

  • 单操作数
    单操作数与mul类似
  • 双操作数
  • 3操作数

    div指令

    div source
    div指令用于无符号整数除法,操作数不能使用立即数,默认使用dx/edx/rdx和al/ax/eax/rax寄存器作为目的操作数。有四种类型。
被除数 除数 余数
AX reg/mem8 AL AH
DX:AX reg/mem16 AX DX
EDX/EAX reg/mem32 EAX EDX
RDX/RAX reg/mem64 RAX RDX
div reg/mem8
div reg/mem16
div reg/mem32
div reg/mem64

idiv指令

idiv source
idive指令用于执行有符号整数的除法,其操作数与div指令一样。

idiv reg/mem8
idiv reg/mem16
idiv reg/mem32
idiv reg/mem64

跳转指令

无条件跳转指令

jmp指令

jmp destination
jmp指令无条件跳转到目标地址,该地址用代码标号来标识,并被汇编器转换为偏移值。

top:.
      .
    jmp top

call/ret指令

call指令调用一个子程序,指挥着处理器从一个新内存地址开始执行,并使用指令ret将处理器转回子程序被调用的位置上继续执行下面的指令。在x86下。cpu指令的执行由cs :eip 两个指令控制的。cs是代码程序代码区的起点地址,eip为指向执行指令的偏移值。执行call指令后,cpu会自动执行push eip指令。当执行完成子程序后通过执行ret指令。cpu会自动执行pop eip,并跳转到eip指向的地址的执行指令。

#过程/子程序
fun proc
.
.
ret
fun endp
;主函数
main proc
call fun
main endp

条件跳转指令

x86指令布集包括大量的条件跳转指令。他们能比较有符号。无符号整数,并根据单个cpu标记的值或者某个寄存器值来执行操作。条件比较指令只要分为4种类型

  • 居于特定标志位的值跳转
  • 居于两数是否相等。(循环指令)
  • 居于无符号操作数的比较跳转
  • 居于有符号操作数的比较跳转

    loop指令

    loop destination
    loop指令,正式称为按照ecx计数器循环,将程序重复特定次数。ecx自动成为计数器,每次循环计数器减1,。loop指令执行分为两步,第一步ecx -1,第二步ecx与0比较。如果ecx不等于0,则跳转到目标给出的标号。
          mov ax,0
      mov ecx, 5
    L1:
      inc ax
      loop L1
           mov bx,ax ; bx = 5
    

    loope/loopz指令

    loopz destination
    loope标识ecx寄存器为0跳转。loopz指令的工作方式和loop指令相同,只要一个附加条件,ZF位为1。
          test al,0; 设置ZF位为1.
          mov ax,0
      mov ecx, 5
    L1:
      inc ax
      loope L1
           mov bx,ax ; bx = 5
    

    loopne/loopnz指令

    loopne destination
    loopne指令与loope相对应,当ecx寄存器中的无符号数值大于0,却标记位等于0的时候。执行跳转。
          or al,0; 设置ZF位为0.
          mov ax,0
      mov ecx, 5
    L1:
      inc ax
      loope L1
           mov bx,ax ; bx = 5
    

    标记位条件跳转集合

    这是标志位条件跳转集合。当标记条件为真时,条件指令跳转到目标标号。否则当标记位条件为假的时候,立即执行条件跳转后面的指令。
指令名 说明 标记位
JZ(jmp zero) 为0跳转 ZF =1
JNZ(jmp no zero) 非0跳转 ZF=0
JC(jmp come) 进位跳转 CF=1
JNC(jmp no come) 无进位跳转 CF=0
JO(jmp overflow) 溢出跳转 OF=1
JNO(jmp no overflow) 无溢出跳转 OF=0
JS(jmp signed ) 有符号跳转 SF=1
JNS(jmp no signed) 无符号跳转 SF=0
JP(jmp parity check) 偶校验跳转 PE=1
JNP(jmp no parity check) 奇校验跳转 PE=0

其他条件跳转指令集合

针对了特定的指令或者寄存器进行的跳转指令。
cmp leftOp,rightOP指令相等性条件跳转(有符号和无符号)

指令 说明
JE 相等跳转(leftOp == rightOp )
JNE 不等跳转(leftOp != rightOp)

cmp leftOp,rightOP指令无符号比较跳转

指令 说明
JA leftOp > rightOp
JNBE leftOp > rightOp
JAE leftOp >= rightOp
JNB leftOp >= rightOp
JB leftOp < rightOp
JNAE leftOp < rightOp
JBE leftOp <= rightOp
JNA leftOp <= rightOp

cmp leftOp,rightOP指令有符号比较跳转

指令 说明
JG leftOp > rightOp
JNLE leftOp > rightOp
JGE leftOp >= rightOp
JNL leftOp >= rightOp
JL leftOp < rightOp
JNGE leftOp < rightOp
JLE leftOp <= rightOp
JNG leftOp <= rightOp

CX,ECX,RCX寄存器

指令 说明
JCXZ CX==0
JECXZ ECX==0
JERCXZ RCX == 0(64位寄存器)

堆栈操作指令

push指令

push source
push指令首先减少esp的值。再将原操作数复制到堆栈中,操作数是16位,则esp -2,操作数是32位,esp-4,操作数是64位,esp-8

push reg/mem16
push reg/mem32
push imm32

pop指令

pop desination
pop指令首先把esp指针指向的堆栈内存复制到一个16位或32位的目的操作数中,再增加esp的值。如果操作数是16位esp+2,如果操作数是32位esp+4

pop reg/mem16
pop reg/mem32

pusha指令

把AX,CX,DX,BX,SP,BP,SI,DI依次压入堆栈.

popa指令

把DI,SI,BP,SP,BX,DX,CX,AX依次弹出堆栈.

pushad指令

把EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI依次压入堆栈.

popad指令

把EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX依次弹出堆栈.

pushf指令

16位标志位入栈

popf指令

16位标志位出栈

pushd指令

32位标志位入栈

popd指令

32位标志位出栈

比较指令

在高级语言中,通过使用比较指令实现了高级语言的if判断语句,while语句等。

and指令

and destination,source
and指令在两个操作数的对应位之间进行按位与操作。并把结果存放在目标操作数中。操作数可以是8,16,32,64位。但两个操作数必须是同样的大小。两个操作数的每一个对应位都是1,则结果是1,否则等于0.

and reg,reg
and reg,mem
and reg,imm
and mem,reg
and mem,imm

or指令

or destination,source
or指令在两个操作数的对应位进行按位或操作。并把结果存放在目的操作数上,操作数可以是8,16,32,64位。但两个操作数必须是同样的大小。两个操作数的一个对应位是1,则结果是1,否则等0

or reg,reg
or reg,mem
or reg,imm
or mem,reg
or mem,imm

xor指令

xor destination,source
xor指令在两个操作数之间进行异或操作,并把结果存放在目的操作数上。xor指令操作数和and和or指令一样。如果两个位的值相同则结果等于0,否则为1。

xor reg,reg
xor reg,mem
xor reg,imm
xor mem,reg
xor mem,imm

not指令

not destination
not 指令触发操作数所有位把0变,把1变为0。其结果称为反码。

not reg
not mem

test指令

test destination,source
test指令在两个操作数之间进行and操作,并根据运算结果设置符号标志位,零标志位和奇偶标志位。test指令和and指令不同的是,test指令不修改目的操作数。test指令允许的操作数组合和and指令相同。

test reg,reg
test reg,mem
test reg,imm
test mem,reg
test mem,imm

cmp指令

cmp destination, source
cmp指令执行从目的操作数中减去源操作数的隐含减法操作。并且不修改任何的操作数。不同的跳转指令根据标记位执行不同的跳转逻辑。

or reg,reg
or reg,mem
or reg,imm
or mem,reg
or mem,imm

当实际的减法发生的,cmp指令按照计算结果修改溢出,符号,零,进位,辅助进位和奇偶标志位。不同的操作数,标志位有不同的结果过。
两个无符号数

cmp结果 零标记位(ZF) 进位标记位(CF)
目的操作数 < 源操作数 0 1
目的操作数 > 源操作数 0 0
目的操作数 = 源操作数 1 0

两个有符号数

cmp结果 标记位
目的操作数 < 源操作数 SF != OF
目的操作数 > 源操作数 SF = OF
目的操作数 = 源操作数 ZF =1

位移指令

位移标识在操作数中向左或者向右移动。

指令 说明
SHL((shifting left)) 左移
SHR((shifting right)) 右移
SAL(shifting arithmetic left) 算术左移
SAR(shifting arithmetic right) 算术右移
ROL 循环左移
ROR 循环右移
RCL 带进位的循环左移
RCR 带进位的循环右移
SHLD 双精度左移
SHRD 双精度右移

中断指令

int指令

中断

into指令

溢出中断

iret指令

中断返回

处理器控制指令

hlt指令

处理器暂停, 直到出现中断或复位信号才继续.

wait指令

等待

nop指令

空操作.

stc指令

置进位标志位.

clc指令

清进位标志位.

cmc指令

进位标志取反.

std指令

置方向标志位.

cld指令

清方向标志位.

sti指令

置中断允许位.

cli指令

清中断允许位.

输出输入指令

in指令

i/o端口输入

out指令

i/o端口输出

目的传送指令

lea指令

装入有效地址

lds指令

les指令

lfs指令

lgs指令

lss指令