MASM32+Visual 2010 编辑字符函数(strset、strcmp等)

    科技2022-07-21  117

    MASM32+Visual 2010 编辑字符函数

    一.实验目的

    利用MASM32+Visual 2010,利用汇编语言,写出如下字符函数: (1)strset (2)strlen (3)strcmp (4)strchr (5)memset (6)memcpy

    二.环境配置

    参考:MASM32+Visual studio 2010写汇编程序入门 连接:https://blog.csdn.net/MaxWoods/article/details/44649685?ops_request_misc=%7B%22request%5Fid%22%3A%22160182254019725222408586%22%2C%22scm%22%3A%2220140713.130102334..%22%7D&request_id=160182254019725222408586&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_v2~rank_v28-1-44649685.pc_first_rank_v2_rank_v28&utm_term=MASM32+Visual studio 2010写汇编程序&spm=1018.2118.3001.4187

    三.MASM32入门

    假如学过微机原理,但是对 VS2010汇编编程不太熟悉的话,请参阅下文: [入门masm32编写简单汇编程序并做具体分析](https://blog.csdn.net/codes_first/article/details/78279641?ops_request_misc=%7B%22request%5Fid%22%3A%22160179651419724848341514%22%2C%22scm%22%3A%2220140713.130102334.pc%5Fall.%22%7D&request_id=160179651419724848341514&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_v2~rank_v28-1-78279641.pc_first_rank_v2_rank_v28&utm_term=MASM32写汇编程序入门&spm=1018.2118.3001.4187)

    四.思路与代码详解

    3.1.strset函数

    (1)strset函数功能
    strset(string s,char c)——>将字符串s中所有的字符设置成c
    (2)程序流图
    step1:设置指针指向需要改变的字符串 step2:比较:此指针所指的字节值<——>0 step3:如果不相等,将此指针所指的字节值变为字符c,更新指针 step4:否则,更新指针,转到step2
    (3)代码实现
    .386 .model flat, stdcall include kernel32.inc includelib kernel32.lib include msvcrt.inc includelib msvcrt.lib .data szText db "Reverse Engineering", 0 chr db 'j' .code main PROC LEA EDI, szText MOV ECX,0FFFFFFFFH XOR EAX,EAX ;将EAX置为0 MOV AL,chr ;将低位AL置为j change: MOV [EDI],AL ;将j放入sztext中,将其中的一个字符变为J ADD EDI,1 ;改变地址,使得地址增加 CMP BYTE PTR [EDI],0 ;观察一下,看这个字符是不是为0 JNZ change ;如果不是的话,就继续change循环 INVOKE crt_printf, addr szText ;将sztext打印出来 INVOKE crt_getchar INVOKE ExitProcess, 0 main ENDP END main 注意:上述代码中: .386 .model flat,stdcall include kernel32.inc includelib kernel32.lib ... 这些代码段,均是使用C++进行汇编的一般架构,在上述连接:入门masm32编 写简单汇编程序并做具体分析中,有详细的叙述。
    (4)结果展示
    将"Reverse Engineering"全部转为"jjjj...jjjjj"

    3.2.strlen函数

    (1)strlen函数功能
    int strset(string s)——>计算字符串s的长度
    (2)程序流图
    step1:设置指针指向需要计算长度的字符串,设置记录长度的寄存器初始为0 step2:比较:此指针所指的字节值<——>0 step3:如果不为0,将记录长度的寄存器+1,更新指针 step4:否则,说明字符串已经到结尾,结束程序
    (3)代码实现
    .386 .model flat, stdcall include kernel32.inc includelib kernel32.lib include msvcrt.inc includelib msvcrt.lib .data szText db "xie chuan long is shuai", 0 format db "length = %d", 0AH, 0 .code main PROC LEA EDI, szText ;将字符串的初始地址放到EDI中去 MOV ECX,0FFFFFFFFH MOV EAX,0 ;计数,初始值设为0 count: CMP BYTE PTR [EDI],0 ;比较[EDI]的值(字符串的某个字符)是否为\0 PUSHFD ;将标志寄存器压入栈中 ADD EDI,1 ;将地址位+1 INC EAX ;还没看出[EDI]是否为\0,先加上再说 POPFD ;将标志寄存器出栈 LOOPNZ count ;观察ZF是否为0,如果不为0,循环count DEC EAX ;因为最后把\0也加上了,所以要减去1 INVOKE crt_printf, addr format, EAX INVOKE crt_getchar INVOKE ExitProcess, 0 main ENDP END main
    (4)结果展示
    计算"xie chuan long is shuai"的长度=23

    3.3.strcmp函数

    (1)strcmp函数功能
    int strcmp(string s1,string s2):如果s1=s2,输出为0;如果s1>s2 (s2更短,或s2对应字符的ASCII更小),输出为1;如果前两种情况都不是 ,输出为-1。
    (2)程序流图

    注意:s1(i)的含义为:s1字符串的第i个字符
    (3)代码实现
    szText db "Reverse Engineering", 0 szText2 db "Reverse Engineering", 0 ;szText==szText2 szText3 db "Reverse Eng", 0 ;szText>szText3 szText4 db "Reverse Engj", 0 ;szText<szText4 szText5 db "Reverse Engh", 0 ;szText>szText5 .code main PROC LEA ESI, szText LEA EDI, szText2 ;result=0 ;LEA EDI, szText3 ;result=1 ;LEA EDI, szText4 ;result=-1 ;LEA EDI, szText5 ;result=1 ;话不多说,都在图中 compare: MOV BL,[EDI] CMP BYTE PTR [ESI],BL JNE noequal CMP BYTE PTR [ESI],0 JE equal ADD ESI,1 ADD EDI,1 JMP compare equal: MOV EAX,0 JMP print noequal: MOV BL,[EDI] CMP BYTE PTR [ESI],BL JA bigger smaller: MOV EAX,-1 JMP print bigger: MOV EAX,1 print: INVOKE crt_printf, addr format, EAX ;EAX=result INVOKE crt_getchar INVOKE ExitProcess, 0 main ENDP END main
    (4)结果展示
    情况一:s1=szText s2=szText2="Reverse Engineering"

    情况二:s1=szText s2=szText3="Reverse Eng" 或者 s1=szText s2=szText5="Reverse Engh"。输出相同结果。

    情况三:s1=szText s2=szText4="Reverse Engj"

    3.4.strchr函数

    (1)strchr函数功能
    int strchr(string s,char d)——>找到字符d在字符串s中的位置
    (2)程序流图

    (3)代码实现
    .386 .model flat, stdcall include kernel32.inc includelib kernel32.lib include msvcrt.inc includelib msvcrt.lib .data szText db "Reverse Engineering", 0 chr db 'i' format db "%d", 0AH, 0 result db "The program is over",0 .code main PROC LEA EDI, szText MOV ECX,0FFFFFFFFH MOV EBX,1 ;EBX记录现在在字符串的哪个位置 equ0: MOV CL,chr ;将要寻找的字符给CL CMP BYTE PTR [EDI],0 ;比较现在EDI所在的位置字符是否为0 JE over ;如果为0,则程序结束 CMP BYTE PTR [EDI],CL ;否则,比较EDI所在字符是否为要找的字符'i' JNE noprint ;如果不是,则直接开启下一个equ0循环 INVOKE crt_printf, addr format,EBX ;我们找到了'i'并输出,但是也许后面也有'i'! noprint: ADD EDI,1 ADD EBX,1 JMP equ0 over: INVOKE crt_printf, addr result INVOKE crt_getchar INVOKE ExitProcess, 0 main ENDP END main
    (4)结果展示
    输出字符串"xie chuan long,i love you"中'i'字符的位置:

    3.5.memset函数

    (1)memset函数功能
    void *memset(string s,char d,int size)——>将字符串s前size个字节用字符d替换
    (2)程序流图
    这个程序逻辑很简单,与前面strlen类型相似,在此不做描述。代码中有注释。
    (3)代码实现
    .386 .model flat, stdcall include kernel32.inc includelib kernel32.lib include msvcrt.inc includelib msvcrt.lib .data szText db "xie chuan long is shuaige", 0 chr db 'x' siz db 3 format db "%d", 0AH, 0 .code main PROC LEA EDI,szText MOV ECX,0FFFFFFFFH XOR ECX,ECX XOR EDX,EDX MOV DH,chr ;将要重复的字符chr->DH MOV CL,siz ;将要复制的长度siz->CL change: CMP CL,0 ;比较CL是否为0,如果为0,则输出转换后的结果 JE print MOV [EDI],DH ;将siz->EDI所处位置 ADD EDI,1 ;更新EDI与CL DEC CL JMP change print: INVOKE crt_printf, addr szText INVOKE crt_getchar INVOKE ExitProcess, 0 main ENDP END main
    (4)结果展示
    将字符串"xie chuan long is shuaige"前三个字符变为"x":

    3.6.memcpy函数

    (1)memcpy函数功能
    void *memcpy(void *destin, void *source, unsigned n)——>将source所指字节按顺序给destin,字节长度为n
    (2)程序流图
    这个程序逻辑也很简单,在此不做描述。代码中有注释。
    (3)代码实现
    .386 .model flat, stdcall include kernel32.inc includelib kernel32.lib include msvcrt.inc includelib msvcrt.lib .data szText db "xie chuan long is shuaige", 0 chr db 128 dup(0) format db "%d", 0AH, 0 .code main PROC LEA EDI,szText ;EDI指向要复制的字符串,ESI指向目的地址 LEA ESI,chr MOV ECX,0FFFFFFFFH copy: CMP BYTE PTR [EDI],0 ;判断此时[EDI]是否为0 JE print ;如果为0,说明字符串已经到末尾,应该结束了 PUSH [EDI] ;[EDI]->[ESI] POP [ESI] ADD EDI,1 ;将EDI与ESI增加1 ADD ESI,1 JMP copy print: INVOKE crt_printf, addr chr INVOKE crt_getchar INVOKE ExitProcess, 0 main ENDP END main
    (4)结果展示

    Processed: 0.011, SQL: 8