6.5 字符串指令与前缀
在 8086 术语中,字符串(string)是连续的字节或字序列。它既可以保存文本,也可以保存数字、像素或其他数据。字符串指令通过隐含操作数节省编码空间:助记符不会列出所有寄存器,但硬件会遵循固定规则。
一条字符串指令处理一个元素
字节形式让指针移动 1,字形式让指针移动 2:
MOVSB/MOVSW从 DS:[SI] 复制到 ES:[DI]。
LODSB/LODSW把 DS:[SI] 装入 AL 或 AX。
STOSB/STOSW把 AL 或 AX 保存到 ES:[DI]。
CMPSB/CMPSW比较 DS:[SI] 与 ES:[DI],并像减法一样设置标志。
SCASB/SCASW比较 AL 或 AX 与 ES:[DI],并设置标志。
方向标志(direction flag,DF)决定处理一个元素后的指针移动方向:
- DF=0 表示向前:SI 和/或 DI 增加。
CLD清除 DF。
- DF=1 表示向后:SI 和/或 DI 减少。
STD设置 DF。
例如 DS:[SI] 保存 34H,ES:[DI] 保存 00H,DF=0。执行一次 MOVSB 会把 34H 写入 ES:[DI],然后让 SI 与 DI 都加 1。MOVSB 自身不会改变 CX。
对于原始 8086 的字符串目的,ES 是固定的。段超越前缀可以替换源操作数默认使用的 DS,但不能重定向 ES 目的。过程在进行向前字符串处理前通常应执行 CLD,除非调用约定已经保证 DF=0。
REP 前缀加入硬件控制的重复
重复前缀让处理器重复执行一条字符串指令,并在每个元素之后让 CX 减 1:
REP重复 MOVS、LODS 或 STOS,直到 CX 变为零。
REPE/REPZ在 CX 非零且最近一次比较 ZF=1 时重复 CMPS 或 SCAS。
REPNE/REPNZ在 CX 非零且最近一次比较 ZF=0 时重复 CMPS 或 SCAS。
若进入时 CX=0,执行次数就是零。它与 LOOP 指令的零计数陷阱不同:重复前缀会在处理元素之前检查计数。
假设两个五字节数组第一次不同出现在下标 2。REPE CMPSB 先成功比较下标 0 与 1,再比较下标 2 并清除 ZF。它经过三次迭代后停止,此时 CX=2;SI 与 DI 已经指向不匹配元素的下一个位置。
若要寻找字节 7EH,把它放入 AL,让 ES:DI 指向搜索范围,把最大长度装入 CX,为向前扫描清除 DF,然后执行 REPNE SCASB。停止时 ZF=1 表示找到匹配;CX=0 且 ZF=0 表示范围已用尽但没有匹配。因为 DI 会在成功比较后继续移动,所以向前扫描时匹配字节位于 DI−1。
第 6 章已经把编码后的操作数变成可运行程序:数据可以传送,算术与逻辑可以变换数据,标志能够控制流程,字符串前缀能够处理整片区域。第 7 章会把这些指令组合成完整的汇编语言程序结构。