linux平台学x86汇编(十三 ):字符串的比较与搜索

【版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet,文章仅供学习交流,请勿用于商业用途】
        cmps指令用于比较字符串值,cmps指令有三种格式:cmpsb、cmpsw、cmpsl。隐含的源操作数和目标操作数位置存储在esi和edi寄存器中,每次执行cmps指令时,根据DF标志,esi和edi寄存器按照被比较的数据长度递增或递减。cmps指令从源字符串中减去目标字符串,并且适当地设置EFLAGS寄存器的进位、符号、溢出、零、奇偶校验和富足进位标志。cmps指令执行之后,可以根据字符串的值,使用一般的条件 跳转指令跳转到分支。
        cmps指令和rep指令一起使用可以对跨越多个字节的字符串重复进行比较。但rep指令不在两个重复的过程之间检查标志状态,它只关心ecx寄存器中的计数值。所以使用rep指令中的其他指令:repe、repne、repz、repnz。这些指令在每次重复过程中检查0标志,如果0标志被设置,就停止重复。rep其他指令使用如下表:
指令
描述
repe
等于时重复
repne
不等于时重复
repnz
不为零时重复
repz
为零时重复
示例:
#cmps.s
.section .data
val1:
    .ascii "Hello as!"
val2:
    .ascii "Hello wd!"

.section .text
.globl _start
_start:
    nop
    movl $1, %eax   #system call SYS_exit()
    leal val1, %esi
    leal val2, %edi
    movl $9, %ecx
    cld
    repe cmpsb
    je equal
    movl %ecx, %ebx
    int $0x80
equal:
    movl $0, %ebx
    int $0x80
该程序把源和目标字符串的位置加载到esi和edi寄存器中,字符串长度加载到ecx寄存器中,repe cmpsb指令逐字节地重复字符串的比较,直到ecx寄存器为0,或者0标志被设置(说明不匹配)。
程序执行结果如下:
$ ./cmps 
$ echo $?
2
ecx寄存器将包含不匹配字符在字符串中的位置,该位置是从字符串的末尾从0开始向回计数。
字符串的扫描使用scas指令,其提供了搜索一个字符或多个字符的方式。
scas指令类似其他字符串指令,有三种格式:scanb、scanw、scanl,三种格式分别比较内存中的一个字节和AL、AX、EAX寄存器的值。scas指令使用edi寄存器作为隐含的目标操作数。edi寄存器必须包含要扫描的字符串的内存地址,当执行scas指令时,edi寄存器的值按照搜索字符数据长度递增或递减。
scas指令的一个非常有用的功能是确定0结尾的字符串导长度,对于0结尾的字符串,要搜索的显然是0的位置,并且计算找到0经过 多少个字符。如下示例:
# scas.s
.section .data
string:
    .asciz "this is a test string!\n"   
.section .text
.globl _start
_start:
    nop
    leal string, %edi         #将要用于查找的字符串的内存地址加载到edi寄存器中
    movl $0xffff, %ecx        #0xffff表明这个程序只能用于长度最大为65535的字符串
    movb $0, %al                #将要搜索的字符加载到al寄存器中
    cld
    repne scasb                    #使用repne指令扫描字符串,获得搜索位置
    jne notfound                    #如果没找到,跳转到notfound分支
    subw $0xffff, %cx                #如果找到了,那么其距离字符串末尾的位置就存放在cx寄存器中,从cx寄存器的值中减去字符串的长度
    neg %cx                            #使用neg指令改变结果的值的符号
    dec %cx                            #因为该长度包含表示结尾的0,所以最终值必须减1才能显示字符串的真正长度。
    movl $1, %eax
    movl %ecx, %ebx            #将计算结果存放在ebx寄存器中。
    int $0x80
notfound:
    movl $1, %eax
    movl $0, %ebx
    int $0x80
运行程序结果如下:
$ ./scas 
$ echo $?
23

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。