函数实现:
[cpp]
1. /***********************************************************************/
2. /* 比较两个字符串是否相等 */
3. /**********************************************************************/
4. bool isEqual(const char * str1,const char
5. {
6.
7. // if (strlen(str1)!=strlen(str2)){//长度不相等则不相等
8. // return false;
9. // }
10.
11. //对上面判断语句的汇编实现
12. __asm
13. {
14. //str1地址入栈
15. //调用c函数获取长度
16. //堆栈平衡[c调用约定"__cdecl"规定由函数的调用者释放堆栈]
17. //存放比较结果,为了避免后面再次调用strlen函数引起返回值覆盖[函数的返回值规范约定保存在eax里面]
18. //str2地址入栈
19. //调用c函数获取长度[函数的返回值规范约定保存在eax里面]
20. //堆栈平衡[c调用约定"__cdecl"规定由函数的调用者释放堆栈]
21. //比较两个字符串的长度
22. //不相等则跳转到 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. //str1地址入栈
37. //调用c函数获取长度
38. //堆栈平衡[c调用约定"__cdecl"规定由函数的调用者释放堆栈]
39. //取str1地址到esi寄存器
40. //复制到edx寄存器
41. //取str2地址到edi寄存器
42. char //计算指针偏移量[eax中存放的是strlen的返回值,str1是字符指针,对指针做算术运算时参与运算的值是它所指向的类型的长度]
43. //计算循环上限[str1+strlen(str1)]
44. beginfor:
45. //比较[str1<str1+strlen(str1)]
46. //如果不小于那么结束循环[当然也可以用"大于等于"跳转指令]
47. //取str1的一个字符到bl寄存器
48. //取str2的一个字符到cl寄存器
49. //比较两个字符大小
50. //不相等则结束
51. char //str1指针向前移动
52. char //str2指针向前移动
53. //跳转到beginfor继续循环
54. endfor:
55.
56. }
57.
58. __asm
59. {
60.
61. exit1:
62. //返回相等[return true]
63. //结束
64. exit2:
65. //返回不相等[return false]
66. exit: //程序结束
67. }
68.
69. }
测试:
[cpp]
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. //传递第2个参数
42. //传递第1个参数
43. //调用函数[VC编译器默认采用c调用约定"__cdecl"]
44. //堆栈平衡[c调用约定"__cdecl"规定由函数的调用者释放堆栈]
45. //eax是上面函数调用的返回值,对eax本身进行与操作[只影响标志位,不影响寄存器本身],检查其值是否为
46.
47. 0
48. //je等同于jz,如果eax的值是0[说明返回的是false],那么与结果值为0,则zf=1,则函数调用的
49.
50. 返回的值是false[不相等]
51. //相等,msg2地址入栈[向printf传递参数]
52. //调用c函数prinf输出
53. //堆栈平衡
54. //程序结束
55. local1:
56. //不相等,msg1地址入栈[向printf传递参数]
57. //调用c函数prinf输出
58. //堆栈平衡
59. local2:
60. }
61.
62.
63.
64.
65. return
66. }
测试字符串是否以某个子字符串开始
函数:
[cpp]
1. /************************************************************************/
2. /*检查是否以prefix开始 */
3. /* content:整个字符串
4.
5. */
6. /* prefix: 要查找的字符串 */
7. /* result: 返回的值 */
8. /************************************************************************/
9. void _stdcall startWith(const char * pContent,const char * pPrefix,bool
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. //验证pContent
30. //为0则退出
31. //验证pPrefix
32. //为0则退出
33.
34. //strlen(pContent)-->ebx
35. call strlen;
36. add esp,4
37. mov ebx,eax
38.
39. //strlen(pPrefix)-->eax
40. call strlen
41. add esp,4
42.
43. //strlen(pContent)<strlen(pPrefix)
44. jl exitwithfalse
45. }
46.
47. const char
48. const char
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. //strlen(pPrefix)
62. call strlen
63. //
64. char //strlen(pPrefix)*sizeof(char)
65. mov edi,pPrefix
66. //pPrefix+strlen(pPrefix)*sizeof(char)
67. beginfor:
68. //if (pp<pPrefix+strlen(pPrefix)*sizeof(char))
69. //不满足循环条件则退出循环
70.
71. mov eax,pp
72. //*pp-->al
73. mov ebx,pc
74. //*pc-->bl
75. //if (*pp!=*pc)
76. //发现不通的字符则退出循环
77. char //pp++
78. char //pc++
79. //继续下一轮循环
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. //*pResult=0
94. jmp exit
95. exitwithtrue:
96. mov eax,[ebp+0x10]
97. //*pResult=1
98. exit: //退出
99. }
100. }
测试代码:
[cpp]
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
12.
13. // startWith(content,prefix,&result);
14. // printf("%s/n",result?"包含":"不包含");
15.
16. //以下是汇编实现版本
17. __asm
18. {
19. //传递第三个参数
20. //传递第二个参数--取数组首地址
21. //传递第二个参数
22. //传递第一个参数--取数组首地址
23. //传递第一个参数
24. //调用函数[该函数采用__stdcall约定,将由北调用函数自身负责堆栈的平衡]
25.
26. //比较结果是否为1[true]
27. //如果为1说明包含,跳转到processeq处理显示包含信息
28. //否则说明不包含--取msg2数组首地址
29. //否则说明不包含--传递第二个参数
30. //传递第一个参数--取数组fmt首地址
31. //传递第一个参数
32. //调用函数输出信息
33. //堆栈平衡
34. //程序结束
35. processeq: //处理包含的情况
36. //取数组msg1的首地址
37. //第二个参数入栈
38. //去数组fmt的首地址
39. //第一个参数入栈
40. //调用函数输出信息
41. //堆栈平衡
42. exit: //程序结束
43. }
44.
45. return
46. }