x86 指令集有五组指令用于处理字节、字和双字数组。虽然它们被称为字符串原语 (string primitives),但它们并不局限于字符数组。32 位模式中,下表中的每条指令都隐含使用 ESI、EDI,或是同时使用这两个寄存器来寻址内存。
指令 | 说明 |
---|---|
MOVSB、MOVSW、MOVSD | 传送字符串数据:将 ESI 寻址的内存数据复制到 EDI 寻址的内存位置 |
CMPSB、CMPSW、CMPSD | 比较字符串:比较分别由 ESI 和 EDI 寻址的内存数据 |
SCASB、SCASW、SCASD | 扫描字符串:比较累加器 (AL、AX 或 EAX) 与 EDI 寻址的内存数据 |
STOSB、STOSW、STOSD | 保存字符串数据:将累加器内容保存到 EDI 寻址的内存位置 |
LODSB、LODSW、LODSD | 从字符串加载到累加器:将 ESI 寻址的内存数据加载到累加器 |
根据指令数据大小,对累加器的引用隐含使用 AL、AX 或 EAX。字符串原语能高效执行,因为它们会自动重复并增加数组索引。
就其自身而言,字符串基本指令只能处理一个或一对内存数值。如果加上重复前缀,指令就可以用 ECX 作计数器重复执行。重复前缀使得单条指令能够处理整个数组。下面为可用的重复前缀:
REP | ECX > 0 时重复 |
REPZ、REPE | 零标志位置 1 且 ECX > 0 时重复 |
REPNZ、REPNE | 零标志位清零且 ECX > 0 时重复 |
【示例】复制字符串:下面的例子中,MOVSB 从 string1 传送 10 个字节到 string2。重复前缀在执行 MOVSB 指令之前,首先测试 ECX 是否大于 0。若 ECX=0,MOVSB 指令被忽略,控制传递到程序的下一行代码;若 ECX>0,则 ECX 减 1 并重复执行 MOVSB 指令:
重复 MOVSB 指令时,ESI 和 EDI 自动增加,这个操作由 CPU 的方向标志位控制。
根据方向标志位的状态,字符串基本青令增加或减少 ESI 和 EDI 如下表所示。可以用 CLD 和 STD 指令显式修改方向标志位:
方向标志位的值 | 对ESI和EDI的影响 | 地址顺序 |
---|---|---|
0 | 增加 | 低到高 |
1 | 减少 | 高到低 |
在执行字符串基本指令之前,若忘记设置方向标志位会产生大麻烦,因为 ESI 和 EDI 寄存器可能无法按预期增加或减少。