汇编语言串操作指令

  • MOVS(Move String)      串传送

  • CMPS(Compare String)     串比较

  • SCAS(Scan String)      串扫描

  • STOS(Store in to String)    存入串

  • LODS(Load from String)    从串取

串操作指令用以处理内存中的数据串,但该操作每一次执行处理的只是单个字节或字,因此对于数据串来说,需要重复执行串操作指令才能处理完整个串。串操作指令的重复有特定的前缀指令配合,下面先介绍前缀指令:

  • REP(repeat)              重复

  • REPE/REPZ(repeat while equal/zero)     相等/为零则重复

  • REPNE/REPNZ(repeat while not equal/not zero) 不相等/不为零则重复

(1)前缀 REP 的作用是重复执行串操作指令,直到寄存器 CX=0 为止,而每执行一次串操作指令,会使 CX 的内容自动减 1,因此总的重复次数等于 CX 寄存器的初始值。

(2)前缀 REPE 也叫 REPZ,只有当 CX 寄存器的值 ≠0 并且标志位 ZF=1 时,重复执行串操作指令。若用以比较两个字符串是否相等,每次的串操作指令把源串中的一个字节和目的串中的一个字节进行比较,如果相等(即 ZF=1),则还需继续执行串操作指令,若不相等或者比较全部串的数据(CX=0),则停止。

(3)前缀 REPNE 也叫 REPNZ,只有当 CX 寄存器的值 ≠0 并且标志位 ZF=0 时,重复执行串操作指令。若在一个字符串中查找是否存在某一个字符,串操作指令把字符串中的一个字节和要找的这个字符进行比较,如果不相等(即 ZF=0),则还需继续执行串操作指令,直到找到(ZF=1)或者查找完整个串的数据(CX=0),才停止。

以上三种串操作指令的前缀,和下面介绍的串操作指令配合使用,可以完成对数据串的相关操作。

一、MOVS串传送指令

格式有 3 种:

(1)MOVSB:以字节为单位传送;

(2)MOVSW:以字为单位传送;

(3)MOVS DST,SRC:将源串 SRC 传送到目的串 DST 中。

实际上 MOVS 指令的寻址方式是固定的,目的串地址为 ES:[DI],源串地址为 DS:[SI],因此前两种格式都将操作数直接省略了。若采用第三种格式指令,则以字节为单位传送时,可以表示为:

1
MOVS  ES:BYTE PTR[DI],DS:[SI]

目的操作数指出了是字节的传送,如果源串不在数据段,也可加前缀,如 ES:[SI]。但这种格式不够简洁,因而不太常用。

下面只介绍前两种格式的操作:

(1)字节(MOVSB)操作:

(ES:DI)←(DS:SI),DI±1,SI±1

(2)字(MOVSW)操作:

(ES:DI)←(DS:SI),DI±2,SI±2

上述操作中,当方向标志 DF=0 时 SI、DI 用 +;DF=1 时 SI、DI 用 -。方向标志 DF 的设置有两条指令:

  • CLD(clear direction flag)设置正向(向前,使 DF=0,SI 或 DI 自动加)

  • STD(set direction flag)设置反向(向后,使 DF=1,SI 或 DI 自动减)

注意

上述传送指令默认源操作数是 DS 和源变址寄存器 SI 构成的地址,ES 和目的变址寄存器 DI 构成的地址为目的操作数地址,并且通过方向标志指令设置自动变址功能,数据的传送是从内存到内存的传送!不仅是串传送指令,下面介绍的其他串操作指令也具有同样的特点。

因此,为了实现整个串的传送,在使用串操作指令前,应该做好如下准备工作。

① 数据段中的源串首地址(如反向传送则是末地址)送 DS 和 SI。

② 附加段中的目的串首地址(如反向传送则是末地址)送 ES 和 DI。

③ 串长度送计数寄存器 CX。

④ 方向标志 DF。

MOVS 指令可以把由源变址寄存器 SI 指向的数据段中的一个字节(或字)传送到由目的变址寄存器 DI 指向的附加段中的一个字节(或字)中去,同时根据方向标志 DF 及数据格式(字节或字)对源变址寄存器 SI 和目的变址寄存器 DI 进行修改。每次执行 MOVS 操作只能传送数据串中的一个字节或者字,还需要与前缀 REP 联合使用,才可将数据段中的某个串全部传送到附加段中去,如 例 39 所示。

例 39 在数据段中有一个字符串 MESS,其长度为 19,要求把它们转送到附加段中名为 BUFF 的一个缓冲区中,并显示出 BUFF 字符串,编制程序如下所示。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
DATA SEGMENT

MESS  DB  'COMPUTER SOFTWARE $ '

DATA ENDS

EXT SEGMENT

BUFF  DB  19 DUP(?)

EXT ENDS

CODE SEGMENT

ASSUME CS:CODE,DS:DATA,ES: EXT

START:

MOV  AX,DATA      ; 赋段地址

MOV  DS,AX

MOV  AX,EXT

MOV  ES,AX

LEA  SI,MESS      ; 赋偏移地址

LEA  DI,BUFF

MOV  CX,19       ; 串长

CLD            ; 设置DF的方向

REP  MOVSB       ; 完成串传送

MOV  BX,ES       ; 准备显示BUFF字符串

MOV  DS,BX       ; DS:DX指向待显示串的地址

LEA  DX,BUFF

MOV  AH,9

INT  21H

MOV  AH,4CH

INT  21H

CODE ENDS

END START

程序中定义了数据段 DATA,其中用 DB 伪操作定义了字节类型数据串 MESS,串 MESS 中的每个字符占一个字节,以该字符的 ASCII 码存放。定义了附加段 EXT,其中定义的串 BUFF 的长度由 DUP 操作符开辟了 19 个字节空间,没有赋值。

程序运行过程可以用图 18 来说明。

(a)预置情况

图 18(a)预置情况

(b)执行一次 MOVSB 以后

图 18(b)执行一次 MOVSB 以后

(c)执行完 REP MOVSB 以后

图 18(c)执行完 REP MOVSB 以后

二、CMPS 串比较指令

格式有 3 种:

(1)CMPSB(字节);

(2)CMPSW(字);

(3)CMPS DST,SRC。

和串传送指令相同,串比较指令也是涉及两个串,目的串地址为 ES:[DI],源串地址为 DS:[SI]。只介绍常用的2种格式,其操作如下:

(1)字节(CMPSB)操作:

(ES:DI)-(DS:SI),DI±1,SI±1

(2)字(CMPSW)操作:

(ES:DI)-(DS:SI),DI±2,SI±2

本条串操作指令把两个串的对应位置的字节或字相减,不保存结果,只是根据结果设置标志位。该指令与前缀 REPE 联用时,可比较两个串是否相等。在每次比较过程中,一旦发现不相等,ZF=0,则终止重复执行,而不必等到整个串全部比较结束,此时 CX≠0,ZF=0。该指令终止执行后,可根据标志 ZF 判断两个串是否相等。其他指令格式与串传送指令相同。

例 40 在数据段中有一个长度为 19 的字符串 MESS1,还有一个长度为 19 的字符串 MESS2,比较它们是否相等。若相等显示‘Y',否则显示‘N'。编制程序如下所示。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
DATA SEGMENT

MESS1  DB  'COMPUTER SOFTWARE $ '

MESS2  DB  'COMKUTER SOFTWARE $ '

DATA ENDS

CODE SEGMENT

ASSUME CS:CODE,DS:DATA

START:

MOV  AX,DATA

MOV  DS,AX

MOV  ES,AX     ; DS=ES

LEA  SI,MESS1

LEA  DI,MESS2

MOV  CX,19     ; 串长

CLD         ; 设置DF方向

REPE  CMPSB     ; 当CX=0或者ZF=1时,比较结束

JZ  YES      ; 如果ZF=1,说明相等,跳转到标号YES

MOV  DL,'N'    ; 两串不相等

JMP  DISP      ; 跳转到标号DISP

YES: MOV  DL,'Y'

DISP: MOV  AH,2

INT  21H

MOV  AH,4CH

INT  21H

CODE ENDS

END START

程序运行过程可以用图 19 来说明。

程序运行情况

图 19 程序运行情况

三、SCAS 串扫描指令

格式有 3 种:

(1)SCASB(字节);

(2)SCASW(字);

(3)SCAS DST。

串扫描指令只涉及一个目标串,因而由 ES:[DI] 指定串的地址好理解也便于记忆,默认源操作数为 AL(字节)或 AX(字)。其对应的操作如下:

(1)字节(SCASB)操作:

AL-(ES:DI),DI±1

(2)字(SCASW)操作:

AX-(ES:DI),DI±2

串扫描指令是把 AL/AX 寄存器中的内容与附加段中的由目的变址寄存器 DI 所指向的内存单元内容相比较,与 CMPS 比较指令相似,并不保存结果,只是根据结果设置标志位。该指令与前缀 REPNE 联用时,可在目的串中查找有无和 AL/AX 寄存器中的内容相同的字节或字。在每次执行串扫描指令过程中,一旦发现相等,即 ZF=1,则终止执行,此时 CX≠0,ZF=1,说明已找到相同的内容,而不必等到整个串全部扫描结束。该指令终止执行后,可根据标志位 ZF 判断是否找到。指令相关格式要求同串传送指令。

例 41 在附加段中有一个字符串 MESS,其长度为 19,要求查找其中有无空格符,若有空格符,把首次发现的空格符改为‘#',存回该单元,并显示‘Y',否则显示‘N'。编制程序如下所示。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
EXT  SEGMENT

MESS  DB  'COMPUTER SOFTWARE $ '

EXT  ENDS

CODE SEGMENT

ASSUME CS:CODE,ES:EXT

START:

MOV  AX,EXT

MOV  ES,AX

LEA  DI,MESS

MOV  CX,19

MOV  AL,20H    ; 空格符

CLD

REPNE SCASB

JZ  YES      ; 如果ZF=1跳转到标号YES

MOV  DL,'N'

JMP  DISP      ; 跳转到标号DISP

YES: DEC  DI

MOV  BYTE PTR ES:[DI],23H  ; '#’送原空格位置

MOV  DL,'Y'

DISP: MOV  AH,2

INT  21H

MOV  AH,4CH

INT  21H

CODE ENDS

END START

程序运行过程如图 20 所示。

程序运行情况

图 20 程序运行情况

四、STOS 串存入指令

格式有 3 种:

(1)STOSB(字节)

(2)STOSW(字)

(3)STOS DST

该指令的格式与 SCAS 的指令格式相同,其操作如下:

(1)字节(STOSB)操作:

(ES:DI)←AL,DI±1

(2)字(STOSW)操作:

(ES:DI)←AX,DI±2

该指令把 AL/AX 寄存器的内容存入由目的变址寄存器指向的附加段的某单元中,并根据 DF 的值及数据类型修改目的变址寄存器的内容。当它与 REP 联用时,可把累加器的内容存入一个连续的内存缓冲区,该缓冲区长度由 CX 指定,因此 STOS 串指令可用于初始化某一块内存区。上述有关串处理指令的特性也适合本指令。

例 42 写出把附加段 EXT 中的首地址为 MESS,长度为 9 个字的缓冲区置为 0 值的程序片段。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
MOV  AX,EXT

MOV  ES,AX

LEA  DI,MESS

MOV  CX,9

MOV  AX,0

CLD

REP  STOSW

注意

REP STOSW 是字操作,每次执行时 DI 自动 +2。其运行结果如图 21 所示。

STOSW 程序运行结果

图 21 STOSW 程序运行结果

五、LODS 从串中取数指令

格式有 3 种:

(1)LODSB  (字节);

(2)LODSW (字);

(3)LODS SRC。

该指令只涉及一个源串,由 DS:[SI] 指定,其操作如下:

(1)字节(LODSB)操作:

AL←(DS:SI),SI±1

(2)字(LODSW)操作:

AX←(DS:SI),SI±2

该指令意义不大,一般不和 REP 联用,因为重复执行多次的结果也只是使累加器为最后一次的值。该指令可以由 MOV 指令代替。

本节介绍了多个串操作指令,与串前缀配合使用,可以完成多种串操作,表 2 列出了有关串处理指令的特性及用法。

串处理指令特性及用法

表 2 串处理指令特性及用法

请参阅

(完)

comments powered by Disqus