汇编语言-80x86指令系统

数据传送指令

通用数据传输指令

MOV

  • 格式

    mov dst,src

  • 执行操作

    (dst)<-(src)

  • 注意

    • DST、SRC不能同时为段寄存器
    • 立即数不能送段寄存器
    • DST不能是CS
    • DST、SRC不能同时是存储器寻址
    • 不影响标志位
  • 相关指令

    • movsx

      带符号扩展传送

    • movzx

      带零扩展传送

PUSH

  • 格式

    push src

  • 执行操作(16位指令)

    1. (sp)<-(sp)-2,说明栈顶地址低
    2. ((sp+1),(sp))<-(src)
  • 注意

    • 堆栈操作必须以字为单位
    • pushpop不能用立即寻址方式
    • popdst不能是CS
    • SP在任何时候都指向栈顶
    • pushpop不影响标志位
  • 相关指令

    • pusha

      16位通用寄存器依次进栈

    • popa

      16位通用寄存器依次出栈

POP

  • 格式

    pop dst

  • 执行操作(16位指令)

    1. (dst)<-((sp+1),(sp))
    2. (sp)<-(sp)+2

累加器专用传送指令

该组指令仅限于使用累加器EAX,AX或AL传送信息

IN

输入,即I/O传给CPU信息。

  • 长格式
    • in al,port
    • in ax,port
  • 执行操作
    • (al)<-(port),字节
    • (ax)<-(port),字
  • 短格式
    • in al,dx,字节
    • in ax,dx,字
  • 执行操作
    • (al)<-((dx)),字节
    • (ax)<-((dx)),字

OUT

输出,即CPU传给IO信息。

  • 长格式
    • out port,al,字节
    • out port,ax,字
  • 执行操作
    • (port)<-(al),字节
    • (port+1,port)<-(ax),字
  • 短格式
    • out dx,al,字节
    • out dx,ax,字
  • 执行操作
    • ((dx))<-(al),字节
    • ((dx)+1,(dx))<-(ax),字
  • s
    • 当$端口号\geq256$时,只能使用短格式。
    • INOUT指令不影响标志位。

地址传送指令

LEA

源操作数的偏移地址送寄存器

  • 格式

    lea reg,src

  • 执行操作

    (reg)<-src

  • 注意

    • dst不能使用段寄存器
    • 源操作数可以是除立即数和寄存器以外的任一种存储器寻址方式。
    • 不影响标志位

标志寄存器传送指令

LAHF

FLAGS低字节送AH,load AH with FLAGS

  • 格式

    LAHF

  • 执行操作

    (AH)<-(FLAGS的低字节)

SAHF

AHFLAGS低字节,store AH into FLAGS

  • 格式

    SAHF

  • 执行操作

    (FLAGS的低字节)<-(AH)

PUSHF

标志进栈指令

  • 格式

    PUSHF

  • 执行操作

    • (SP)<-(SP)-2
    • ((SP)+1,(SP))<-(FLAGS)

POPF

标志出栈指令

  • 格式

    POPF

  • 执行操作

    • (FLAGS)<-((SP)+1,(SP))
    • (SP)<-(SP)+2

类型转换指令

不影响标志位

CBW

字节转换为字,AL的内容符号扩展到AH,形成AX中的字

CWD

字转换为双字,同理,AX扩展为DX:AX

CDQ

双字转换为4字,同理,EAX扩展为EDX:EAX

算术指令

加法指令

ADD

加法

  • 格式

    ADD DST,SRC

  • 执行操作

    (DST)<-(SRC)+(DST)

ADC

带进位加法

  • 格式

    ADC DST,SRC

  • 执行操作

    (DST)<-(DST)+(SRC)+CF

INC

加1

  • 格式

    INC OPR

  • 执行操作

    (OPR)<-(OPR)+1

  • 注意

    以上三条指令除INC不影响CF外,它们都影响条件标志位。

XADD

交换并相加

  • 格式

    XADD DST,SRC

  • 执行操作

    • TEMP<-(SRC)+(DST)
    • (SRC)<-DST
    • (DST)<-TEMP

减法指令

DEC不影响CF标志外,它们都影响条件标志位。

SUB

减法

  • 格式

    SUB DST,SRC

  • 执行操作

    (DST)<-(DST)-(SRC)

SBB

带借位减法

  • 格式

    SBB DST,SRC

  • 执行操作

    (DST)<-(DST)-(SRC)-CF

DEC

减1

  • 格式

    DEC OPR

  • 执行操作

    (OPR)<-(OPR)-1

NEG

求补指令

  • 格式

    NEG OPR

  • 执行操作

    (OPR)<-(OPR),操作数按位求反后+1

CMP

  • 格式

    CMP OPR1,OPR2

  • 执行操作

    (OPR1)-(OPR2)

乘法指令

乘法指令对CFOF以外的条件码无定义。

AXDX,AX为隐含的乘数寄存器。

SRC不能是立即数。

MUL

无符号数乘法

  • 格式

    MUL SRC

  • 执行指令

    (AX)<-(AL)*(SRC)

    (DX,AX)<-(AX)*(SRC)

IMUL

带符号数乘法

  • 格式

    IMUL SRC

  • 执行操作

    MUL指令相同,但必须是带符号数,而MUL是无符号数

除法指令

除法指令对所有条件码均无定义。

SRC不能是立即数。

目的操作数必须存放在AXDX,AX中。

DIV

无符号数除法指令

  • 格式

    DIV SRC

  • 执行操作

    (AL)<-(AX)/(SRC)的商(AH)<-(AX)/(SRC)的余数

    (AX)<-(DX,AX)/(SRC)的商(DX)<-(DX,AX)/(SRC)的余数

IDIV

带符号数除法指令

  • 格式

    IDIV SRC

  • 执行操作

    DIV指令相同,但必须是带符号数

逻辑指令

逻辑运算指令

除了NOT外,其他4条逻辑运算指令使CFOF为0,对AF无定义,对SFZFPF根据运算结果设置。

AND

逻辑与

  • 格式

    AND DST,SRC

  • 执行操作

    (DST)<-(DST)∧(SRC)

OR

  • 格式

    OR DST,SRC

  • 执行操作

    (DST)<-(DST)∨(SRC)

NOT

按位取反

  • 格式

    NOT OPR

  • 执行操作

  • 注意

    不允许使用立即数,不影响标志位

XOR

异或

  • 格式

    XOR DST,SRC

  • 执行操作

TEST

两个操作数进行逻辑与,不保存结果

  • 格式

    TEST OPR1,OPR2

  • 执行操作

    (OPR1)∧(OPR2)

移位指令

CNT为1时,OF位才有效,否则无定义

指令格式指令 OPR,CNT

非循环移位指令

SA:Shift Arithmetic

SH:Shift

根据移位后的结果设置SFZFPF位,AF则无定义。

算术移位指令适用于带符号数运算,逻辑移位指令适用于无符号数运算。

  • SHL

    逻辑左移指令,低位补0,CF存放移出去的最后一位

  • SAL

    算术左移指令,和SHL相同

  • SHR

    逻辑右移指令,高位补0,CF存放移出去的最后一位

  • SAR

    算术右移指令,高位补符号位,CF存放移出去的最后一位

循环移位指令

RC:Rotate Carry

RO:Rotate

不影响除CFOF外的其他条件标志。

  • ROL

    循环左移指令,移出去的最后一位存入CF

  • ROR

    循环右移指令,移出去的最后一位存入CF

  • RCL

    带进位循环左移指令,CF参与循环移位

  • RCR

    带进位循环右移指令,CF参与循环移位

串处理指令

步骤

  1. 设置ESDS

  2. 设置DISI

  3. 串长度存入CX

  4. 建立方向标志

    CLD:正向,DF=0,Clear Direction

    STD:反向,DF=1,Set Direction

  5. 串处理,REP MOVSB

REP

格式:REP MOVS

如果CX为0,则结束;否则(CX)<(CX)-1,执行串指令。LOOP也是先判断CX是不是0。

MOVS

REPREPZREPNZ这三个前缀配合使用。

格式:MOVS DST,SRC

不影响条件码

控制转移指令

无条件转移指令

不影响标志位

条件转移指令

不影响标志位

JL

  • 测试条件

    SF异或OF=1

JGE

  • 测试条件

    SF异或OF=0

条件设置指令

STD

CLD

等等

循环指令

不影响条件码。

执行操作

  • (CX)<-(CX)-1
  • 检查是否满足测试条件

LOOP

当计数器不为0时循环指令

  • 格式

    LOOP OPR

  • 测试条件

    (CX)!=0

LOOPZ

当计数器不为0且结果为0(即ZF=1)时循环指令

  • 格式

    LOOPZ OPR

  • 测试条件

    ZF=1且(CX)!=0

LOOPNZ

当计数器不为0且结果不为0(即ZF=0)时循环指令

  • 格式

    LOOPNZ OPR

  • 测试条件

    ZF=0且(CX)!=0

子程序

均不影响条件码。

IPCS都是先写IP,再写CS。中断也是这样。所以压栈也应先压CS,再压IP

CALL

格式CALL DST

段内:只需要PUSH(IP)

段间:先PUSH (CS)PUSH (IP)

直接:偏移量DDST指定的段地址和偏移地址

间接:根据(EA)去取(IP)(CS)

  • 段内直接近调用

    • 执行操作
      • PUSH (IP)
      • (IP)<-(IP)+DD为位移量。
  • 段内间接近调用

    由指定的寄存器或存储单元的内容给出转向地址

    • 执行操作
      • PUSH (IP)
      • (IP)<-(EA)
  • 段间直接远调用

    • 执行操作
      • PUSH (CS)
      • PUSH (IP)
      • (IP)<-DST指定的偏移地址
      • (CS)<-DST指定的段地址
  • 段间间接远调用

    • 执行操作
      • PUSH (CS)
      • PUSH (IP)
      • (IP)<-(EA)
      • (CS)<-(EA+2)

RET

段内:只需要(IP)<-POP()

段间:先(IP)<-POP()(CS)<-POP()

带立即数:最后(SP)<-(SP)+DD为位移量

  • 段内近返回

    • 格式

      RET

    • 执行操作

      (IP)<-POP()

  • 段内带立即数近返回

    • 格式

      RET EXP

    • 执行操作

      • (IP)<-POP()
      • (SP)<-(SP)+DD为位移量
  • 段间远返回

    • 格式

      RET

    • 执行操作

      • (IP)<-POP()
      • (CS)<-POP()
  • 段间带立即数返回

    • 格式

      RET EXP

    • 执行操作

      • (IP)<-POP()
      • (CS)<-POP()
      • (SP)<-(SP)+DD为位移量

中断

INT

  • 格式

    INT TYPE

    INT

  • 执行操作

    • PUSH (FLAGS)
    • IF<-0
    • TF<-0
    • AC<-0
    • PUSH (CS)
    • PUSH (IP)
    • (IP)<-(TYPE*4)
    • (CS)<-(TYPE*4+2)

IRET

  • 格式

    IRET

  • 执行操作

    • (IP)<-POP()
    • (CS)<-POP()
    • (FLAGS)<-POP()

作者:@臭咸鱼

转载请注明出处:https://chouxianyu.github.io

欢迎讨论和交流!