串和串操作

来源:互联网 发布:广告公司软件免费版 编辑:程序博客网 时间:2024/06/05 04:17

一、概述< xmlnamespace prefix ="o" ns ="urn:schemas-microsoft-com:office:office" />

    1)串和串操作

    存储器中的地址连续的若干单元的字符或数据称为字符串或数据串。串操作指令就是用来对串中每个字符或数据进行操作的指令。

    串指令既可处理字节串,也可处理字串,并在每完成一个字节(或字)的操作后,能够自动修改指针,以便执行下一个字节(或字)的操作。

    串指令可完成两个存储单元之间的传送和比较操作(也只有串指令才可以)。

    2)串操作的共同点

    l 源串(源操作数)默认在数据段中:段基地址由DS指定(但允许段超越),偏移地址由SI指定。即源串指针为DS:SI

    l 目的串(目的操作数)默认在附加段中,段基地址由ES指定,偏移地址由DI指定。即目的串指针为ES:DI

    l 若要使用重复前缀,则应把串长度放在CX中;

    l 在对串中的每个字节(或字)操作后,SIDI中的串地址都会自动修改:±1±2。其中±由方向标志DF决定:若DF=0,取“+”;若DF=1,取“-”。增减量大小由操作数类型决定:字节操作增减量为1,字操作增减量为2。若使用了重复前缀,CX的内容也会每次自动减1

    3)串指令的操作
   
执行规定的操作;

    SI和(或)DI自动增量(或减量);
   
若有重复前缀,CX自动减1

    由上可知,使用串操作指令之前应该设置:方向标志(DF)、源串指针(DS:SI)、目的串指针(ES:DI)和重复次数(CX)。

    显然,串操作指令可以处理的最大串长度为65535字节(或字)。

    [top]

二、重复操作前缀

    串操作指令前面允许带有一个重复操作前缀(简称重复前缀),使该指令能重复执行。重复前缀使得串操作指令在每完成一次操作后自动修改CX的值,直到CX=0或满足指定的条件为止。重复前缀包括:

    REP           CX≠0时重复执行指令规定的操作(无条件重复前缀)

    REPE/REPZ     CX≠0ZF=1时重复执行指令规定的操作

    REPNE/REPNZ   CX≠0ZF=0时重复执行指令规定的操作

    重复前缀可单独写为一行,也可写在串指令前面(但要用空格分开)。

    使用重复前缀可简化程序的编写,并加快串运算指令的执行速度。

    [top]

三、串操作指令

    8086指令系统共有5条串操作指令:串传送MOVS、串比较CMPS、串扫描SCAS、串装入LODS、串存储STOS

    1. 串传送指令 MOVS

    【格式】

        MOVSB

      MOVSW

      MOVS  destsrc

    【功能及操作】

    串传送指令完成两个存储单元之间的数据传送。

    “MOVSB”指令将DS:SI所指向的存储单元中的一个字节传送到ES:DI所指向的存储单元。若DF=0,则传送后SIDI都加1;若DF=1,则传送后SIDI都减1

    “MOVSW”指令将DS:SI所指向的存储单元中的一个字传送到ES:DI所指向的存储单元。若DF=0,则传送后SIDI都加2;若DF=1,则传送后SIDI都减2

    “MOVS destsrc”指令视操作数类型(字节或字)与“MOVSB”“MOVSW”等价。

    【使用】

    上述三种格式的串传送指令在执行前都需要预先设置地址指针DS:SIES:DI,设置传送方向,如果要重复执行,还需把重复次数放入CX并使用重复前缀。

    MOVS指令常与重复前缀REP联合使用,以简化程序,提高程序运行速度。

    点击观看MOVS指令动画演示。

    【例1】将2000H:1200H地址开始的200个字节传送到6000H:2000H开始的存储单元中。程序段如下:
        MOV  AX
2000H 
        MOV  DS
AX      ;设置源串段地址
        MOV  AX
6000H 
        MOV  ES
AX      ;设置目的串段地址
        MOV  SI
1200H   ;设置源串偏移地址
        MOV  DI
2000H   ;设置目的串偏移地址
        MOV  CX
100     ;串长度送CX
        CLD              ;DF
0,方向为从低地址到高地址

        REP  MOVSB       ;每次传送一个字节,并自动修改地址指针及CX内容

                         ;若修改后CX≠0就重复执行

    [top][top1]

    2. 串比较指令 CMPS

    【格式】

        CMPSB

      CMPSW

      CMPS  destsrc

    【功能及操作】

    串比较指令与比较指令CMP的操作有点类似,CMP指令是对两个单个数据进行比较,而CMPS是对两个数据串进行比较。

    “CMPSB”指令将源存储单元(DS:SI)中的一个字节与目的存储单元(ES:DI)中的一个字节相减,根据结果设置标志位,但不保存结果。若DF=0,则比较后SIDI都加1;若DF=1,则比较后SIDI都减1

    “CMPSW”指令将源存储单元(DS:SI)中的一个字与目的存储单元(ES:DI)中的一个字相减,根据结果设置标志位,但不保存结果。若DF=0,则传送后SIDI都加2;若DF=1,则传送后SIDI都减2

    “CMPS destsrc”指令视操作数类型(字节或字)与“CMPSB”“CMPSW”等价。

    【使用】

    上述三种格式的串比较指令在执行前都需要预先设置地址指针DS:SIES:DI,设置方向标志位,如果要重复执行,还需把重复次数放入CX并使用重复前缀。

    串比较指令通常和条件重复前缀REPEREPZ)或REPNEREPNZ)连用,用来检查两个字符串是否相等。

    点击观看CMPS指令动画演示。

    【例2】比较字符串STR1和字符串STR2是否相同,如果不同,将STR1中不相等字符的地址送BX。两个字符串的长度均为200个字节。

        程序如下:(假定DSES已设置好)

        LEA  SISTR1    ;SI源串首地址
        LEA  DI
STR2    ;DI目的串首地址
        MOV  CX
200     ;CX串长度

        CLD              ;DF0,增地址方向

        REPZ CMPSB       ;对两个串逐个字符进行比较,直到遇到不同的字符或比较完

        JZ   STOP        ;若所有字符都相同,则转STOP
        DEC  SI          ;
否则,使SI指向不相等的字符(CMPS指令已对SI自动加1
        MOV  BX
SI      ;BX不相等单元的地址
  STOP
...

    [top][top1]

    3. 串扫描指令 SCAS

    【格式】

        SCASB

      SCASW

      SCAS  dest

    【功能及操作】

    SCAS指令将累加器AL(或AX)的内容与目的串(指针为ES:DI)中的字节(或字)进行比较,比较结果不改变目的操作数,只影响标志位。它执行与CMPS指令同样的不回送结果的减法操作,只是这里源操作数为AL(或AX)。

    “SCASB”指令将AL的内容与目的存储单元(ES:DI)中的一个字节相减,根据结果设置标志位,但不保存结果。若DF=0,则比较后DI1;若DF=1,则比较后DI1

    “SCASW”指令将AX的内容与目的存储单元(ES:DI)中的一个字相减,根据结果设置标志位,但不保存结果。若DF=0,则传送后DI2;若DF=1,则传送后DI2

    “SCAS destsrc”指令视操作数类型(字节或字)与“SCASB”“SCASW”等价。

    【使用】

    上述三种格式的串扫描指令在执行前都需要预先设置AL(或AX)、目的串指针ES:DI,方向标志位DF,如果要重复执行,还需把重复次数放入CX并使用重复前缀。

    串扫描指令通常和条件重复前缀REPEREPZ)或REPNEREPNZ)连用,用来在字符串中搜索某个特定的关键字(把要查找的关键字放在AL(或AX),再用本指令与字符串中各字符逐一比较)。

    【例3】从ES:2000H单元开始存放了一个长度为100的字符串,寻找其中有无字符“S”。若有则记下扫描次数(次数放CNT单元),并记下存放“A”的地址(地址放ADDR单元)。程序段如下:

        MOV  DI2000H    ;DI目的串首地址
        MOV  CX
100      ;CX串长度
        MOV  AL
"S"      ;AL关键字“S”
        CLD               ;DF
0,增地址方向
        REPNZ SCASB       ;
扫描字符串,直到找到“S”或扫描结束
        JZ   FOUND        ;
若找到则转移

        MOV  DI0        ;没找到,使DI=0
        JMP  DONE
FOUND
DEC  DI           ;使DI指向找到的“S”字符(SCAS指令已对DI自动加1
        MOV  ADDR
DI     ;“S”字符的地址送ADDR单元 
        SUB  DI
2000H    ;“S”字符的地址减去首地址得到扫描次数
 DONE
MOV  CNTDI      ;将搜索次数送CNT单元

    本例中,重复前缀REPNZ表示未找到字符“S”且扫描未结束(CX≠0)时,就继续搜索。若此例改为查找第一个不是“S”的字符,则重复前缀应使用REPZ,表示找到字符“S”且扫描未结束(CX≠0)时,就继续搜索。

    本例中,由于使用了条件重复前缀(REPNZ)从而使得退出串扫描循环的原因有两种可能:一种是找到“S”而退出,此时ZF=l。另一种可能是直到串扫描结束都没找到“S”而退出,此时ZF=0CX=0。因而退出之后,可根据ZF标志来判断是属于哪种情况。

    另外,每执行一次SCAS,目的串指针DI都会自动加1,所以找到“S”字符后,需将DIl才能得到“S”字符的地址。

    [top][top1]

    4. 串装入指令 LODS

    【格式】

        LODSB

      LODSW

      LODS  src

    【功能及操作】

    “LODSB”(或“LODSW”)指令把由DS:SI指向的源串中的字节(或字)装入到AL(或AX)中,并根据DF自动修改指针SI,以指向下一个要装入的字节(或字)。

    “LODS src”指令视操作数类型(字节或字)与“LODSB”“LODSW”指令等价。

    字节装入指令LODSB等价于以下两条指令组合:

        MOV  AL[SI]

        INC  SI       ; DEC  SI(当DF=1

    字装入指令LODSW等价于以下三条指令组合:

        MOV  AL[SI]

        INC  SI       ; DEC  SI(当DF=1

        INC  SI       ; DEC  SI(当DF=1

    【使用】

    上述三种格式的串装入指令在执行前都需要预先设置源串指针DS:SI和方向标志DFLODS指令一般不使用重复前缀,因为每重复一次ALAX中内容将被后一次所装入的字符所取代,前一次装入的内容被复盖。

    【例4】以MEM1为首地址的存储器中有10个字节数据,编写程序将这10个数都乘2

        (假定DS已设置好)
        LEA  SI
MEM1   ;SI源串首地址
        MOV  CX
10     ;CX串长度
        CLD             ;DF
0
  NEXT
LODSB           ;取一个数据到AL
        ADD  AL
AL     ;2

        MOV  [SI-1]AL ;存回去

        DEC  CX         ;CXCX-1
        JNZ  NEXT       ;CX≠0
则继续

        ...

    [top][top1]

    5. 串存储指令 STOS

    【格式】

        STOSB

      STOSW

      STOS  dest

    【功能及操作】

    “STOSB”(或“STOSW”)指令把AL(或AX)中的内容存储到由ES:DI指向的目的串中,并根据DF自动修改指针DI,以指向下一个要写入的字节(或字)存储单元。

    “STOS src”指令视操作数类型(字节或字)与“STOSB”“STOSW”指令等价。

    字节装入指令STOSB等价于以下两条指令组合:

        MOV  ES:[DI]AL

        INC  DI       ; DEC  DI(当DF=1

    字装入指令STOSW等价于以下三条指令的组合:

        MOV  ES:[DI]AX

        INC  DI       ; DEC  DI(当DF=1

        INC  DI       ; DEC  DI(当DF=1

    【使用】

    上述三种格式的串存储指令在执行前都需要预先设置AL(或AX)、目的串指针DS:SI和方向标志DF。利用重复前缀REP,可对连续的存储单元写入相同的值。

    本指令常用于对某一存储区域进行初始化(初值在放AL(AX)中)。

    【例5】把6000H:1200H开始的100个字节存储单元全部设置为55H
        MOV  AX
6000H
        MOV  ES
AX      ;ES目的串的段地址
        MOV  DI
1200H   ;DI目的串的偏移地址
        MOV  CX
100     ;CX串长度
        CLD              ;DF
0,增地址方向

        MOV  AL55H     ;AL55H
        REP  STOSB       ;
100个单元都写入55H

    [top][top1]

四、串指令使用总结

 

指令

源操作数

目的操作数

重复前缀

指针增减

默认

允许的段超越

MOVS

DS:SI

ESSSCS

ES:DI

REP

DF=0:增量

DF=1:减量

字节:±1

字:±2

CMPS

DS:SI

ESSSCS

ES:DI

REPZREPNZ

SCAS

AL/AX

-

ES:DI

REPZREPNZ

LODS

DS:SI

ESSSCS

AL/AX

-

STOS

AL/AX

-

ES:DI

REP

    使用串指令的程序段结构如下:

      ...

      设置源串指针(DS,SI

      设置目的串指针(ES,DI

      设置重复操作次数(CX--仅执行1次时可省略

      设置操作方向(DF

      重复前缀(REP/REPZ/REPNZ--仅执行1次时可省略

      串操作指令(MOVS/CMPS/SCAS/LODS/STOS