zoukankan      html  css  js  c++  java
  • 反汇编角度->C++ const

    1. #include<iostream>
    2. #include<stdlib.h>
    3. using namespace std;
    4. const int &add( const int &a,const int &b)
    5. {
    6. return a+b;
    7. }
    8. int main()
    9. {
    10. const int &result = add(5,8);
    11. add(11, 8);//重复使用栈.排除虽然栈回收.但值没变的可能性
    12. add(5, 8);
    13. add(5,8);
    14. add(5,8);
    15.     add(5,8);
    16. cout << result << endl;
    17. system("pause");
    18. return 0;
    19. }
       

    以上结果输出13.原因在于当add的时候参数5,8.将生成2个临时对象(但这个临时对象的生存周期可伴随main).用来保存5,8
    main.c 部分反汇编代码
    1. 00FC18CE mov dword ptr [ebp-0D4h],8 ;创建一个地址用来保存8
    2. 00FC18D8 mov dword ptr [ebp-0E0h],5 ;创建一个地址用来保存5
    3. 00FC18E2 lea eax,[ebp-0D4h] ;将保存8的地址赋给eax.
    4. 00FC18E8 push eax ;地址压栈
    5. 00FC18E9 lea ecx,[ebp-0E0h] ;将保存5的地址赋给ecx
    6. 00FC18EF push ecx ;将地址压入栈中
    7. 00FC18F0 call add (0FC138Eh)
    8. 00FC18F5 add esp,8 ;回收栈
    9. 00FC18F8 mov dword ptr [result],eax 

    1. const int &add(const int &a, const int &b)
    2. {
    3. 002217C0 push ebp
    4. 002217C1 mov ebp,esp
    5. 002217C3 sub esp,0CCh ;开辟局部栈空间,大小为0cch
    6. 002217C9 push ebx
    7. 002217CA push esi
    8. 002217CB push edi
    9. 002217CC lea edi,[ebp-0CCh] ;
    10. 002217D2 mov ecx,33h
    11. 002217D7 mov eax,0CCCCCCCCh
    12. 002217DC rep stos dword ptr es:[edi]
    注意.以上局部栈空间大小在 esp到esp-0cch之间.当函数调用完此空间将回收(并不是真正意义的回收.只是改变栈指针罢了.原来的数值还在.不过如果此栈被反复调用(这就是为何我重复调用的原因).栈的数据当然改变)
    1. 00FC17DE mov eax,dword ptr [a] ;将临时对象5的地址赋给eax (const int &a) [a]保存的是临时对象5的
    2. 00FC17E1 mov ecx,dword ptr [eax] ;将eax保存的值给ecx
    3. 00FC17E3 mov edx,dword ptr [b] ;将临时对象b的地址赋给edx
    4. 00FC17E6 add ecx,dword ptr [edx] ;将edx保存的值加到ecx中
    5. 00FC17E8 mov dword ptr [ebp-0C8h],ecx ;将结果保存到ebp-0c8h中(临时对象)
    6. 00FC17EE lea eax,[ebp-0C8h] ;将结果地址赋给eax
    7. }
    8. 执行完Add函数后将临时对象的地址保存到result引用中
    9. 00FC18F8 mov dword ptr [result],eax 
    注意了 return a+b;开辟的临时对象在ebp-0c8h处.处于局部栈之内!!!(ebp~ebp-0xcch).当add调用完后..将此回收地址赋给了result引用.于是出现了结果乱了的情况了

    2.初始化一个常量引用所引发的临时对象
      当初始化一个常量引用(const reference)时,如果给定的初始化对象类型与目标引用类型不同(但是两者  能够相互转换),需要产生临时对象;
    对于局部const int  temp=10这类变量.即使取地址使得其改变也不会有任何变化.
    double db=10.000;
    int &q=db;
    以上会报错.
    因为实际他会转化为 int temp=(int) db; int &a=temp;.本意是想通过a可以改变db.但实现却不可以改变(改变的是Temp).因此.编译器将会报错

    当然如果是 const int &a=db;这样编译器将不会报错.因为const修饰这个temp(db)不会改变的
    1. double db = 10;
    2. 00EB1868 movsd xmm0,mmword ptr ds:[0EB6B38h]
    3. 00EB1870 movsd mmword ptr [db],xmm0
    4. const int &q = db;
    5. 00EB1875 cvttsd2si eax,mmword ptr [db] ;db的值10赋给eax
    6. 00EB187A mov dword ptr [ebp-28h],eax ;将eax赋给ebp-28h(就是临时对象)
    7. 00EB187D lea ecx,[ebp-28h]
    8. 00EB1880 mov dword ptr [q],ecx


    3.修改const 常量的值
    1. #include<iostream>
    2. #include<stdlib.h>
    3. using namespace std;
    4. const int &add(const int &a, const int &b)
    5. {
    6. return a + b;
    7. }
    8. int main()
    9. {
    10. const int temp = 10;
    11. int *p = (int *)&temp;
    12. *p = 10000;
    13. cout << *p << endl;
    14. cout << temp << endl;
    15. system("pause");
    16. }

    以上*p输出10000,但是temp输出10;因为const int temp=10在编译阶段就已经知道其值了
    1. cout << temp << endl;
    2. 002C4F91 push 2C1069h
    3. 002C4F96 mov edi,esp
    4. 002C4F98 push 0Ah ;将10压栈进行输出.所以..反正汇编语言是这样解释的..那就是编译器的规则了
    5. 002C4F9A mov ecx,dword ptr ds:[2CA0A8h]
    6. 002C4FA0 call dword ptr ds:[2CA0A0h]




    最简单程序
    1. #include<iostream>
    2. #include<stdlib.h>
    3. using namespace std;
    4. int main()
    5. {
    6. const int &p = 1;
    7. system("pause");
    8. }
    常量引用也会分配变量内存的.引用一个常量将会产生一个临时对象.临时对象赋值为1.然后将临时对象地址赋给引用.引用的底层实现其实也是一个指针常量罢了
    1. const int &p = 1;
    2. 002618E8 mov dword ptr [ebp-18h],1 ;ebp-18h是临时对象.将1赋给临时对象
    3. 002618EF lea eax,[ebp-18h] ;取出临时对象的地址
    4. 002618F2 mov dword ptr [p],eax ;将地址赋给p










  • 相关阅读:
    [NOI2010]航空管制
    [POI2008]POD-Subdivision of Kingdom
    CF17C Balance
    [HAOI2007]理想的正方形
    [Code+#1]大吉大利,晚上吃鸡!
    HDU 3371
    hdu1102
    最短路算法、应用、模板总结
    csu十月月赛 并查集+分组背包
    csu 十月月赛 最短路+最小费用
  • 原文地址:https://www.cnblogs.com/zengyiwen/p/5679160.html
Copyright © 2011-2022 走看看