8086汇编指令

966 阅读21分钟

## 8086汇编指令


数据传送指令

mov 传送指令

格式:mov 目标, 源

功能:将源操作数(一个字节或一个字)传送到目标操作数

push:进栈指令

格式:push 源

功能:将源操作数推入栈中(先进后出原则)

pop:出栈指令

pop 目的

功能:把当前SP所指向的堆栈顶部的一个字送到指令的目的操作数中

pushf:标志入栈指令

格式:pushf

功能:吧整个标志寄存器的内容推入堆栈, 同时修改堆栈指针, 是SP←Sp-2, 这条指令执行后对标志位无影响.

popf:标志出栈指令

格式popf

功能:吧当前堆栈指针Sp所指的一个字, 传送给标志寄存器FLAGS, 并修改堆栈指针, 是SP←SP+2

xchg:交换指令

格式:xchg 目的, 源

功能:把一个字或字节的源操作数和目的操作数交换

交换可以在寄存器起之间、寄存器与存储器之间进行, 但段寄存器不能作为操作数, 也不能直接交换两个存贮单元中的内容

算术运算指令

add:加法指令

add 目的, 源

功能:将源和目的操作数相加, 结果送到目的操作数中, 即:

目的←源+目的

sub:减法指令

sub 目的, 源

功能: 将源和目的操作数相减, 结果送到目的操作数中, 即:

目的←目的-源

mul:无符号乘法指令

格式:mul 源

功能:把源操作数和累加器(al/ax)中的数都当成无符号数, 然后对将两个数相乘, 源操作数可以是字节或字

如果原操作数是一个字节, 它把累加器al中的内容相乘, 乘积为双倍长的16位数,, 高8位送到ah, 低8位送到al, 即:

ax←al*源

如果原操作数是一个字, 它把累加器ax中的内容相乘, 乘积为32位数, 高位字放在dx寄存器中, 高位字放在ax寄存器中, 即:

(dx, ax)←ax*源

当源操作数是存储单位是, 必须在操作数前加byte或word说明字节或字

imul整数乘法指令

格式:imul 源

功能:把源操作数和累加器中的数都作为带符号数,进行相乘

存放结果的方式与mul的方式相同. 如果源操作数为字节, 则与al相乘, 双倍长结果送到ax中. 如果源操作数为字, 则与ax相乘, 双倍字长结果送到dx和ax中, 最后给成绩赋予正确的符号

div无符号除法指令

格式:div 源

功能:对两个无符号二进制数可能性除法操作. 源操作数可以是字节或字

如果源操作数为字节, 16位被除数必须放在ax中, 8为出书为源操作数, 它可以是寄存器或存储单元. 相除之后, 8位商在al中, 余数在ah中, 即:

al←ax/源(字节)的商

ah←ax/源(字节)的余数

要是被除数只有8位, 必须把它放在al中, 并将ah清0, 然后相除.

如果源操作数为字, 32位被除数必须放在dx、ax中, 8为出书为源操作数, 它可以是寄存器或存储单元. 相除之后, dx中存816位商, dx存16位余数, 即:

ax←ax/源(字节)的商

dx←ax/源(字节)的余数

要是被除数只有16位, 除数也是16位, 则必须将被除数放在ax中, 再将dx寄存器清0, 然后相除.

idiv整数除法指令

格式:idiv 源

功能:该指令执行的操作数与div相同, 但操作数必须是带符号数, 商和余数也都是带符号数, 而且规定余数的符号和被除数相同, 因此idiv也称为带符号除法指令

adc:带进位的加法指令

功能:功能与add类似, 只是在两个操作数相加是, 还要把进位标志CF的当前值加进去作为和, 再把结果送到目的操作数中, 即:

目的←源+目的+CF

sbb:带借位的减法指令

格式:sbb 目的, 源

功能:与sub类似, 只是在两个操作数相减后, 还要减去进位/借位标志CF的当前值, 即:

目的←目的-源-CF

cmp:比较指令

格式:cmp 目的, 源

功能:将目的操作数减去源操作数, 但结果不会送到目的操作数中, 仅将结果反映在标志位上, 用于比较两个数的大小, 可用条件跳转指令决定程序的去向, 即:

目的-源

两个无符号数比较

cmp ax, bx

如果(ax)=(bx) 则(ax) - (bx)= 0,所以:ZF=1, SF=0;

如果(ax)≠(bx) 则(ax) - (bx)≠ 0,所以:ZF = 0;

如果(ax)<(bx) 则(ax) - (bx)将产生借位,所以:CF=1, SF = 1;

如果(ax)≥(bx) 则(ax) - (bx)不必借位,所以:CF=0;

如果(ax)>(bx) 则(ax) - (bx)既不必借位,结果又不为0,所以:CF=0并且ZF=0, , SF = 0;

如果(ax)≤(bx) 则(ax) - (bx)既可能借位,结果可能为0,所以:CF=1或ZF=1

反过来看上面的例子

ZF=1,说明(ax)=(bx)

ZF=0,说明(axjT^bx)

CF=1,说明(ax)<(bx)

CF=0,说明(ax)^(bx)

CF=0 并且ZF=0,说明(ax)>(bx)

CF=1 或 ZF=1,说明(ax)≤(bx)

两个有符号数比较

cmp ax, bx

如果 SF=1,而 OF=1

(ah)<(bh)

如果 SF=1,而 OF=0

(ah)>(bh)

如果 SF=0,而 OF=1

(ah)<(bh)

如果 SF=0,而 OF=0

(ah)≥(bh)

neg:取负指令

格式:neg 目的

功能:对目的操作数取负, 即:

目的←0-目的

inc:增量指令

格式:inc 目的

功能:对目的数加1, 结果送回操作数, 即:

目的←目的+1

dec:减量指令

格式:dec 目的

功能:对指定的目的数减1, 结果送回此操作数, 即:

目的←目的-1

逻辑运算指令

and:逻辑与指令,按位进行与运算

格式:and 目的, 源

功能:将两个操作数进行按位逻辑与操作, 结果送回目的操作数, 即:

目的←目的∧源

例如指令:

mov alz 01100011B

and al,00111011B

执行后:al=0010001 IB

主要用于使操作数的某些位保留(和”1”相与), 而使某些位清除(和”0”相与)

or:逻辑或指令,按位进行或运算

格式:or目的, 源

功能:将两个操作数进行按位逻辑或操作, 结果送回目的操作数, 即:

目的←目的∨源

例如指令:

mov al,01100011B

or al,00111011B

执行后:al=01111011B

主要用于使操作数的某些位保留(和”0”相或), 而使某些位置1(和”1”相或)

not取反指令

格式:not 目的

将目的操作数求反, 结果送回目的操作数, 即:

目的←____目的

例如指令:

mov al,01100011B

not al

执行后:al=10011100B

指令执行后, 均将CF和OF清0

xor:异或指令

格式:xor 目的, 源

功能:对两个操作数按位进行逻辑异或运算, 结果送回目的操作数, 即:

目的←目的源

例如指令:

mov al,01100011B

xor al,00111011B

执行后:al=10100111B

主要用于使操作数的某些位保留(和”0”相异或), 而使某些位去反(和”1”相异或)

test:测试指令

格式:test 目的, 源

功能:对两个操作数进行逻辑与操作, 并修改标志位, 但不送回结果, 即指令执行后, 两个操作数都不变, 即

目的∧源

常用在要检测某些条件是否满足, 但又不希望改变原有操作数的情况下. 紧跟在这条指令后面的往往是一条条件转移指令, 根据测试结果产生分支, 转向不同的处理程序

例如指令:

test al, 80h

jnz T_ALARM

test al, 40h

jnz P_ALARM

标志寄存器

状态标志位

CF: 进位标志位,一般情况,进行无符号运算时,它记录运算结果的最高位向更高位的进位值,或从更高位的借位值,如果运算结果的最高位产生了一个进位或借位,那么其值为1,否则其值为0。

SF: 符号标志位,它记录相关指令执行后,其结果是否为负,如果结果为负,SF=1,如果非负,SF=0

AF: 辅助进位标志位。这个位表示加减法做到一半时有没有形成进位/借位,如果有则AF=1。

例如 MOV AL,00001110 MOV BL,00001000 ADD AL,BL 最后结果为AL=00010110这就是低四位向高四位进位。反之在减法中第三位不够减向第四位借位(注意数位是从第0位开始数的)叫低四位向高四位借位!像前面的AL中前四位为高四位,后四位为低四位。例如,当两个字节相加时,如果从低4位向高4位有进位时,则AF=1。

PF: 奇偶标志位,它记录相关指令执行后,其结果的所有二进制位中1个个数是否为偶数,如果是偶数,PF=1,反之为0

OF: 溢出标志位,在进行有符号数运算的时候,如果结果超出了机器所能表示的范围称为溢出,OF的值被置为1,否则OF的值为0。

注意:这里所说的溢出,只是对有符号运算而言。

ZF: 零位标志位,它记录相关指令执行后的结果是否为0,如果是0,那么ZF=1,如果结果不为0,那么ZF=0

控制标志位

IF: 中断允许标志位,用来决定CPU是否响应CPU外部的可屏蔽中断发出的中断请求,但不管该标志为何值,CPU都必须响应CPU外部的不可屏蔽中断所发出的中断请求,以及CPU内部产生的中断请求。

l 当IF=1时,CPU可以相应CPU外部的可屏蔽中断发出的中断请求。

l 当IF=0时,CPU不响应CPU外部的可屏蔽中断发出的中断请求。

TF: 追踪标志位,当追踪标志被置为1时,CPU进入单步执行方式,即每执行一条指令产生一个单步中断请求,这中方式主要用于程序的调试。

DF: 方向标志位,在串处理指令中,控制每次操作后,si(指向原始偏移地址)、di(指向目标偏移地址)的增减。

l DF=0时,每次操作后,si、di递增;

l DF=1时,每次操作后,si、di递减。

我们可以使用cld指令将DF的值置为0,使用std指令将DF的值置为1。DF需要与rep、movsb等指令配合使用。

移位操作指令

非循环移位指令

算术移位(有符号)

sal 算术左移指令

格式:sal 目的, 移动次数(移动一位是右指令直接给出, 移动两位及以上时, 移位次数必须由cl指定)

功能:

1) 将一个寄存器或内存单元中的数据向左移位

2) 将最后移出的一位写入CF中

3) 最低位用0补充

例:

mov al,01001000b

shl al, 1 ;将al中的数据左移一位

执行后(al)=10010000b, CF=0。

如果移动位数大于1, 必须讲移位位数放在cl

例:

CF

mov al, 01010001b

mov cl, 03H

shl al,cl

执行后(al)=10001000b,因为最后移出的一位是0,所以CF=0

将X逻辑左移一位,相当于执行X=X*2。

sar 算术右移指令

格式:sar 目的, 移动次数

功能:

1) 将一个寄存器或内存单元中的数据向右移动

2) 将最后移除的一位写入CF中

3) 最高位保持不变

例:

mov al,01010001b

mov cl, 03H

sar al,cl

执行后(al)=00001010b, 因为最后移出的一位是0,所以CF=0

逻辑移位(无符号)

shl 逻辑左移指令

格式:shl 目的, 移动次数

功能:与sal完全一样

shr 逻辑右移指令, 它和shl所进行的操作刚好相反。

格式:shr 目的, 移动次数

功能:

1) 将一个寄存器或内存单元中的数据向右移位

2) 将最后移出的一位写入CF中

3) 最高位用0补充

例:

mov al,01010001b

mov cl, 03H

shr al,cl

执行后(al)=00001010b,因为最后移出的一位是0,所以CF=0

将X逻辑右移一位,相当于执行X=X/2。

逻辑左移可以实现乘法运算

逻辑右移可以实现除法运算

例:用右移的方法做除法133/8=16……5

mov al, 10000101B

mov cl, 03H

shr al, cl

指令执行后, al=00010000B=16, 余数5被丢失。CF=1

循环移位指令

不带进位的循环移位

rol 循环左移指令

rol循环左移

格式:rol 目的, 移动次数

CF


ror循环右移

CF

ror 循环右移指令

格式:ror 目的, 移动次数

rcl通过进位的循环左移

CF


带进位的循环移位

rcl:通过进位为循环左移

格式:rcl 目的, 移动次数

CF

rcr:通过进位为循环右移

rcr通过进位的循环右移

格式:rcr 目的, 移动次数

rcl和rcr指令把CF作为循环的一部分,一起参与循环移位

重复前缀

无条件重复

rep 功能:

当cx≠0时,cx-1, rep后的指令将继续重复执行

常用与传送类指令前—为传送完则继续传送

条件重复

repz/repz 功能:

cx≠0 & ZF=1, 则前缀后的指令将继续重复执行

repnz 功能:

cx≠0 & ZF=0, 则前缀后的指令将继续执行

串操作指令

串传送

movs 目标串, 源串 (此格式仅适用于源操作数需段重设的情况下)

功能:

把由si作指针的原串中的一个字节或字,传送到由di作指针的目的串中,且自动修改指针si和di

movsb 功能:

mov es:[di], byte ptr ds:[si]

如果df=0:

inc si

inc di

如果df=1:

dec si

dec di

movsw 功能:

mov es:[di], word ptr ds:[si]

如果df=0:

si←si+2

di←di+2

如果df=1:

si←si-2

di←di-2

串比较

cmps 源串, 目的串

功能:从si作指针的源串中减去由di作指针的目的串数据, 相减后的结果反映在标志位上,但不改变两个数据串的原始值. 同时, 操作后源串和目的串指针会自动修改,指向下一对待比较的串.

cmpsb 功能:

(es:[di])-( ds:[si])

如果df=0:

inc si

inc di

如果df=1:

dec si

dec di

cmpsw 功能:

(es:[di])-( ds:[si])

如果df=0:

si←si+2

di←di+2

如果df=1:

si←si-2

di←di-2

串扫描

scas 目的串

功能: 从al(字节操作)或ax(字操作)寄存器的内容减去附加段中的以di为指针的目的串元素, 结果反映在标志位上, 但不改变源操作数. 同时, 操作后的目的串指针会自动修改, 指向下一个待搜索的串元素.

利用scas指令, 可在内存中搜索所需要的数据. 这个被搜索的数据被称为关键字. 指令执行前, 必须事先将他存在al(字节)或ax(字)中, 才能用scas指令进行搜索. scas指令前也可以嘉重复前缀

scasb 功能:

(al)-(es:di)

inc di

scasw 功能:

(ax)-(es:di)

如果df=0:

di←di+2

如果df=1:

di←di-2

串装入

lods 源串

功能:把数据段中以si作为指针的串元素, 传送到al(字节操作)或ax(字操作)中, 同时修改si, 使它指向串的下一个元素, si的修改量由方向标志df和源串的类型确定, 即遵守上述隐含约定

lodsb(字节串读取) 功能:

al←(ds:si)

inc si

lodsw(字串读取) 功能:

ax←(ds:si)

如果df=0:

si←si+2

如果df=1:

si←si-2

串送存

stos 目的串

功能:将累加器al(字节操作)或ax(字操作)中的一个字节或字, 传送到附加段中以di为目的指针的目的串中, 同时修改di, 以指向串中的下一个单元

stosb(字节存储) 功能:

(es:di)←al

inc di

stows(字存储) 功能:

(es:di)←ax

如果df=0:

di←di+2

如果df=1:

di←di-2

转移指令

无条件转移指令

段内转移

jmp short 标号:段内近转移

功能: (IP)=(IP)+8位位移。

1) 8位位移=标号处的地址-jmp指令后的第一个字节的地址

2) short指明此处的位移为8位位移

3) 8位位移的范围为-128 ~127

4) 8位位移由编译程序在编译时算出。

jmp near标号

功能: (IP)=(IP)+16位位移: 段内远转移

5) 16位位移=标号处的地址-jmp指令后的第一个字节的地址

6) short指明此处的位移为16位位移

7) 16位位移的范围为- 32768 ~ 32767

8) 16位位移由编译程序在编译时算出。

jmp word ptr 内存单元地址

jmp 某一合法寄存器: 用寄存器中的值修改IP。

段间转移

jmp 段地址:偏移地址:只能在debug中使用

jmp far 标号

jmp dword ptr 内存单元地址

条件转移指令

jcxz标号: CX寄存器的内容为零则转移到标号处

符号

指令

含义

格式

检测的相关标志位

无符号

jb/ jnae /jc

低于/不高于等于/进位为1则转移

jb/ jnae /jc 标号

CF=1

jnb/ jae/jnc

不低于/高于等于/进位为0则转移

Jnb/ jae/jnc标号

CF=0

jbe /jna

低于等于/不高于则转移

jbe /jna标号

CF=1 or ZF=1

jnbe /ja

不低于等于/高于则转移

jnbe /ja标号

CF=0 & ZF=0

有符号

jl/ jnge

小于/不大于等于则转移

jl/ jnge标号

SF≠OF & ZF=0

jnl/ jge

不小于/大于等于则转移

jnl/ jge标号

SF=OF or ZF=1

jle/ jng

小于等于/不大于则转移

jle/ jng标号

SF≠OF or ZF=1

jnle/ jg

不小于等于/大于则转移

jnle/ jg标号

SF=OF & ZF=0

a(above)大于,b(below)小于,e(equal)等于,用于比较无符号数

g(great)大于,l(less than)小于, e(equal)等于,用于比较带符号数

条件转移指令均为段内短转移, 即转移范围为:-128-------+127

循环指令

loop

格式:loop 标号

循环条件cx≠0

loopz

功能:先使cx-1, 在根据cx中值及CF值类决定是否继续循环

循环条件:cx≠0, 且ZF=1

loopnz

功能:同上

循环条件:cx≠0, 且ZF=0

过程调用

段内调用

call 标号 功能:

相当于进行:

1) push IP

2) jmp near ftr 标号

call word ptr [si]

功能:

1) push IP

2) jmp word ptr 内存单元地址

ret 功能: pop IP

段间调用

call far 标号 功能:

相当于进行:

1) push CS

2) push IP

3) jmp far ptr 标号

call dword ptr [si] 功能:

1) push CS

2) push IP

3) jmp dword ptr 内存单元地址

retf 功能:

pop IP

pop CS

中断

int 功能为引发中断过程

a) 取中断类型码n

b) 标志寄存器入栈(pushf),IF=O, TF=O

c) CS、IP入栈 (push CS push IP)

d) (lP)=(n*4), (CS)=(n*4+2)

从此处转去执行n号中断的中断处理程序。

iret 功能 pop IP

pop CS

popf

处理器控制指令

对标志位的操作

指令助记符

操作

说明

CLC

CF←0

进位标志位清0

CMC

CF←1

进位标志位置1

CLD

CF←CF

进位标志位取反

STC

DF←0

方向标志位清0,串操作从低地址到高地址

STD

DF←1

方向标志位置1,串操作从高地址到低地址

CLI

IF←0

中断标志位清0

STI

IF←1

中断标志位置1


与外部设备的同步

NOP 一个字节的机器码,没有操作数,对状态标志位没有影响。不执行任何操作,但占用3个时钟周期,然后继续执行下一条指令。

HLT 处理器停止工作,进入暂停状态。外部中断或复位信号可使CPU退出暂停状态。对状态标志位没有影响。

WAIT 处理器处于等待状态,等到外部的TEST引脚上的低电平到来。

ESC 该指令是一个交权的指令前缀,把指令给协处理处理。

一般和WAIT指令一起使用,通过TEST引脚和协处理器同步。

LOCK 该指令是一个前缀,使得使用此前缀的指令执行时一直维持总线封锁状态。

伪指令

数据定义伪指令

用于定义数据去中变量的类型及其所占内存空间大小

格式:[变量名] 伪指令助记符 操作数, …;[注释]

符号地址 定义变量类型 变量值,可以是是常数, 表达式或字符串。其大小不能超过伪指令助记符所限定的范围

数据定义伪指令助记符(类型)

db(define byte)

定义的变量诶字节型

dw(define byte)

定义的变量为字类型

dd(define double byte)

定义的变量为双字类型

dq(define quadword)

定义的变量为4字类型

bt(define tenbyte)

定义的变量为10字类型

例:

data1 db 11h, 22h, 33h

定义字符串必须用db伪指令,对应字符用ASCII码表示

例:

data1 db ‘abcd’ 100H

61H

62H

63H

64H

65H

66H

重复操作符

[变量名] 伪指令助记符 n dup (值1, 值2, ……)

功能:为一个数据区的各单元设置相同的值

例:

M1 db 10 dup (0)

相当于M1 db 0,0,0,0,0,0,0,0,0,0

“?”的作用

表示随机值,用于预留存储空间

例:

M1 db 5 dup (0)

db ?

0

0

0

0

0

x

符号定义伪指令

格式:符号名 equ 表达式

功能:

将表达式的值赋给一个名字。当源程序中需要多次引用某一条表达式时, 可以利用equ指令, 用一个符号代替表达式, 以便于程序维护

例:

aaa equ 10 ;把常数值10赋给符号名aaa

段定义伪指令

格式:

段名 segment [定义类型][组合类型][‘类型’]

段名 ends

段名也代表了逻辑段的段地址

设定段寄存器伪指令

格式:

assume 段寄存器名:段名[, 段寄存器名:段名, ……]

结束伪指令

格式:

end [标号]

功能:

1) 通知编译器程序结束

2) 通知编译器程序的入口在什么地方

一个完整的程序结构

assume cs:代码段名, ds:数据段名, ss:堆栈段名, es:附加段名

数据段名:segment

数据段名 ends

堆栈段名:segment

堆栈段名 ends

附加段名:segment

数据段名 ends

代码段名:segment

标号 mov ax, 数据段名

mov ds, ax

mov ax, 堆栈段名

mov ss, ax

mov ax, 附加段名

mov es, ax

代码段名 ends

end [标号]

过程定义伪指令

格式:过程名 proc[near/far]

ret

过程名 endp

过程名是过程入口的符号地址

功能:用于定义一个过程体

宏命令伪指令

宏:源程序中由汇编程序识别的具有独立功能的一段程序代码

当源程序中需要多次使用同一程序段时, 可以将该程序段定义为一个宏

格式:宏命令名macro <形式参数>

endm

例:

(定义宏)

modd macro x, y, z

mov ax, x

add ax, y

mov z, ax

endm

(调用宏)

dadd data1, data2, data3

调整偏移量伪指令功能:

格式:org 表达式

例:

data segment

org 1200H

buff db 1, 2 ;变量buff的便宜地址为1200H

data ends

功能:规定程序或变量在逻辑段中的起始地址