以下代码在VC6下编译测试通过
函数实现:
- /***********************************************************************/
- /* 比较两个字符串是否相等 */
- /**********************************************************************/
- bool isEqual(const char * str1,const char * str2)
- {
- // if (strlen(str1)!=strlen(str2)){//长度不相等则不相等
- // return false;
- // }
- //对上面判断语句的汇编实现
- __asm
- {
- push [ebp+0x8] //str1地址入栈
- call strlen //调用c函数获取长度
- add esp,4 //堆栈平衡[c调用约定"__cdecl"规定由函数的调用者释放堆栈]
- mov ebx,eax //存放比较结果,为了避免后面再次调用strlen函数引起返回值覆盖[函数的返回值规范约定保存在eax里面]
- push [ebp+0xc] //str2地址入栈
- call strlen //调用c函数获取长度[函数的返回值规范约定保存在eax里面]
- add esp,4 //堆栈平衡[c调用约定"__cdecl"规定由函数的调用者释放堆栈]
- cmp eax,ebx //比较两个字符串的长度
- jne exit2 //不相等则跳转到 exit2
- }
- // for (;str1<str1+strlen(str1);str1++,str2++)//循环比较每个字符是否相等,如果某个字符不相等那么整个也不相等
- // {
- // if (*str1!=*str2){
- // return false;
- // }
- // }
- //对上面for循环的汇编实现
- __asm
- {
- push [ebp+8] //str1地址入栈
- call strlen //调用c函数获取长度
- add esp,4 //堆栈平衡[c调用约定"__cdecl"规定由函数的调用者释放堆栈]
- mov esi,[ebp+8] //取str1地址到esi寄存器
- mov edx,esi //复制到edx寄存器
- mov edi,[ebp+0xc] //取str2地址到edi寄存器
- imul eax,type char //计算指针偏移量[eax中存放的是strlen的返回值,str1是字符指针,对指针做算术运算时参与运算的值是它所指向的类型的长度]
- add edx,eax //计算循环上限[str1+strlen(str1)]
- beginfor:
- cmp esi,edx //比较[str1<str1+strlen(str1)]
- jnl endfor //如果不小于那么结束循环[当然也可以用"大于等于"跳转指令]
- mov bl,byte ptr [esi] //取str1的一个字符到bl寄存器
- mov cl,byte ptr [edi] //取str2的一个字符到cl寄存器
- cmp bl,cl //比较两个字符大小
- jne exit2 //不相等则结束
- add esi,type char //str1指针向前移动
- add edi,type char //str2指针向前移动
- jmp beginfor //跳转到beginfor继续循环
- endfor:
- }
- __asm
- {
- exit1:
- mov eax,1 //返回相等[return true]
- jmp exit //结束
- exit2:
- mov eax,0 //返回不相等[return false]
- exit: //程序结束
- }
- }
测试:
- #include "stdafx.h"
- #include "string.h"
- bool isEqual(const char * ,const char *);
- extern "C" void _stdcall startWith(const char *,const char *,bool *);
- extern "C" int __stdcall ncompare(int,int);
- int main(int argc, char* argv[])
- {
- __asm
- {
- mov eax,eax
- mov eax,eax
- }
- char * course1 = "java5";
- char * course2 = "java6";
- char * msg1 = "不相等";
- char * msg2 = "相等";
- // if (::strcmp(course1,course2))
- // {
- //
- // printf("不相等");
- // }
- // else
- // {
- // printf("相等");
- // }
- // bool ret = isEqual(course1,course2);
- // if (ret)
- // {
- // printf("相等");
- // }
- // else
- // {
- // printf("不相等");
- // }
- //调用自定义的函数
- __asm
- {
- push course2 //传递第2个参数
- push course1 //传递第1个参数
- call isEqual //调用函数[VC编译器默认采用c调用约定"__cdecl"]
- add esp,8 //堆栈平衡[c调用约定"__cdecl"规定由函数的调用者释放堆栈]
- test eax,eax //eax是上面函数调用的返回值,对eax本身进行与操作[只影响标志位,不影响寄存器本身],检查其值是否为
- 0
- je local1 //je等同于jz,如果eax的值是0[说明返回的是false],那么与结果值为0,则zf=1,则函数调用的
- 返回的值是false[不相等]
- push msg2 //相等,msg2地址入栈[向printf传递参数]
- call printf //调用c函数prinf输出
- add esp,4 //堆栈平衡
- jmp local2 //程序结束
- local1:
- push msg1 //不相等,msg1地址入栈[向printf传递参数]
- call printf //调用c函数prinf输出
- add esp,4 //堆栈平衡
- local2:
- }
- return 0;
- }
测试字符串是否以某个子字符串开始
函数:
- /************************************************************************/
- /*检查是否以prefix开始 */
- /* content:整个字符串
- */
- /* prefix: 要查找的字符串 */
- /* result: 返回的值 */
- /************************************************************************/
- void _stdcall startWith(const char * pContent,const char * pPrefix,bool * pResult)
- {
- // if (pContent==NULL || pPrefix == NULL || strlen(pContent)<strlen(pPrefix))
- // {
- // *pResult = false;
- // return;
- // }
- /**
- 当前堆栈情况
- 0x12FEEC: 0012FF80 //进入当前方法前的EBP的值
- +0x4 0040D9CC //当前方法的返回地址
- +0x8 0012FF70 //传递给当前方法的第一个参数PContent
- +0xc 0012FF68 //传递给当前方法的第二个参数pPrefix
- +0x10 0012FF50 //传递给当前方法的第三个参数pResult
- */
- //验证执行条件
- __asm
- {
- cmp [ebp+8],0 //验证pContent
- je exitwithfalse //为0则退出
- cmp [ebp+0xc],0 //验证pPrefix
- je exitWithfalse //为0则退出
- push [ebp+8] //strlen(pContent)-->ebx
- call strlen;
- add esp,4
- mov ebx,eax
- push [ebp+0xc] //strlen(pPrefix)-->eax
- call strlen
- add esp,4
- cmp ebx,eax //strlen(pContent)<strlen(pPrefix)
- jl exitwithfalse
- }
- const char * pp = pPrefix;
- const char * pc = pContent;
- // for (; pp<pPrefix+(strlen(pPrefix)*sizeof(char)); pp++,pc++)
- // {
- // if (*pp!=*pc)
- // {
- // *pResult = false;
- // return;
- // }
- // }
- //以下是循环的代码实现
- __asm
- {
- push [ebp+0xc] //strlen(pPrefix)
- call strlen
- add esp,4 //
- imul eax,type char //strlen(pPrefix)*sizeof(char)
- mov edi,pPrefix
- add edi,eax //pPrefix+strlen(pPrefix)*sizeof(char)
- beginfor:
- cmp pp,edi //if (pp<pPrefix+strlen(pPrefix)*sizeof(char))
- jnl exitwithtrue //不满足循环条件则退出循环
- mov eax,pp
- mov al,byte ptr [eax] //*pp-->al
- mov ebx,pc
- mov bl,byte ptr [ebx] //*pc-->bl
- cmp al,bl //if (*pp!=*pc)
- jne exitwithfalse //发现不通的字符则退出循环
- add pp,type char //pp++
- add pc,type char //pc++
- jmp beginfor //继续下一轮循环
- }
- //*pResult =true;
- __asm
- {
- endfor:
- jmp exitwithtrue
- }
- __asm
- {
- exitwithfalse:
- mov eax,[ebp+0x10]
- mov [eax],0 //*pResult=0
- jmp exit
- exitwithtrue:
- mov eax,[ebp+0x10]
- mov [eax],1 //*pResult=1
- exit: //退出
- }
- }
测试代码:
- int main(int argc, char* argv[])
- {
- char content[] = "welcome to you";
- char prefix[] ="welcome";
- char msg1[] = "包含";
- char msg2[] = "不包含";
- char fmt[] = "%s/n";
- bool result = false;
- bool * pResult = &result;
- // startWith(content,prefix,&result);
- // printf("%s/n",result?"包含":"不包含");
- //以下是汇编实现版本
- __asm
- {
- push pResult //传递第三个参数
- lea eax,prefix //传递第二个参数--取数组首地址
- push eax //传递第二个参数
- lea eax,content //传递第一个参数--取数组首地址
- push eax //传递第一个参数
- call startWith //调用函数[该函数采用__stdcall约定,将由北调用函数自身负责堆栈的平衡]
- cmp result,1 //比较结果是否为1[true]
- je processeq; //如果为1说明包含,跳转到processeq处理显示包含信息
- lea eax,msg2 //否则说明不包含--取msg2数组首地址
- push eax //否则说明不包含--传递第二个参数
- lea eax,fmt //传递第一个参数--取数组fmt首地址
- push eax //传递第一个参数
- call printf //调用函数输出信息
- add esp,8 //堆栈平衡
- jmp exit //程序结束
- processeq: //处理包含的情况
- lea eax,msg1 //取数组msg1的首地址
- push eax //第二个参数入栈
- lea eax,fmt //去数组fmt的首地址
- push eax //第一个参数入栈
- call printf //调用函数输出信息
- add esp,8 //堆栈平衡
- exit: //程序结束
- }
- return 0;
- }