## 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
功能:规定程序或变量在逻辑段中的起始地址