欣欣celin 发表于 2014-4-17 22:56:31

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

本帖最后由 欣欣celin 于 2014-4-18 22:30 编辑

#include "stdio.h"
void main()
{
    void copyString(char *from, char *to);

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

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

    copyString(a, b);

    printf("\nstring a - %s\nstring b - %s\n", a, b);
}
void copyString(char *from, char *to)
{
    for(; *from != '\0'; from++, to++)
    {
      *to = *from;
    }
    *to = '\0';
}以上代码,调器如下:(汇编看不懂,求详注,感激感激{: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,
0040102C   mov         ecx,12h
00401031   mov         eax,0CCCCCCCCh
00401036   rep stos    dword ptr
5:      void copyString(char *from, char *to);
6:
7:      char *a = "i am a teacher";
00401038   mov         dword ptr ,offset string "i am a teacher" (00422098)
8:      char *b = "you are a student";
0040103F   mov         dword ptr ,offset string "you are a student" (00422080)
9:
10:       printf("string a = %s\nstring b = %s\n", a, b);
00401046   mov         eax,dword ptr
00401049   push      eax
0040104A   mov         ecx,dword ptr
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
0040106B   push      edx
0040106C   mov         eax,dword ptr
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
0040107B   push      ecx
0040107C   mov         edx,dword ptr
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,
004010CC   mov         ecx,10h
004010D1   mov         eax,0CCCCCCCCh
004010D6   rep stos    dword ptr
19:       for(; *from != '\0'; from++, to++)
004010D8   jmp         copyString+2Ch (004010ec)
004010DA   mov         eax,dword ptr
004010DD   add         eax,1
004010E0   mov         dword ptr ,eax
004010E3   mov         ecx,dword ptr
004010E6   add         ecx,1
004010E9   mov         dword ptr ,ecx
004010EC   mov         edx,dword ptr
004010EF   movsx       eax,byte ptr
004010F2   test      eax,eax
004010F4   je          copyString+42h (00401102)
20:       {
21:         *to = *from;
004010F6   mov         ecx,dword ptr
004010F9   mov         edx,dword ptr
004010FC   mov         al,byte ptr
004010FE   mov         byte ptr ,al
22:       }
00401100   jmp         copyString+1Ah (004010da)
23:       *to = '\0';
00401102   mov         ecx,dword ptr
00401105   mov         byte ptr ,0
24:   }
00401108   pop         edi
00401109   pop         esi
0040110A   pop         ebx
0040110B   mov         esp,ebp
0040110D   pop         ebp
0040110E   ret

向往青莲 发表于 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同理

我直接解释你发上来的汇编了。。。。有些不重要的就不解释了。。。
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,
0040102C   mov         ecx,12h
00401031   mov         eax,0CCCCCCCCh       
00401036   rep stos    dword ptr                                         ////上面是分配空间,保存变量,填充CC(int 3),乃懂的
5:      void copyString(char *from, char *to);
6:
7:      char *a = "i am a teacher";
00401038   mov         dword ptr ,offset string "i am a teacher" (00422098)                //让第一个变量a 指向字符串
8:      char *b = "you are a student";
0040103F   mov         dword ptr ,offset string "you are a student" (00422080)        //同上
9:
10:       printf("string a = %s\nstring b = %s\n", a, b);
00401046   mov         eax,dword ptr
00401049   push      eax
0040104A   mov         ecx,dword ptr
0040104D   push      ecx
0040104E   push      offset string "string a = %s\nstring b = %s\n" (0042205c)
00401053   call      printf (00401130)                                                                        //上面是压栈printf需要的参数。。。调用printf打印
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
0040106B   push      edx
0040106C   mov         eax,dword ptr
0040106F   push      eax                                                                //压栈参数...也就是先压栈b,再压栈a......._stdcall
00401070   call      @ILT+0(_copyString) (00401005)   //调用copyString函数
//单步运行到这句,弹出对话框说"unhandled exception in copy exe:0xc0000005: access violation",何解会访问冲突呢
00401075   add         esp,8                                                        //堆栈平衡。。。。。。现在我们就当没有冲突哈。。O(∩_∩)O!
14:
15:       printf("\nstring a - %s\nstring b - %s\n", a, b);
00401078   mov         ecx,dword ptr
0040107B   push      ecx
0040107C   mov         edx,dword ptr
0040107F   push      edx
00401080   push      offset string "\nstring a - %s\nstring b - %s\n" (0042201c)                //printf同上
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                                                                //程序结束

                //解下来分析函数copyString
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,
004010CC   mov         ecx,10h
004010D1   mov         eax,0CCCCCCCCh
004010D6   rep stos    dword ptr                         //同上
19:       for(; *from != '\0'; from++, to++)
004010D8   jmp         copyString+2Ch (004010ec)                        //注意这里就是for循环。。。最好照着调试。。。不然我解释了你也不懂..跳到4010ec
004010DA   mov         eax,dword ptr                                 //这里是下面跳上来的哈
004010DD   add         eax,1                               
004010E0   mov         dword ptr ,eax                                //from++
004010E3   mov         ecx,dword ptr
004010E6   add         ecx,1
004010E9   mov         dword ptr ,ecx                        //to++...............注意。。。。这里就是for循环彻底结束。。。下面重复进行操作。。直到测试不成功位置
004010EC   mov         edx,dword ptr                                 //吧b字符串首地址赋值给edx
004010EF   movsx       eax,byte ptr                                         //取出字符串第一个字符
004010F2   test      eax,eax                                                                //测试是否为'0'
004010F4   je          copyString+42h (00401102)                        //是就调走401102, 不是就继续运行
20:       {
21:         *to = *from;
004010F6   mov         ecx,dword ptr                                 //把第二个字符串首地址给ecx
004010F9   mov         edx,dword ptr                                 //把第一个字符串首地址给edx
004010FC   mov         al,byte ptr                                         //取出字符串第一个字符
004010FE   mov         byte ptr ,al                                        //把这个字符放到第二个字符串
22:       }
00401100   jmp         copyString+1Ah (004010da)                        //跳到上面。。。也就是说循环结束了第一次。。要进行from++和to++了
23:       *to = '\0';
00401102   mov         ecx,dword ptr                                 //到了这里就表示结束
00401105   mov         byte ptr ,0
24:   }
00401108   pop         edi
00401109   pop         esi
0040110A   pop         ebx
0040110B   mov         esp,ebp
0040110D   pop         ebp
0040110E   ret

就是这样。。。

欣欣celin 发表于 2014-4-18 22:29:17

向往青莲 发表于 2014-4-17 22:56 static/image/common/back.gif
首先。。。我们先解决你会什么会报访问内存错误。。。。
是因为。。*to = *from。。。
而to又是引用的a。 ...

感谢您如些详尽的解答,大神就是大神吖{:7_157:}
虽然没完全理解,不过偶会再细细品味,必要时抽时间学一下小甲鱼的汇编看看{:5_91:}

向往青莲 发表于 2014-4-18 22:55:19

欣欣celin 发表于 2014-4-18 22:29 static/image/common/back.gif
感谢您如些详尽的解答,大神就是大神吖
虽然没完全理解,不过偶会再细细品味,必要时抽时间学一下 ...

O(∩_∩)O~
{:7_168:}{:7_168:}{:7_168:}{:7_168:}{:7_168:}{:7_168:}

欣欣celin 发表于 2014-4-18 23:09:05

向往青莲 发表于 2014-4-18 22:55 static/image/common/back.gif
O(∩_∩)O~

开心每一天很重要,感恩-ing{:7_148:}
页: [1]
查看完整版本: 看不懂调试的汇编代码,求详注(关于C指针-从A字符串抄到B字符患)