字符串操作实践[内联汇编实现]

以下代码在VC6下编译测试通过

函数实现:

  1. /***********************************************************************/  
  2. /*             比较两个字符串是否相等                                  */  
  3. /**********************************************************************/  
  4. bool isEqual(const char * str1,const char * str2)  
  5. {  
  6.   
  7. //  if (strlen(str1)!=strlen(str2)){//长度不相等则不相等  
  8. //      return false;  
  9. //  }  
  10.   
  11.     //对上面判断语句的汇编实现  
  12.     __asm  
  13.     {  
  14.         push [ebp+0x8]  //str1地址入栈  
  15.         call strlen     //调用c函数获取长度  
  16.         add esp,4       //堆栈平衡[c调用约定"__cdecl"规定由函数的调用者释放堆栈]  
  17.         mov ebx,eax     //存放比较结果,为了避免后面再次调用strlen函数引起返回值覆盖[函数的返回值规范约定保存在eax里面]  
  18.         push [ebp+0xc]  //str2地址入栈  
  19.         call strlen     //调用c函数获取长度[函数的返回值规范约定保存在eax里面]  
  20.         add esp,4       //堆栈平衡[c调用约定"__cdecl"规定由函数的调用者释放堆栈]  
  21.         cmp eax,ebx     //比较两个字符串的长度  
  22.         jne exit2       //不相等则跳转到 exit2  
  23.     }  
  24.   
  25. //  for (;str1<str1+strlen(str1);str1++,str2++)//循环比较每个字符是否相等,如果某个字符不相等那么整个也不相等  
  26. //  {  
  27. //      if (*str1!=*str2){  
  28. //          return false;  
  29. //      }  
  30. //  }  
  31.   
  32.     //对上面for循环的汇编实现  
  33.     __asm  
  34.     {  
  35.   
  36.         push [ebp+8]            //str1地址入栈  
  37.         call strlen             //调用c函数获取长度  
  38.         add esp,4               //堆栈平衡[c调用约定"__cdecl"规定由函数的调用者释放堆栈]  
  39.         mov esi,[ebp+8]         //取str1地址到esi寄存器  
  40.         mov edx,esi             //复制到edx寄存器  
  41.         mov edi,[ebp+0xc]       //取str2地址到edi寄存器  
  42.         imul eax,type char      //计算指针偏移量[eax中存放的是strlen的返回值,str1是字符指针,对指针做算术运算时参与运算的值是它所指向的类型的长度]  
  43.         add edx,eax             //计算循环上限[str1+strlen(str1)]  
  44. beginfor:  
  45.         cmp esi,edx             //比较[str1<str1+strlen(str1)]  
  46.         jnl endfor              //如果不小于那么结束循环[当然也可以用"大于等于"跳转指令]  
  47.         mov bl,byte ptr [esi]   //取str1的一个字符到bl寄存器  
  48.         mov cl,byte ptr [edi]   //取str2的一个字符到cl寄存器  
  49.         cmp bl,cl               //比较两个字符大小  
  50.         jne exit2               //不相等则结束  
  51.         add esi,type char       //str1指针向前移动  
  52.         add edi,type char       //str2指针向前移动  
  53.         jmp beginfor            //跳转到beginfor继续循环  
  54. endfor:  
  55.           
  56.     }  
  57.   
  58.     __asm  
  59.     {  
  60.   
  61. exit1:  
  62.         mov eax,1               //返回相等[return true]  
  63.         jmp exit                //结束  
  64. exit2:  
  65.         mov eax,0               //返回不相等[return false]         
  66. exit:                           //程序结束  
  67.     }  
  68.   
  69. }  

 

测试:

  1. #include "stdafx.h"  
  2. #include "string.h"  
  3. bool isEqual(const char * ,const char *);  
  4. extern "C" void _stdcall startWith(const char *,const char *,bool *);  
  5. extern "C" int __stdcall ncompare(int,int);  
  6. int main(int argc, char* argv[])  
  7. {  
  8.     __asm  
  9.     {  
  10.         mov eax,eax  
  11.         mov eax,eax  
  12.     }  
  13.     char * course1 = "java5";  
  14.     char * course2 = "java6";  
  15.     char * msg1 = "不相等";  
  16.     char * msg2 = "相等";  
  17.   
  18.     //  if (::strcmp(course1,course2))  
  19.     //  {  
  20.     //        
  21.     //      printf("不相等");  
  22.     //  }  
  23.     //  else  
  24.     //  {  
  25.     //      printf("相等");  
  26.     //  }  
  27.       
  28.     //  bool ret = isEqual(course1,course2);  
  29.     //  if (ret)  
  30.     //  {  
  31.     //      printf("相等");  
  32.     //  }  
  33.     //  else  
  34.     //  {  
  35.     //      printf("不相等");  
  36.     //  }  
  37.       
  38.     //调用自定义的函数  
  39.     __asm  
  40.     {  
  41.         push course2    //传递第2个参数  
  42.         push course1    //传递第1个参数  
  43.         call isEqual    //调用函数[VC编译器默认采用c调用约定"__cdecl"]  
  44.         add esp,8       //堆栈平衡[c调用约定"__cdecl"规定由函数的调用者释放堆栈]  
  45.         test eax,eax    //eax是上面函数调用的返回值,对eax本身进行与操作[只影响标志位,不影响寄存器本身],检查其值是否为  
  46.   
  47. 0  
  48.         je local1       //je等同于jz,如果eax的值是0[说明返回的是false],那么与结果值为0,则zf=1,则函数调用的  
  49.   
  50. 返回的值是false[不相等]  
  51.         push msg2       //相等,msg2地址入栈[向printf传递参数]  
  52.         call printf     //调用c函数prinf输出  
  53.         add esp,4       //堆栈平衡  
  54.         jmp local2      //程序结束  
  55. local1:  
  56.         push msg1       //不相等,msg1地址入栈[向printf传递参数]  
  57.         call printf     //调用c函数prinf输出  
  58.         add esp,4       //堆栈平衡  
  59. local2:  
  60.     }  
  61.       
  62.   
  63.   
  64.   
  65.     return 0;  
  66. }  

 


测试字符串是否以某个子字符串开始

函数:

  1. /************************************************************************/  
  2. /*检查是否以prefix开始                                                 */  
  3. /*  content:整个字符串                                                    
  4.  
  5. */  
  6. /*  prefix: 要查找的字符串                                             */  
  7. /*  result: 返回的值                                                    */  
  8. /************************************************************************/  
  9. void _stdcall startWith(const char * pContent,const char * pPrefix,bool * pResult)  
  10. {  
  11. //  if (pContent==NULL || pPrefix == NULL || strlen(pContent)<strlen(pPrefix))  
  12. //  {  
  13. //      *pResult = false;  
  14. //      return;  
  15. //  }  
  16.   
  17.     /** 
  18.     当前堆栈情况 
  19.     0x12FEEC:   0012FF80    //进入当前方法前的EBP的值 
  20.         +0x4    0040D9CC    //当前方法的返回地址 
  21.         +0x8    0012FF70    //传递给当前方法的第一个参数PContent 
  22.         +0xc    0012FF68    //传递给当前方法的第二个参数pPrefix 
  23.         +0x10   0012FF50    //传递给当前方法的第三个参数pResult 
  24.     */  
  25.       
  26.     //验证执行条件  
  27.     __asm  
  28.     {  
  29.         cmp [ebp+8],0       //验证pContent  
  30.         je exitwithfalse    //为0则退出  
  31.         cmp [ebp+0xc],0     //验证pPrefix  
  32.         je exitWithfalse    //为0则退出  
  33.           
  34.         push [ebp+8]        //strlen(pContent)-->ebx  
  35.         call strlen;          
  36.         add esp,4  
  37.         mov ebx,eax  
  38.   
  39.         push [ebp+0xc]      //strlen(pPrefix)-->eax  
  40.         call strlen  
  41.         add esp,4  
  42.   
  43.         cmp ebx,eax         //strlen(pContent)<strlen(pPrefix)  
  44.         jl exitwithfalse  
  45.     }  
  46.   
  47.     const char * pp = pPrefix;  
  48.     const char * pc = pContent;  
  49.   
  50. //  for (; pp<pPrefix+(strlen(pPrefix)*sizeof(char)); pp++,pc++)  
  51. //  {  
  52. //      if (*pp!=*pc)  
  53. //      {  
  54. //          *pResult = false;  
  55. //          return;  
  56. //      }  
  57. //  }  
  58.     //以下是循环的代码实现  
  59.     __asm  
  60.     {  
  61.         push [ebp+0xc]          //strlen(pPrefix)  
  62.         call strlen  
  63.         add esp,4               //  
  64.         imul eax,type char      //strlen(pPrefix)*sizeof(char)  
  65.         mov edi,pPrefix           
  66.         add edi,eax             //pPrefix+strlen(pPrefix)*sizeof(char)  
  67. beginfor:  
  68.         cmp pp,edi              //if (pp<pPrefix+strlen(pPrefix)*sizeof(char))  
  69.         jnl exitwithtrue        //不满足循环条件则退出循环  
  70.           
  71.         mov eax,pp  
  72.         mov al,byte ptr [eax]   //*pp-->al  
  73.         mov ebx,pc  
  74.         mov bl,byte ptr [ebx]   //*pc-->bl  
  75.         cmp al,bl               //if (*pp!=*pc)  
  76.         jne exitwithfalse       //发现不通的字符则退出循环  
  77.         add pp,type char        //pp++  
  78.         add pc,type char        //pc++  
  79.         jmp beginfor            //继续下一轮循环  
  80.     }  
  81.   
  82.     //*pResult =true;  
  83.     __asm   
  84.     {  
  85.         endfor:  
  86.             jmp exitwithtrue  
  87.     }  
  88.       
  89.     __asm  
  90.     {  
  91. exitwithfalse:  
  92.         mov eax,[ebp+0x10]  
  93.         mov [eax],0             //*pResult=0  
  94.         jmp exit  
  95. exitwithtrue:  
  96.         mov eax,[ebp+0x10]  
  97.         mov [eax],1             //*pResult=1  
  98. exit:           //退出  
  99.     }  
  100. }  

 

测试代码:

  1. int main(int argc, char* argv[])  
  2. {  
  3.   
  4.     char content[] = "welcome to you";  
  5.     char prefix[] ="welcome";  
  6.     char msg1[] = "包含";  
  7.     char msg2[] = "不包含";  
  8.     char fmt[] = "%s/n";  
  9.   
  10.     bool result = false;  
  11.     bool * pResult = &result;  
  12.       
  13.  // startWith(content,prefix,&result);  
  14.  // printf("%s/n",result?"包含":"不包含");  
  15.   
  16.     //以下是汇编实现版本  
  17.     __asm  
  18.     {  
  19.         push pResult        //传递第三个参数  
  20.         lea eax,prefix      //传递第二个参数--取数组首地址  
  21.         push eax            //传递第二个参数  
  22.         lea eax,content     //传递第一个参数--取数组首地址  
  23.         push eax            //传递第一个参数  
  24.         call startWith      //调用函数[该函数采用__stdcall约定,将由北调用函数自身负责堆栈的平衡]  
  25.           
  26.         cmp result,1            //比较结果是否为1[true]  
  27.         je processeq;       //如果为1说明包含,跳转到processeq处理显示包含信息  
  28.         lea eax,msg2        //否则说明不包含--取msg2数组首地址  
  29.         push eax            //否则说明不包含--传递第二个参数  
  30.         lea eax,fmt         //传递第一个参数--取数组fmt首地址  
  31.         push eax            //传递第一个参数  
  32.         call printf         //调用函数输出信息  
  33.         add esp,8           //堆栈平衡  
  34.         jmp exit            //程序结束  
  35. processeq:                  //处理包含的情况  
  36.         lea eax,msg1        //取数组msg1的首地址  
  37.         push eax            //第二个参数入栈  
  38.         lea eax,fmt         //去数组fmt的首地址  
  39.         push eax            //第一个参数入栈  
  40.         call printf         //调用函数输出信息  
  41.         add esp,8           //堆栈平衡  
  42. exit:                       //程序结束  
  43.     }  
  44.   
  45.     return 0;  


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值