1.求下面程序的输出结果:
view plaincopy to clipboardprint?
01.#include <stdio.h>
02.
03.int main()
04.{
05. int i = 3;
06. int a;
07. a = ++i + ++i + ++i;
08. printf("%d \n", a);
09. return 0;
10.}
#include <stdio.h>
int main()
{
int i = 3;
int a;
a = ++i + ++i + ++i;
printf("%d \n", a);
return 0;
}
上述程序在VC 6下反汇编后的结果如下:
view plaincopy to clipboardprint?
01.--- D:\exp\plusplus\plusplus.cpp ---------------------------------------------------------1: #include <stdio.h>
02.2:
03.3: int main()
04.4: {
05.00401010 push ebp ;保存 ebp,并把 esp 放入 ebp 中。此时 ebp 与 esp 同。
06.00401011 mov ebp,esp ;都是这次函数调用时的栈顶。
07.00401013 sub esp,48h ;把 esp 往上移动一个范围,等于在堆栈中放出一片新
08. ;的空间用来存局部变量.
09.00401016 push ebx ;下面保存三个寄存器:ebx,esi,edi,这也是 C 规范.
10.00401017 push esi
11.00401018 push edi
12.00401019 lea edi,[ebp-48h] ;本来是要 mov edi,ebp-0cch,但是 mov 不支持-操作。所
13. ;以对 ebp-0cch 取内容,而 lea 把内容的地址也就是 ebp
14. ;-0cch 加载到 edi 中.目的是把保存局部变量的区域(从
15. ;ebp-0cch 开始的区域)初始化成全部 0cccccccch.
16.
17.0040101C mov ecx,12h
18.00401021 mov eax,0CCCCCCCCh
19.00401026 rep stos dword ptr [edi]
20.5: int i = 3;
21.00401028 mov dword ptr [ebp-4],3
22.6: int a;
23.7: a = ++i + ++i + ++i;
24.0040102F mov eax,dword ptr [ebp-4] ;i值先自增1
25.00401032 add eax,1
26.00401035 mov dword ptr [ebp-4],eax
27.00401038 mov ecx,dword ptr [ebp-4] ;i值再自增1
28.0040103B add ecx,1
29.0040103E mov dword ptr [ebp-4],ecx
30.00401041 mov edx,dword ptr [ebp-4]
31.00401044 add edx,dword ptr [ebp-4];计算i + i
32.00401047 mov eax,dword ptr [ebp-4];i值再自增1
33.0040104A add eax,1
34.0040104D mov dword ptr [ebp-4],eax
35.00401050 add edx,dword ptr [ebp-4];上面i + i的和再加 i
36.00401053 mov dword ptr [ebp-8],edx
37.8: printf("%d \n", a);
38.00401056 mov ecx,dword ptr [ebp-8]
39.00401059 push ecx
40.0040105A push offset string "%d \n" (0042201c)
41.0040105F call printf (00401090)
42.00401064 add esp,8
43.9: return 0;
44.00401067 xor eax,eax
45.10: }
46.00401069 pop edi
47.0040106A pop esi
48.0040106B pop ebx
49.0040106C add esp,48h
50.0040106F cmp ebp,esp
51.00401071 call __chkesp (00401110)
52.00401076 mov esp,ebp
53.00401078 pop ebp
54.00401079 ret
55.--- No source file -----------------------------------------------------------------------
--- D:\exp\plusplus\plusplus.cpp ---------------------------------------------------------1: #include <stdio.h>
2:
3: int main()
4: {
00401010 push ebp ;保存 ebp,并把 esp 放入 ebp 中。此时 ebp 与 esp 同。
00401011 mov ebp,esp ;都是这次函数调用时的栈顶。
00401013 sub esp,48h ;把 esp 往上移动一个范围,等于在堆栈中放出一片新
;的空间用来存局部变量.
00401016 push ebx ;下面保存三个寄存器:ebx,esi,edi,这也是 C 规范.
00401017 push esi
00401018 push edi
00401019 lea edi,[ebp-48h] ;本来是要 mov edi,ebp-0cch,但是 mov 不支持-操作。所
;以对 ebp-0cch 取内容,而 lea 把内容的地址也就是 ebp
;-0cch 加载到 edi 中.目的是把保存局部变量的区域(从
;ebp-0cch 开始的区域)初始化成全部 0cccccccch.
0040101C mov ecx,12h
00401021 mov eax,0CCCCCCCCh
00401026 rep stos dword ptr [edi]
5: int i = 3;
00401028 mov dword ptr [ebp-4],3
6: int a;
7: a = ++i + ++i + ++i;
0040102F mov eax,dword ptr [ebp-4] ;i值先自增1
00401032 add eax,1
00401035 mov dword ptr [ebp-4],eax
00401038 mov ecx,dword ptr [ebp-4] ;i值再自增1
0040103B add ecx,1
0040103E mov dword ptr [ebp-4],ecx
00401041 mov edx,dword ptr [ebp-4]
00401044 add edx,dword ptr [ebp-4];计算i + i
00401047 mov eax,dword ptr [ebp-4];i值再自增1
0040104A add eax,1
0040104D mov dword ptr [ebp-4],eax
00401050 add edx,dword ptr [ebp-4];上面i + i的和再加 i
00401053 mov dword ptr [ebp-8],edx
8: printf("%d \n", a);
00401056 mov ecx,dword ptr [ebp-8]
00401059 push ecx
0040105A push offset string "%d \n" (0042201c)
0040105F call printf (00401090)
00401064 add esp,8
9: return 0;
00401067 xor eax,eax
10: }
00401069 pop edi
0040106A pop esi
0040106B pop ebx
0040106C add esp,48h
0040106F cmp ebp,esp
00401071 call __chkesp (00401110)
00401076 mov esp,ebp
00401078 pop ebp
00401079 ret
--- No source file -----------------------------------------------------------------------
通过反汇编可知,程序的结果是:5 + 5 + 6 = 16.
2.
view plaincopy to clipboardprint?
01.#include <stdio.h>
02.
03.int main()
04.{
05. int i = 3;
06. int a;
07. a = ++i + ++i + i++;
08. printf("%d \n", a);
09. return 0;
10.}
#include <stdio.h>
int main()
{
int i = 3;
int a;
a = ++i + ++i + i++;
printf("%d \n", a);
return 0;
}
view plaincopy to clipboardprint?
01.--- D:\exp\plusplus\plusplus.cpp -----------------------------------------------------------------------------------------------------------------------------------------------------------------
02.1: #include <stdio.h>
03.2:
04.3: int main()
05.4: {
06.00401010 push ebp
07.00401011 mov ebp,esp
08.00401013 sub esp,48h
09.00401016 push ebx
10.00401017 push esi
11.00401018 push edi
12.00401019 lea edi,[ebp-48h]
13.0040101C mov ecx,12h
14.00401021 mov eax,0CCCCCCCCh
15.00401026 rep stos dword ptr [edi]
16.5: int i = 3;
17.00401028 mov dword ptr [ebp-4],3
18.6: int a;
19.7: a = ++i + ++i + i++;
20.0040102F mov eax,dword ptr [ebp-4]
21.00401032 add eax,1
22.00401035 mov dword ptr [ebp-4],eax
23.00401038 mov ecx,dword ptr [ebp-4]
24.0040103B add ecx,1
25.0040103E mov dword ptr [ebp-4],ecx
26.00401041 mov edx,dword ptr [ebp-4]
27.00401044 add edx,dword ptr [ebp-4]
28.00401047 add edx,dword ptr [ebp-4]
29.0040104A mov dword ptr [ebp-8],edx
30.0040104D mov eax,dword ptr [ebp-4]
31.00401050 add eax,1
32.00401053 mov dword ptr [ebp-4],eax
33.8: printf("%d \n", a);
34.00401056 mov ecx,dword ptr [ebp-8]
35.00401059 push ecx
36.0040105A push offset string "%d \n" (0042201c)
37.0040105F call printf (004010a0)
38.00401064 add esp,8
39.9: return 0;
40.00401067 xor eax,eax
41.10: }
42.00401069 pop edi
43.0040106A pop esi
44.0040106B pop ebx
45.0040106C add esp,48h
46.0040106F cmp ebp,esp
47.00401071 call __chkesp (00401120)
48.00401076 mov esp,ebp
49.00401078 pop ebp
50.00401079 ret
51.--- No source file --------------------------------------------------------------------
--- D:\exp\plusplus\plusplus.cpp -----------------------------------------------------------------------------------------------------------------------------------------------------------------
1: #include <stdio.h>
2:
3: int main()
4: {
00401010 push ebp
00401011 mov ebp,esp
00401013 sub esp,48h
00401016 push ebx
00401017 push esi
00401018 push edi
00401019 lea edi,[ebp-48h]
0040101C mov ecx,12h
00401021 mov eax,0CCCCCCCCh
00401026 rep stos dword ptr [edi]
5: int i = 3;
00401028 mov dword ptr [ebp-4],3
6: int a;
7: a = ++i + ++i + i++;
0040102F mov eax,dword ptr [ebp-4]
00401032 add eax,1
00401035 mov dword ptr [ebp-4],eax
00401038 mov ecx,dword ptr [ebp-4]
0040103B add ecx,1
0040103E mov dword ptr [ebp-4],ecx
00401041 mov edx,dword ptr [ebp-4]
00401044 add edx,dword ptr [ebp-4]
00401047 add edx,dword ptr [ebp-4]
0040104A mov dword ptr [ebp-8],edx
0040104D mov eax,dword ptr [ebp-4]
00401050 add eax,1
00401053 mov dword ptr [ebp-4],eax
8: printf("%d \n", a);
00401056 mov ecx,dword ptr [ebp-8]
00401059 push ecx
0040105A push offset string "%d \n" (0042201c)
0040105F call printf (004010a0)
00401064 add esp,8
9: return 0;
00401067 xor eax,eax
10: }
00401069 pop edi
0040106A pop esi
0040106B pop ebx
0040106C add esp,48h
0040106F cmp ebp,esp
00401071 call __chkesp (00401120)
00401076 mov esp,ebp
00401078 pop ebp
00401079 ret
--- No source file --------------------------------------------------------------------
通过反汇编可知,程序的结果是:5 + 5 + 5 = 15.
总结:
1.编译的最长匹配原则,以及++的优先级高于+。对变量的引用是通过地址进行的。
2.参数的压栈及运算符的压栈。例如:a = ++i + ++i + ++i,是通过将++压入符号栈,然后将i压入数据栈,弹栈,计算出该++i的值,将该值的引用地址压入数据栈;将+压入符号栈,将++压入符号栈,将i压入数据栈,因为后面的是+,而++的优先级高于+,所以数据栈弹栈,符号栈弹栈,计算出的结果压栈。再继续弹栈,压栈。。。。