核心提示:5.2.10 条件设置字节指令条件设置字节指令(Set Byte Conditionally)是80386 及其以后CPU 所具有的一组指令。它们在测试条件方面与条件转移是一致的,但在功能方 面,它们不是转移,而是根据测试条件的值来设置其字节操作数的内容为1 或0 。条件设置
字节指令的一般格式如下:SETnn... 5.2.10 条件设置字节指令
条件设置字节指令(Set Byte Conditionally) 是80386及其以后CPU 所具有的一组指令。它 们在测试条件方面与条件转移是一致的,但在功能方面,它们不是转移,而是根据测试条件 的值来设置其字节操作数的内容为1或0 。 条件设置字节指令的一般格式如下: SETnn Reg/Mem ;80386+
其中:nn是表示测试条件的(见表5.4) ,操作数只能是8 位寄存器或一个字节单元。 这组指令的执行不影响任何标志位。 表5.4 条件设置字节指令列表
指令的助忆符操作数和检测条件之间的关系 SETZ/SETE Reg/Mem = ZF
SETNZSETNE Reg/Mem = not ZF SETS Reg/Mem = SF
SETNS Reg/Mem = not SF SETO Reg/Mem = OF
SETNO Reg/Mem = not OF SETP/SETPE Reg/Mem = PF
SETNP/SETPO Reg/Mem = not PF SETC/SETB/SETNAE Reg/Mem = CF SETNC/SETB/SETAE Reg/Mem = not CF SETNA/SETBE Reg/Mem = (CF or ZF) SETA/SETNBE Reg/Mem = not (CF or ZF) SETL/SETNGE Reg/Mem = (SF xor OF) SETNL/SETGE Reg/Mem = not (SF xor OF) SETLE/SETNG Reg/Mem = (SF xor OF) or ZF
SETNLE/SETG Reg/Mem = not ((SF xor OF) or ZF)
例5.19 编写程序段:检测寄存器 EAX的8 个16 进制中有几个0H,并把统计结果存入 BH中。 解:
方法1 :用条件转移指令来实现 XOR BH, BH
MOV CX, 8 ;测试寄存器EAX——8次
TEST AL, 0FH ; 测试低四位二进制是否为0H again: JNZ next INC BH
ROR EAX, 4 ; 循环向右移四位,为测试高四位作准备 LOO P
again
方法2 :用条件设置字节指令来实现 XOR BH, BH next:
MOV CX, 8 ;测试寄存器EAX——8次
TEST AL, 0FH ; 测试低四位二进制是否为0H
SETZ BL ; 如果AL的低四位是0 ,则 BL置为1,否则,BL为0 ADD BH, BL ROR EAX, 4 again: LOO P again
5.2.11 字符串操作指令
字符串操作指令的实质是对一片连续存储单元进行处理,这片存储单元是由隐含指针
DS:SI或ES:DI 来指定的。字符串操作指令可对内存单元按字节、字或双字进行处理,并能 根据操作对象的字节数使变址寄存器SI(和DI) 增减1 、2 或4。具体规定如下: (1)、当DF=0时,变址寄存器SI(和DI)增加1 、2 或4; (2)、当DF=1时,变址寄存器SI(和DI)减少1 、2 或4。
在后面各指令中,有关变址寄存器都按上述规定进行增减,不再一一说明。 1 、取字符串数据指令(Load String Instruction)
从由指针DS:SI所指向的内存单元开始,取一个字节、字或双字进入AL、AX或EAX 中,并根据标志位DF对寄存器SI 作相应增减。该指令的执行不影响任何标志位。 指令的格式:LODS 地址表达式 LODSB/LODSW
LODSD ;8 0386+
在指令LODS 中,它会根据其地址表达式的属性来
决定读取一个字节、字或双字。即:当该地址表达式的 属性为字节、字或双字时,将从指针DS:SI处读一个字 节到AL中,或读一个字到 AX,或读一个双字到 EAX 中,与此同时,SI 还将分别增减1 ,2 或4 。
其它字符串指令中的“地址表达式”作用与此类似,将不再说明。 2 、置字符串数据指令(Store String Instruction) 该指令是把寄存器AL、AX 或EAX中的值存于
以指针ES:DI 所指向内存单元为起始的一片存储单元 里,并根据标志位 DF对寄存器DI作相应增减。该指 令不影响任何标志位。
指令的格式:STOS 地址表达式 STOSB/STOSW
STOSD ;80386+
3 、字符串传送指令(Move String Instruction)
该指令是把指针DS:SI 所指向的字节、字或双字传送给指针ES:DI 所指向内存单元,并 根据标志位DF对寄存器DI和SI 作相应增减。该指令的执行不影响任何标志位。 指令的格式:MOVS 地址表达式1, 地址表达式2 MOVSB/MOVSW
MOVSD ;80386+
4 、输入字符串指令(Input String Instruction)
该指令是从某一指定的端口接受一个字符串,并存入一片存储单元之中。输入端口由 DX指定,存储单元的首地址和读入数据的个数分别由 ES:DI 和CX来确定。在指令的执行 过程中,还根据标志位DF对寄存器DI作相应增减。该指令不影响任何标志位。 与指令有关的操作数ES、DI、DX和CX等都是隐含操作数。 指令的格式:INS 地址表达式 INSB/INSW
INSD ;80286+
5 、输出字符串指令(Output String Instruction)
该指令是把一个字符串输入到指定的输出端口中。输出端口由 DX指定,其输出数据的 首地址和个数分别由DS:SI和CX来确定。在指令的执行过程中,还根据标志位 DF对寄存 器SI 作相应增减。该指令的执行不影响任何标志位。
与指令有关的操作数DS、SI 、DX和CX等都是隐含操作数。 指令的格式:OUTS 地址表达式 OUTSB/OUTSW
OUTSD ;80286+
6 、字符串比较指令(Compare String Instruction) 该指令是把指针DS:SI 和ES:DI 所指向字节、字或
双字的值相减,并用所得到的差来设置有关的标志位。 与此同时,变址寄存器SI 和DI也将根据标志位DF的 值作相应增减。
指令的格式:CMPS 地址表达式1, 地址表达式 2
CMPSB/CMPSW
CMPSD ;80386+
受影响的标志位:AF、CF、OF、PF、SF和ZF
7 、字符串扫描指令(Scan String Instruction)
该指令是用指针ES:DI 所指向字节、字或双字的值与相应的 AL、AX或EAX的值相减, 用所得到的差来设置有关标志位。与此同时,变址寄存器 DI还将根据标志位DF的值进行增 减。
指令的格式:SCAS 地址表达式1 SCASB/SCASW
SCASD ;80386+
受影响的标志位:AF、CF、OF、PF、SF和ZF
8 、重复字符串操作指令(Repeat String Instruction)
前面介绍了七种不同的字符串操作指令:取字符串数据、置字符串数据、字符串传送、 输入字符串、输出字符串、字符串比较和字符串扫描等指令,所叙述是这些指令执行一次所 具有的功能。但我们知道:每个字符串通常会有多个字符的,所以,就需要重复执行这些 字符串操作指令。为了满足这种需求,指令系统提供了一组重复前缀指令。
虽然在这些字符串指令的前面都可以添加一个重复前缀指令,但由于指令执行结果的差 异,对某个具体的字符串指令又不用重复前缀指令而改用其它循环来实现重复的需要。 重复字符串操作指令对标志位的影响是由被重复的字符串操作指令来决定。 重复前缀指令REP(Repeat String Instruction)
重复前缀指令是重复其后的字符串操作指令,重复的次数由CX来决定。其一般格式为: REP LODS/LODSB/LODSW/LODSD REP STOS/STOSB/STOSW/STOSD REP MOVS/MOVSB/MOVSW/MOVSD REP INS/ INSB/INSW/INSD
REP OUTS/OUTSB/OUTSW/OUTSD
重复前缀指令的执行步骤如下: (1)、判断:CX=0;
(2)、如果CX=0,则结束重复操作,执行程序中的下一条指令;
(3)、否则,CX=CX-1(不影响有关标志位),并执行其后的字符串操作指令,在该指 令执行完后,再转到步骤(1)。
从上面的重复前缀指令格式来看,虽然我们可以使用重复取字符串数据指令( 第一组指 令),但可能会因为指令的执行结果而在程序中几乎不被使用。
例5.20 编写一段程序,计算字符串“12345abcdefgh”中字符的ASCII 之和。 解: ? M ES S
DB '12345abcdefgh' ; 在数据段中进行变量说明 ? M O V
AX, SEG MESS M O V
DS, AX LE
A
SI, MESS ; 用DS:SI来指向字符串的首地址 M O V
CX, 13D ; 重复次数 X OR
BX, BX ; 置求和的初值为0 RE P
LODSB
?
虽然指令“REP LODSB”能从字符串中取出每个字符,但它是在一条指令中完成的,程 序的其它指令根本无法处理每次取出的数据,指令的执行结果是:AL只保存最后一次所取 出的字符'h' 的ASCII 码。
所以,为了实现本例的要求,不能使用重复前缀指令,而要把指令“REP LODSB”改写 成如下四条指令: X OR
AH, AH ; 为后面的累加作准备 LODSB A D D
BX, AX ;AL是被取出的字符,AH已被清0 again: LO OP again
条件重复前缀指令(Repeat String Conditionally)
条件重复前缀指令与前面的重复前缀指令功能相类似,所不同的是:其重复次数不仅由 CX来决定,而且还会由标志位 ZF来决定。根据 ZF所起的作用又分为二种:相等重复前缀 指令REPE/REPZ和不等重复前缀指令REPE/REPZ。 A、相等重复前缀指令的一般格式为: REPE/REPZ SCAS/SCASB/SCASW/SCASD REPE/REPZ CMPS/CMPSB/CMPSW/CMPSD 该重复前缀指令的执行步骤如下: (1)、判断条件:CX≠0 且 ZF=1 ;
(2)、如果条件不成立,则结束重复操作,执行程序中的下一条指令;
(3)、否则,CX=CX-1(不影响有关标志位),并执行其后的字符串操作指令,在该指 令执行完后,再转到步骤(1)。