鱼C论坛

 找回密码
 立即注册
查看: 1976|回复: 4

看不懂调试的汇编代码,求详注(关于C指针-从A字符串抄到B字符患)

[复制链接]
发表于 2014-4-17 22:56:31 | 显示全部楼层 |阅读模式
30鱼币
本帖最后由 欣欣celin 于 2014-4-18 22:30 编辑
  1. #include "stdio.h"
  2. void main()
  3. {
  4.     void copyString(char *from, char *to);

  5.     char *a = "i am a teacher";
  6.     char *b = "you are a student";

  7.     printf("string a = %s\nstring b = %s\n", a, b);
  8.     printf("copy string a to b: \n");

  9.     copyString(a, b);

  10.     printf("\nstring a - %s\nstring b - %s\n", a, b);
  11. }
  12. void copyString(char *from, char *to)
  13. {
  14.     for(; *from != '\0'; from++, to++)
  15.     {
  16.         *to = *from;
  17.     }
  18.     *to = '\0';
  19. }
复制代码
以上代码,调器如下:(汇编看不懂,求详注,感激感激{:7_174:})
2:    #include "stdio.h"
3:    void main()
4:    {
00401020   push        ebp
00401021   mov         ebp,esp
00401023   sub         esp,48h
00401026   push        ebx
00401027   push        esi
00401028   push        edi
00401029   lea         edi,[ebp-48h]
0040102C   mov         ecx,12h
00401031   mov         eax,0CCCCCCCCh
00401036   rep stos    dword ptr [edi]
5:        void copyString(char *from, char *to);
6:
7:        char *a = "i am a teacher";
00401038   mov         dword ptr [ebp-4],offset string "i am a teacher" (00422098)
8:        char *b = "you are a student";
0040103F   mov         dword ptr [ebp-8],offset string "you are a student" (00422080)
9:
10:       printf("string a = %s\nstring b = %s\n", a, b);
00401046   mov         eax,dword ptr [ebp-8]
00401049   push        eax
0040104A   mov         ecx,dword ptr [ebp-4]
0040104D   push        ecx
0040104E   push        offset string "string a = %s\nstring b = %s\n" (0042205c)
00401053   call        printf (00401130)
00401058   add         esp,0Ch
11:       printf("copy string a to b: \n");
0040105B   push        offset string "copy string a to b: \n" (00422040)
00401060   call        printf (00401130)
00401065   add         esp,4
12:
13:       copyString(a, b);
00401068   mov         edx,dword ptr [ebp-8]
0040106B   push        edx
0040106C   mov         eax,dword ptr [ebp-4]
0040106F   push        eax
00401070   call        @ILT+0(_copyString) (00401005)      
//单步运行到这句,弹出对话框说"unhandled exception in copy exe:0xc0000005: access violation",何解会访问冲突呢{:7_154:}
00401075   add         esp,8
14:
15:       printf("\nstring a - %s\nstring b - %s\n", a, b);
00401078   mov         ecx,dword ptr [ebp-8]
0040107B   push        ecx
0040107C   mov         edx,dword ptr [ebp-4]
0040107F   push        edx
00401080   push        offset string "\nstring a - %s\nstring b - %s\n" (0042201c)
00401085   call        printf (00401130)
0040108A   add         esp,0Ch
16:   }
0040108D   pop         edi
0040108E   pop         esi
0040108F   pop         ebx
00401090   add         esp,48h
00401093   cmp         ebp,esp
00401095   call        __chkesp (004011b0)
0040109A   mov         esp,ebp
0040109C   pop         ebp
0040109D   ret


17:   void copyString(char *from, char *to)
18:   {
004010C0   push        ebp
004010C1   mov         ebp,esp
004010C3   sub         esp,40h
004010C6   push        ebx
004010C7   push        esi
004010C8   push        edi
004010C9   lea         edi,[ebp-40h]
004010CC   mov         ecx,10h
004010D1   mov         eax,0CCCCCCCCh
004010D6   rep stos    dword ptr [edi]
19:       for(; *from != '\0'; from++, to++)
004010D8   jmp         copyString+2Ch (004010ec)
004010DA   mov         eax,dword ptr [ebp+8]
004010DD   add         eax,1
004010E0   mov         dword ptr [ebp+8],eax
004010E3   mov         ecx,dword ptr [ebp+0Ch]
004010E6   add         ecx,1
004010E9   mov         dword ptr [ebp+0Ch],ecx
004010EC   mov         edx,dword ptr [ebp+8]
004010EF   movsx       eax,byte ptr [edx]
004010F2   test        eax,eax
004010F4   je          copyString+42h (00401102)
20:       {
21:           *to = *from;
004010F6   mov         ecx,dword ptr [ebp+0Ch]
004010F9   mov         edx,dword ptr [ebp+8]
004010FC   mov         al,byte ptr [edx]
004010FE   mov         byte ptr [ecx],al
22:       }
00401100   jmp         copyString+1Ah (004010da)
23:       *to = '\0';
00401102   mov         ecx,dword ptr [ebp+0Ch]
00401105   mov         byte ptr [ecx],0
24:   }
00401108   pop         edi
00401109   pop         esi
0040110A   pop         ebx
0040110B   mov         esp,ebp
0040110D   pop         ebp
0040110E   ret

最佳答案

查看完整内容

首先。。。我们先解决你会什么会报访问内存错误。。。。 是因为。。*to = *from。。。 而to又是引用的a。。。from引用的b 本来。。。看着貌似没错啊。。 但是。。。你忘了。。你定义的是char *a, char *b。。。也就是说。。。那两个字符串是自数据区中。。。a直接指向。。。数据区的变量。。。b也是直接指向数据区的变量。。 而这个数据区是只读的。。。也就是不可写。。。那么你在进行写操作时当然要报错了。。 解决办法很 ...
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2014-4-17 22:56:32 | 显示全部楼层
本帖最后由 向往青莲 于 2014-4-18 08:57 编辑

首先。。。我们先解决你会什么会报访问内存错误。。。。
是因为。。*to = *from。。。
而to又是引用的a。。。from引用的b
本来。。。看着貌似没错啊。。
但是。。。你忘了。。你定义的是char *a, char *b。。。也就是说。。。那两个字符串是自数据区中。。。a直接指向。。。数据区的变量。。。b也是直接指向数据区的变量。。
而这个数据区是只读的。。。也就是不可写。。。那么你在进行写操作时当然要报错了。。
解决办法很简答

char *a
char *b
改为
char a[]
char b[]至于为什么这样定义了。。就没错。。。那是因为。。。这时a不是指针了。。它是数组变量。。。所以虽然字符串一样是在只读数据区内。。但是进行操作时系统会先把数据复制到堆栈再进行操作。。。所以就没可读可写了。。b同理

我直接解释你发上来的汇编了。。。。有些不重要的就不解释了。。。
  1. 2:    #include "stdio.h"
  2. 3:    void main()
  3. 4:    {
  4. 00401020   push        ebp                               
  5. 00401021   mov         ebp,esp
  6. 00401023   sub         esp,48h
  7. 00401026   push        ebx
  8. 00401027   push        esi
  9. 00401028   push        edi
  10. 00401029   lea         edi,[ebp-48h]
  11. 0040102C   mov         ecx,12h
  12. 00401031   mov         eax,0CCCCCCCCh       
  13. 00401036   rep stos    dword ptr [edi]                                        ////上面是分配空间,保存变量,填充CC(int 3),乃懂的
  14. 5:        void copyString(char *from, char *to);
  15. 6:
  16. 7:        char *a = "i am a teacher";
  17. 00401038   mov         dword ptr [ebp-4],offset string "i am a teacher" (00422098)                //让第一个变量a 指向字符串
  18. 8:        char *b = "you are a student";
  19. 0040103F   mov         dword ptr [ebp-8],offset string "you are a student" (00422080)        //同上
  20. 9:
  21. 10:       printf("string a = %s\nstring b = %s\n", a, b);
  22. 00401046   mov         eax,dword ptr [ebp-8]
  23. 00401049   push        eax
  24. 0040104A   mov         ecx,dword ptr [ebp-4]
  25. 0040104D   push        ecx
  26. 0040104E   push        offset string "string a = %s\nstring b = %s\n" (0042205c)
  27. 00401053   call        printf (00401130)                                                                        //上面是压栈printf需要的参数。。。调用printf打印
  28. 00401058   add         esp,0Ch                                                        //堆栈平衡
  29. 11:       printf("copy string a to b: \n");
  30. 0040105B   push        offset string "copy string a to b: \n" (00422040)
  31. 00401060   call        printf (00401130)                                //同上
  32. 00401065   add         esp,4                                                        //同上
  33. 12:
  34. 13:       copyString(a, b);
  35. 00401068   mov         edx,dword ptr [ebp-8]
  36. 0040106B   push        edx
  37. 0040106C   mov         eax,dword ptr [ebp-4]
  38. 0040106F   push        eax                                                                //压栈参数...也就是先压栈b,再压栈a......._stdcall
  39. 00401070   call        @ILT+0(_copyString) (00401005)   //调用copyString函数
  40. //单步运行到这句,弹出对话框说"unhandled exception in copy exe:0xc0000005: access violation",何解会访问冲突呢
  41. 00401075   add         esp,8                                                        //堆栈平衡。。。。。。现在我们就当没有冲突哈。。O(∩_∩)O!
  42. 14:
  43. 15:       printf("\nstring a - %s\nstring b - %s\n", a, b);
  44. 00401078   mov         ecx,dword ptr [ebp-8]
  45. 0040107B   push        ecx
  46. 0040107C   mov         edx,dword ptr [ebp-4]
  47. 0040107F   push        edx
  48. 00401080   push        offset string "\nstring a - %s\nstring b - %s\n" (0042201c)                //printf同上
  49. 00401085   call        printf (00401130)
  50. 0040108A   add         esp,0Ch                                //同上
  51. 16:   }
  52. 0040108D   pop         edi
  53. 0040108E   pop         esi
  54. 0040108F   pop         ebx
  55. 00401090   add         esp,48h
  56. 00401093   cmp         ebp,esp
  57. 00401095   call        __chkesp (004011b0)        //堆栈平衡检测函数,,系统自动添加的
  58. 0040109A   mov         esp,ebp
  59. 0040109C   pop         ebp                                       
  60. 0040109D   ret                                                                //程序结束

  61.                 //解下来分析函数copyString
  62. 17:   void copyString(char *from, char *to)
  63. 18:   {
  64. 004010C0   push        ebp
  65. 004010C1   mov         ebp,esp
  66. 004010C3   sub         esp,40h
  67. 004010C6   push        ebx
  68. 004010C7   push        esi
  69. 004010C8   push        edi
  70. 004010C9   lea         edi,[ebp-40h]
  71. 004010CC   mov         ecx,10h
  72. 004010D1   mov         eax,0CCCCCCCCh
  73. 004010D6   rep stos    dword ptr [edi]                        //同上
  74. 19:       for(; *from != '\0'; from++, to++)
  75. 004010D8   jmp         copyString+2Ch (004010ec)                        //注意这里就是for循环。。。最好照着调试。。。不然我解释了你也不懂..跳到4010ec
  76. 004010DA   mov         eax,dword ptr [ebp+8]                                //这里是下面跳上来的哈
  77. 004010DD   add         eax,1                               
  78. 004010E0   mov         dword ptr [ebp+8],eax                                //from++
  79. 004010E3   mov         ecx,dword ptr [ebp+0Ch]
  80. 004010E6   add         ecx,1
  81. 004010E9   mov         dword ptr [ebp+0Ch],ecx                        //to++...............注意。。。。这里就是for循环彻底结束。。。下面重复进行操作。。直到测试不成功位置
  82. 004010EC   mov         edx,dword ptr [ebp+8]                                //吧b字符串首地址赋值给edx
  83. 004010EF   movsx       eax,byte ptr [edx]                                        //取出字符串第一个字符
  84. 004010F2   test        eax,eax                                                                //测试是否为'0'
  85. 004010F4   je          copyString+42h (00401102)                        //是就调走401102, 不是就继续运行
  86. 20:       {
  87. 21:           *to = *from;
  88. 004010F6   mov         ecx,dword ptr [ebp+0Ch]                                //把第二个字符串首地址给ecx
  89. 004010F9   mov         edx,dword ptr [ebp+8]                                //把第一个字符串首地址给edx
  90. 004010FC   mov         al,byte ptr [edx]                                        //取出字符串第一个字符
  91. 004010FE   mov         byte ptr [ecx],al                                        //把这个字符放到第二个字符串
  92. 22:       }
  93. 00401100   jmp         copyString+1Ah (004010da)                        //跳到上面。。。也就是说循环结束了第一次。。要进行from++和to++了
  94. 23:       *to = '\0';
  95. 00401102   mov         ecx,dword ptr [ebp+0Ch]                                //到了这里就表示结束
  96. 00401105   mov         byte ptr [ecx],0
  97. 24:   }
  98. 00401108   pop         edi
  99. 00401109   pop         esi
  100. 0040110A   pop         ebx
  101. 0040110B   mov         esp,ebp
  102. 0040110D   pop         ebp
  103. 0040110E   ret
复制代码


就是这样。。。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2014-4-18 22:29:17 | 显示全部楼层

感谢您如些详尽的解答,大神就是大神吖{:7_157:}
虽然没完全理解,不过偶会再细细品味,必要时抽时间学一下小甲鱼的汇编看看
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2014-4-18 22:55:19 | 显示全部楼层
欣欣celin 发表于 2014-4-18 22:29
感谢您如些详尽的解答,大神就是大神吖
虽然没完全理解,不过偶会再细细品味,必要时抽时间学一下 ...

O(∩_∩)O~
{:7_168:}{:7_168:}{:7_168:}{:7_168:}{:7_168:}{:7_168:}
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2014-4-18 23:09:05 | 显示全部楼层

开心每一天很重要,感恩-ing{:7_148:}
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-20 02:12

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表