目录

汇编 - 字符串(Strings)

我们在前面的例子中已经使用了可变长度字符串。 可变长度字符串可以包含所需的字符数。 通常,我们通过两种方式之一指定字符串的长度 -

  • 显式存储字符串长度
  • Using a sentinel character

我们可以使用$ location计数器符号显式存储字符串长度,该符号表示位置计数器的当前值。 在以下示例中 -

msg  db  'Hello, world!',0xa ;our dear string
len  equ  $ - msg            ;length of our dear string

$指向字符串变量msg的最后一个字符后的字节。 因此, $-msg给出字符串的长度。 我们也可以写

msg db 'Hello, world!',0xa ;our dear string
len equ 13                 ;length of our dear string

或者,您可以存储带有尾随sentinel字符的字符串来分隔字符串,而不是显式地存储字符串长度。 sentinel字符应该是一个不出现在字符串中的特殊字符。

例如 -

message DB 'I am loving it!', 0

字符串说明

每个字符串指令可能需要源操作数,目标​​操作数或两者。 对于32位段,字符串指令使用ESI和EDI寄存器分别指向源和目标操作数。

但是,对于16位段,SI和DI寄存器分别用于指向源和目标。

处理字符串有五个基本指令。 他们是 -

  • MOVS - 该指令将1字节,字或双字数据从内存位置移动到另一个位置。

  • LODS - 该指令从内存加载。 如果操作数是一个字节,则将其加载到AL寄存器中,如果操作数是一个字,则将其加载到AX寄存器中,并将双字加载到EAX寄存器中。

  • STOS - 该指令将寄存器(AL,AX或EAX)中的数据存储到存储器中。

  • CMPS - 该指令比较内存中的两个数据项。 数据可以是字节大小,字或双字。

  • SCAS - 该指令将寄存器(AL,AX或EAX)的内容与内存中项目的内容进行比较。

上述指令中的每一个都具有字节,字和双字版本,并且可以通过使用重复前缀来重复字符串指令。

这些指令使用ES:DI和DS:SI寄存器对,其中DI和SI寄存器包含有效的偏移地址,指向存储在存储器中的字节。 SI通常与DS(数据段)相关联,DI始终与ES(额外段)相关联。

DS:SI(或ESI)和ES:DI(或EDI)寄存器分别指向源和目标操作数。 假设源操作数为DS:SI(或ESI),ES中的目标操作数:内存中的DI(或EDI)。

对于16位地址,使用SI和DI寄存器,对于32位地址,使用ESI和EDI寄存器。

下表提供了各种版本的字符串指令和操作数的假定空间。

基本教学 操作数在 字节操作 单词操作 双字操作
MOVS ES:DI, DS:SIMOVSBMOVSWMOVSD
LODS AX, DS:SILODSBLODSWLODSD
STOS ES:DI, AXSTOSBSTOSWSTOSD
CMPS DS:SI,ES:DI CMPSBCMPSWCMPSD
SCAS ES:DI, AXSCASBSCASWSCASD

重复前缀

REP字符串在字符串指令之前设置时,例如REP MOVSB,会根据放置在CX寄存器中的计数器重复该指令。 REP执行指令,将CX减1,并检查CX是否为零。 它重复指令处理直到CX为零。

方向标志(DF)确定操作的方向。

  • 使用CLD(清除方向标志,DF = 0)使操作从左到右。
  • 使用STD(设置方向标志,DF = 1)使操作从右向左。

REP前缀还具有以下变体:

  • 记者:这是无条件的重复。 它重复操作直到CX为零。

  • REPE或REPZ:有条件重复。 它重复操作,而零标志指示等于/零。 当ZF指示不等于/零或CX为零时停止。

  • REPNE或REPNZ:这也是有条件的重复。 它在零标志指示不等于/零时重复该操作。 当ZF指示等于/零或CX递减为零时停止。

↑回到顶部↑
WIKI教程 @2018