看不懂调试的汇编代码,求详注(关于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-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
就是这样。。。
向往青莲 发表于 2014-4-17 22:56 static/image/common/back.gif
首先。。。我们先解决你会什么会报访问内存错误。。。。
是因为。。*to = *from。。。
而to又是引用的a。 ...
感谢您如些详尽的解答,大神就是大神吖{:7_157:}
虽然没完全理解,不过偶会再细细品味,必要时抽时间学一下小甲鱼的汇编看看{:5_91:} 欣欣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:} 向往青莲 发表于 2014-4-18 22:55 static/image/common/back.gif
O(∩_∩)O~
开心每一天很重要,感恩-ing{:7_148:}
页:
[1]