0%

8086指令基础 - 串指令

最近在学习 16位汇编编程,所以顺便将每日所学记录下来,一方面为了巩固学习的知识,另一方面也为同样在学习汇编开发的童鞋们提供一份参考。

运行环境:

  • 操作系统: Windows 10家庭版
  • 编译器:Windows XP Debug

串指令

串操作指令是8086系统中比较独特的一类指令,采用比较特殊的数据串寻址方式,在操作主存连续区域的数据时,特别好用;

重点掌握:MOVS STOS LODS CMPS SCAS REP

一般了解:REPZ ERPE ERPNZ REPNE

串数据类型

  • 串操作指令的操作数是主存中连续存放的数据串(String),即在连续的主存区域中,字节或字的序列
  • 串操作指令的操作对象是以字(WORD)为单位的字串,或是以字节(BYTE)为单位的字节串

串寻址方式

  • 源操作数用寄存器SI寻址,默认在数据段DS中,但允许段超越;(DS:[SI])
  • 目的操作数用寄存器DI寻址,默认在附加段ES中,不允许段超越;
  • 每执行一次串操作指令,SI和DI将自动修改
    • 执行指令CLD指令后,DF = 0,地址指针增1或2
    • 执行指令STD指令后,DF = 1,地址指针减1或2

串传送

MOVS

把字节或字操作数从主存的源地址传送至目的地址

1
2
3
4
5
6
MOVSB
;字节串传送:ES:[DI]←DS:[SI]
;SI←SI±1,DI←DI±1
MOVSW
;字串传送:ES:[DI]←DS:[SI]
;SI←SI±2,DI←DI±2

demo:

1
2
3
4
5
0B26:0100 FC            CLD
0B26:0101 BE0020 MOV SI,2000 ;地址偏移2000的位置是拷贝的地址
0B26:0104 BF0030 MOV DI,3000 ;地址偏移3000的位置是目的地址
0B26:0107 A4 MOVSB ;每次传送的字节为byte1字节
0B26:0108 A5 MOVSW ;每次传送的字节为word2字节

串存储

STOS

将AL或AX数据传送到目的地址

1
2
3
4
5
6
STOSB
;字节串存储:ES:[DI]←AL
;DI←DI±1
STOSW
;字串存储:ES:[DI]←AX
;DI←DI±2

demo:

1
2
3
4
5
6
0B26:0100 FD            STD
0B26:0101 B80000 MOV AX,0000
0B26:0104 BF0020 MOV DI,2000
0B26:0107 AA STOSB
0B26:0108 AB STOSW
0B26:0109 C3 RET

串读取

LODS

把指定贮存单元的数据传送给AL或AX

1
2
3
4
5
6
LODSB
;字节串读取:AL←DS:[SI]
;SI←作用SI±1
LODSW
;字串读取:AX←DS:[SI]
;SI←SI±2

demo:

1
2
3
4
5
0B26:0100 FC            CLD
0B26:0101 BE0020 MOV SI,2000
0B26:0104 AC LODSB
0B26:0105 AD LODSW
0B26:0106 C3 RET

串比较

CMPS

将主存中的源操作数减去至目的操作数,以便设置标志,进而比较两操作数之间的关系

1
2
3
4
5
6
CMPSB
;字节串比较:DS:[SI]-ES:[DI]
;SI←SI±1,DI←DI±1
CMPSW
;字串比较:DS:[SI]-ES:[DI]
;SI←SI±2,DI←DI±2

demo:

1
2
3
4
5
6
0B26:0100 FC            CLD
0B26:0101 BE0020 MOV SI,2000
0B26:0104 BF0620 MOV DI,2006
0B26:0107 A6 CMPSB
0B26:0108 A7 CMPSW
0B26:0109 C3 RET

如果在debug中做实现需要使用e指令来修改内存

串扫描

SCAS

将AL/AX减去至目的操作数,以便设置标志,进而比较AL/AX与操作数之间的关系

1
2
3
4
5
6
SCASB   
;字节串扫描:AL-ES:[DI]
;DI←DI±1
SCASW
;字串扫描:AX-ES:[DI]
;DI←DI±2

demo:

1
2
3
4
5
6
0B26:0100 FC            CLD
0B26:0101 B000 MOV AL,00
0B26:0103 BF0020 MOV DI,2000
0B26:0106 AE SCASB
0B26:0107 AF SCASW
0B26:0108 C3 RET

重复前缀指令

repert

  • 串操作指令执行一次,仅对数据串中的一个字节或字量进行操作。但是串操作指令前,都可以加一个重复前缀,实现串操作的重复执行。重复次数隐含中CX寄存器中;
  • 重复前缀分两类,三条指令
    • 配置不影响标志的MOVS、STOS(和LODS)指令的REP前缀
    • 配合影响标志的CMPS和SCAS指令的REPZ和REPNZ前缀

简单理解即为:当数据串没用结束(CX!=0),则继续传送

repz

  • 每执行一次串指令,CX减1
  • 并判断ZF是否为0
  • 只要CX=0或ZF=0,重复执行操作

REPZ和REPE前缀可以理解为:当数据串没有结束(CX!=0),并且串相等(ZF=1),则继续比较

1
2
3
4
5
6
7
0B26:0100 FC            CLD
0B26:0101 B90500 MOV CX,0005 ;拷贝5字节数据
0B26:0104 BE0030 MOV SI,3000 ;拷贝到3000的偏移处
0B26:0107 BF0020 MOV DI,2000 ;从偏移2000处开始拷贝
0B26:010A F3 REPZ ;重复拷贝
0B26:010B A4 MOVSB ;按字节拷贝
0B26:010C C3 RET

REPNZ

  • 每执行一次串指令,CX减1
  • 并判断ZF是否为1
  • 只要CX=0或ZF=1,重复执行操作

REPNZ和REPNE前缀可以理解为:当数据串没有结束(CX!=0),并且串相等(ZF=0),则继续比较

1
2
3
4
5
6
0B26:0101 BE0020        MOV     SI,2000
0B26:0104 BF0030 MOV DI,3000
0B26:0107 B91000 MOV CX,0010
0B26:010A F2 REPNZ
0B26:010B A6 CMPSB
0B26:010C C3 RET