教学提示在正确理解每条指令的功能基础上,可以阅读和编写有实际意义的程序段
3.2.3 位操作类指令
位操作类指令以二进制位为基本单位进行数据的操作;这是一类常用的指令,都应该特别掌握
注意这些指令对标志位的影响
1、逻辑运算指令
AND OR XOR NOT TEST
2、移位指令
SHL SHR SAR
3、循环移位指令
ROL ROR RCL RCR
逻辑与指令 AND
对两个操作数执行逻辑与运算,结果送到目的操作数
AND指令设置 CF = OF = 0,根据结果设置 SF、
ZF和 PF状态,而对 AF未定义
AND reg,imm/reg/mem ; reg←reg ∧ imm/reg/mem
AND mem,imm/reg ; mem←mem ∧ imm/reg
只有相,与,的两位都是 1,结果才是 1;否则,,与,的结果为
0
AND
逻辑或指令 OR
对两个操作数执行逻辑或运算,结果送到目的操作数
OR指令设置 CF = OF = 0,根据结果设置 SF、
ZF和 PF状态,而对 AF未定义
OR reg,imm/reg/mem ; reg←reg ∨ imm/reg/mem
OR mem,imm/reg ; mem←mem ∨ imm/reg
只要相,或,的两位有一位是 1,
结果就是 1;否则,结果为 0
OR
逻辑异或指令 XOR
对两个操作数执行逻辑异或运算,结果送到目的操作数
XOR指令设置 CF = OF = 0,根据结果设置 SF、
ZF和 PF状态,而对 AF未定义
XOR reg,imm/reg/mem ; reg←reg ⊕ imm/reg/mem
XOR mem,imm/reg ; mem←mem ⊕ imm/reg
只有相,异或,的两位不相同,
结果才是 1;否则,结果为 0
XOR
逻辑非指令 NOT
对一个操作数执行逻辑非运算
NOT指令是一个单操作数指令
NOT指令不影响标志位
NOT reg/mem ; reg/mem← ~ reg/mem
按位取反,原来是,0”的位变为,1”;原来是,1”的位变为,0”
NOT
例 1:逻辑运算
mov al,45h ;逻辑与 al=01h
and al,31h ; CF=OF=0,SF=0,ZF=0,PF=0
mov al,45h ;逻辑或 al=75h
or al,31h ; CF=OF=0,SF=0,ZF=0,PF=0
mov al,45h ;逻辑异或 al=74h
xor al,31h ; CF=OF=0,SF=0,ZF=0,PF=1
mov al,45h ;逻辑非 al=0bah
not al ;标志不变例 2:逻辑指令应用; AND指令可用于复位某些位(同 0相与),不影响其他位:将 BL中 D3和 D0位清 0,其他位不变
and bl,11110110B; OR指令可用于置位某些位(同 1相或),不影响其他位:将 BL中 D3和 D0位置 1,其他位不变
or bl,00001001B; XOR指令可用于求反某些位(同 1相异或),不影响其他位:将 BL中 D3和 D0位求反,其他不变
xor bl,00001001B
测试指令 TEST
对两个操作数执行逻辑与运算,结果不回送到目的操作数
AND指令设置 CF = OF = 0,根据结果设置 SF、
ZF和 PF状态,而对 AF未定义
TEST reg,imm/reg/mem ; reg∧ imm/reg/mem
TEST mem,imm/reg ; mem∧ imm/reg
只有相,与,的两位都是 1,结果才是 1;否则,,与,的结果为
0
TEST
例 3:测试为 0或 1
TEST AX,0001H
JZ EVEN_1 ; ZF=1,相等跳转到
EVEN_1
……
EVEN_1:
TEST指令通常用于检测一些条件是否满足,但又不希望改变原操作数的情况
TEST
移位指令 ( shift)
将操作数移动一位或多位,分成逻辑移位和算术移位,
分别具有左移或右移操作
SHL reg/mem,1/CL;逻辑左移,最高位进入 CF,最低位补 0SHR reg/mem,1/CL;逻辑右移,最低位进入 CF,最高位补 0SAL reg/mem,1/CL;算术左移,最高位进入 CF,最低位补 0SAR reg/mem,1/CL;算术右移,最低位进入 CF,最高位不变
SAL与 SHL相同 演示图示移位指令的操作数
移位指令的第一个操作数是指定的被移位的操作数,可以是寄存器或存储单元
后一个操作数表示移位位数,该操作数为 1,表示移动一位;当移位位数大于 1
时,则用 CL寄存器值表示,该操作数表达为 CL
移位指令对标志的影响
按照移入的位设置进位标志 CF
根据移位后的结果影响 SF,ZF,PF
对 AF没有定义
如果进行一位移动,则按照操作数的最高符号位是否改变,相应设置溢出标志 OF:如果移位前的操作数最高位与移位后操作数的最高位不同(有变化),则 OF = 1;否则 OF = 0。当移位次数大于 1时,OF不确定例 4:移位指令
mov cl,4
mov al,0f0h ; al=f0h
shl al,1 ; al=e0h; CF=1,SF=1,ZF=0,PF=0,OF=0
shr al,1 ; al=70h; CF=0,SF=0,ZF=0,PF=0,OF=1
sar al,1 ; al=38h; CF=0,SF=0,ZF=0,PF=0,OF=0
sar al,cl ; al=03h; CF=1,SF=0,ZF=0,PF=1
循环移位指令 ( rotate)
将操作数从一端移出的位返回到另一端形成循环,分成不带进位和带进位,分别具有左移或右移操作
ROL reg/mem,1/CL ;不带进位循环左移
ROR reg/mem,1/CL ;不带进位循环右移
RCL reg/mem,1/CL ;带进位循环左移
RCR reg/mem,1/CL ;带进位循环右移图示图示循环移位指令对标志的影响
按照指令功能设置进位标志 CF
不影响 SF,ZF,PF,AF
如果进行一位移动,则按照操作数的最高符号位是否改变,相应设置溢出标志 OF:如果移位前的操作数最高位与移位后操作数的最高位不同(有变化),则 OF = 1;否则 OF = 0。当移位次数大于 1时,OF不确定
3.2.4 串操作类指令
串操作指令是 8086指令系统中比较独特的一类指令,采用比较特殊的数据串寻址方式,在操作主存连续区域的数据时,特别好用、因而常用重点掌握,MOVS STOS LODS
CMPS SCAS REP
一般了解,REPZ/REPE REPNZ/REPNE
串数据类型
串操作指令的操作数是 主存中连续存放的数据串( String) —— 即在连续的主存区域中,字节或字的序列
串操作指令的 操作对象是以字( W)为单位的字串,或是以字节( B)为单位的字节串串寻址方式
源操作数用寄存器 SI寻址,默认在数据段 DS中,但允许段超越,DS:[SI]
目的操作数用寄存器 DI寻址,默认在附加段 ES中,不允许段超越,ES:[DI]
每执行一次串操作指令,SI和 DI将自动修改:
± 1(对于字节串)或 ± 2(对于字串)
执行指令 CLD指令后,DF = 0,地址指针增 1或 2
执行指令 STD指令后,DF = 1,地址指针减 1或 2
串传送 MOVS( move string)
把字节或字操作数从主存的源地址传送至目的地址
MOVSB;字节串传送,ES:[DI]←DS:[SI]; SI←SI ± 1,DI←DI ± 1
演示
MOVSW;字串传送,ES:[DI]←DS:[SI]; SI←SI ± 2,DI←DI ± 2
演示例 1:字节串传送
mov si,offset source
mov di,offset destination
mov cx,100 ; cx← 传送次数
cld ;置 DF=0,地址增加
again,movsb ;传送一个字节
dec cx ;传送次数减 1
jnz again;判断传送次数 cx是否为 0;不为 0,则到 again位置执行指令;否则,结束
offset是汇编操作符,
求出变量的偏移地址演示例 2:字串传送
mov si,offset source
mov di,offset destination
mov cx,50 ; cx← 传送次数
cld ;置 DF=0,地址增加
again,movsb ;传送一个字
dec cx ;传送次数减 1
jnz again;判断传送次数 cx是否为 0;不为 0,则到 again位置执行指令;否则,结束串存储 STOS( store string)
把 AL或 AX数据传送至目的地址
STOSB;字节串存储,ES:[DI]←AL; DI←DI ± 1
STOSW;字串存储,ES:[DI]←AX; DI←DI ± 2
例 3:串存储
mov ax,0
mov di,0
mov cx,8000h; cx← 传送次数( 32× 1024)
cld ; DF=0,地址增加
again,stosw ;传送一个字
dec cx ;传送次数减 1
jnz again ;传送次数 cx是否为 0
可将 CLD改为 STD吗? 如何改用 STOSB?
可不用给 DI赋值吗?
DI为偶数即可串读取 LODS( load string)
把指定主存单元的数据传送给 AL或 AX
LODSB;字节串读取,AL←DS:[SI]; SI←SI ± 1
LODSW;字串读取,AX←DS:[SI]; SI←SI ± 2
例 4:串读取- 1
mov si,offset block
mov di,offset dplus
mov bx,offset dminus
mov ax,ds
mov es,ax;数据都在一个段中,所以设置 es=ds
mov cx,count ; cx← 字节数
cld
例 5:串读取- 2
go_on,lodsb ;从 block取出一个数据
test al,80h;检测符号位,判断是正是负
jnz minus;符号位为 1,是负数,转向 minus
stosb;符号位为 0,是正数,存入 dplus
jmp again;程序转移到 again处继续执行
jnz go_on ;完成正负数据分离例 6:串读取- 3
minus,xchg bx,di
stosb ;把负数存入 dminus
xchg bx,di
again,dec cx ;字节数减 1
jnz go_on ;完成正负数据分离串比较 CMPS( compare string)
将主存中的源操作数减去至目的操作数,以便设置标志,进而比较两操作数之间的关系
CMPSB;字节串比较,DS:[SI]- ES:[DI]; SI←SI ± 1,DI←DI ± 1
CMPSW;字串比较,DS:[SI]- ES:[DI]; SI←SI ± 2,DI←DI ± 2
例 7:比较字符串
mov si,offset string1
mov di,offset string2
mov cx,count
cld
again,cmpsb ;比较两个字符
jnz unmat ;有不同字符,转移
dec cx
jnz again ;进行下一个字符比较
mov al,0 ;字符串相等,设置 00h
jmp output ;转向 output
unmat,mov al,0ffh ;设置 ffh
output,mov result,al ;输出结果标记串扫描 SCAS( scan string)
将 AL/AX减去至目的操作数,以便设置标志,
进而比较 AL/AX与操作数之间的关系
SCASB;字节串扫描,AL- ES:[DI]; DI←DI ± 1
SCASW;字串扫描,AX- ES:[DI]; DI←DI ± 2
例 8:查找字符串
mov di,offset string
mov al,20h
mov cx,count
cld
again,scasb ;搜索
jz found ;为 0( ZF=1),发现空格
dec cx ;不是空格
jnz again ;搜索下一个字符
..,;不含空格,则继续执行
found,...
重复前缀指令 ( repeat)
串操作指令执行一次,仅对数据串中的一个字节或字量进行操作。但是串操作指令前,都可以加一个重复前缀,实现串操作的重复执行。
重复次数隐含在 CX寄存器中
重复前缀分 2类,3条指令:
配合不影响标志的 MOVS,STOS(和 LODS)指令的 REP前缀
配合影响标志的 CMPS和 SCAS指令的 REPZ和 REPNZ
前缀
REP重复前缀指令
REP前缀可以理解为:当数据串没有结束
( CX≠0),则继续传送
例 1和 例 2中,程序段的最后 3条指令,可以分别替换为:
REP MOVSB 和 REP STOSW
REP ;每执行一次串指令,CX减 1;直到 CX= 0,重复执行结束
REPZ重复前缀指令
REPZ/REPE前缀可以理解为:当数据串没有结束 ( CX≠0),并且串相等 ( ZF= 1),则继续比较
REPZ ;每执行一次串指令,CX减 1;并判断 ZF是否为 0,;只要 CX= 0或 ZF= 0,重复执行结束
REPNZ重复前缀指令
REPNZ/REPNE前缀可以理解为:当数据串没有结束 ( CX≠0),并且串不相等 ( ZF= 0),则继续比较
REPZ ;每执行一次串指令,CX减 1;并判断 ZF是否为 1,;只要 CX= 0或 ZF= 1,重复执行结束例 9:比较字符串
mov si,offset string1
mov di,offset string2
mov cx,count
cld
repz cmpsb ;重复比较两个字符
jnz unmat ;字符串不等,转移
mov al,0 ;字符串相等,设置 00h
jmp output ;转向 output
unmat,mov al,0ffh ;设置 ffh
output,mov result,al ;输出结果标记解释例 10查找字符串
mov di,offset string
mov al,20h
mov cx,count
cld
repnz scasb ;搜索
jz found ;为 0( ZF=1),发现空格
..,;不含空格,则继续执行
found,...