C++ 反汇编初探
来源:互联网 发布:手机淘宝联盟没有提现 编辑:程序博客网 时间:2024/05/21 12:47
因为想到昨天一道笔试题:
char *s = "Apple";
cout <<s+2;
记得算术运算符 + 号比移位运算符 << 的优先级高,可是当时笔试时脑袋很乱,以为会输出'A'+2 ...剩下的就不说了。上机调试了一下,应该是 指针s+2,然后cout 打印 字符串。这么说。
由此在网上看到一个关于运算符++、--优先级的问题(现在看来,依靠未定义的运算顺序来计算是无意义的),先看一题:
int i = 1;
cout << i++ << "," << i-- <<endl;
输出结果 0,1?为什么。我最开始认为按后缀运算符计算方法,起码也该是 i++ 返回 1(此后i=2)、i-- 返回2(此后i=1),但是结果显然和我预料的不一样。此处在 CSDN 的bbs帖子往楼下扫视,得知 cout 是对象,<< 是与它相关的运算符重载函数, “函数”两个字很重要,它表明 ① 一般参数从右至左求值(求值顺序编译器相关,不要依赖这样的求值顺序); ② 函数有返回值。cout<< 的返回值是 (*this),也就是调用者 cout, 这使得运算符 << 像 = 一样可以被连续使用。写成标准的函数调用显示更明显 cout.operator<<(i++).operator<<(i--),与赋值运算符一样,都是从左至右的调用(求值)顺序,那么先用 i=1计算 i-- (返回值为1,但 i 减为0)传参, 然后用 i=0 计算 i++(返回值0)。
再看一题:
int i=3;
cout << i++ * ++i + i-- * --i;
由于运算符本身的优先级,使得:
i++ * ++i + i-- * --i 完全等价于 ( (i++)*(++i))+((i--)*(--i))
我个人认为是 3*5 + 5*3 =30(从左至右求值),于是上机调试,vs 2008 给的结果是 18,也就是 3*3 + 3*3 =18(先求前缀表达式的值++i、--i,则i增1减1不变,整个表达式的值求完后,再求后缀表达式的值),而在 codeblocks 下调试(MinGW gdb 调试器)输出的是 30 。当然后来在 VC++ 6下调试是25, Linux 32 位也是25。
VS 2008 反汇编:
ret = i++ * ++i + i-- * --i;
004113B5 mov eax,dword ptr [i]
004113B8 add eax,1
004113BB mov dword ptr [i],eax
004113BE mov ecx,dword ptr [i]
004113C1 sub ecx,1
004113C4 mov dword ptr [i],ecx
004113C7 mov edx,dword ptr [i]
004113CA imul edx,dword ptr [i]
004113CE mov eax,dword ptr [i]
004113D1 imul eax,dword ptr [i]
004113D5 add eax,edx
004113D7 mov dword ptr [ret],eax
004113DA mov ecx,dword ptr [i]
004113DD sub ecx,1
004113E0 mov dword ptr [i],ecx
004113E3 mov edx,dword ptr [i]
004113E6 add edx,1
004113E9 mov dword ptr [i],edx
VC++ 6 汇编:
ret = i++ * ++i + i-- * --i;
0040156F mov eax,dword ptr [ebp-8]
00401572 add eax,1
00401575 mov dword ptr [ebp-8],eax
00401578 mov ecx,dword ptr [ebp-8]
0040157B imul ecx,dword ptr [ebp-8]
0040157F mov edx,dword ptr [ebp-8]
00401582 sub edx,1
00401585 mov dword ptr [ebp-8],edx
00401588 mov eax,dword ptr [ebp-8]
0040158B imul eax,dword ptr [ebp-8]
0040158F add ecx,eax
00401591 mov dword ptr [ebp-4],ecx
00401594 mov ecx,dword ptr [ebp-8]
00401597 sub ecx,1
0040159A mov dword ptr [ebp-8],ecx
0040159D mov edx,dword ptr [ebp-8]
004015A0 add edx,1
004015A3 mov dword ptr [ebp-8],edx
codeblocks:
ret = i++ * ++i + i-- * --i;
0x0040135D mov -0xc(%ebp),%eax
0x00401360 lea 0x1(%eax),%edx
0x00401363 mov %edx,-0xc(%ebp)
0x00401366 addl $0x1,-0xc(%ebp)
0x0040136A imul -0xc(%ebp),%eax
0x0040136E mov %eax,%ecx
0x00401370 mov -0xc(%ebp),%eax
0x00401373 lea -0x1(%eax),%edx
0x00401376 mov %edx,-0xc(%ebp)
0x00401379 subl $0x1,-0xc(%ebp)
0x0040137D imul -0xc(%ebp),%eax
0x00401381 add %ecx,%eax
0x00401383 mov %eax,-0x10(%ebp)
*gcc 编译器优化的汇编代码里没有继续处理后续的 i++、i--,可能是因为编译器检测到此条语句以后 i 没有再被使用,所有没有后续计算。
值得一提的是,codeblocks 用的是 GCC 编译器,GCC编译器是 Unix/Linux 标准,使用的汇编语言语法格式与Intel的手册有很大不同,Unix/Linux采用AT&T汇编格式作为汇编语言的语法格式。
如果想了解AT&T汇编可以参考文章:Linux AT&T 汇编语言开发指南
- c代码反汇编研究初探
- C++ 反汇编初探
- IDA反汇编工具初探
- IDA反汇编工具初探
- c反汇编学习汇编
- c语言反汇编公式
- 反汇编一个c程序
- C语言的反汇编
- c语言反汇编代码
- 反汇编 C 语言程序
- C语言程序反汇编
- C反汇编示例分析
- gdb 反汇编.c程序
- c代码反汇编研究初探(1),DEBUG篇。http://xue23.blog.163.com/blog/static/9793442005329319570/
- 程序员的吸星大法-IDA反汇编工具初探
- 程序员的吸星大法-IDA反汇编工具初探
- C语言的反汇编代码
- 一段简单的C反汇编
- Eclipse 编程时候常用快捷建
- Apriori算法的C++实现
- 线程间通信 等待唤醒机制 wait notify notifyAll lock Condition唤醒 停止线程interrupt 守护线程setDaemon join yield
- Active MQ无法收到信息
- 基于STL的内存池类
- C++ 反汇编初探
- Windows7下SPIN6.2.6版本及ispin安装
- msgsnd()函数 msgrcv()函数
- 立图教育-专业的职业培训机构
- android4.2 增添永不休眠选项
- 单播、组播和广播 区别
- Java与Highcharts实例(一) - Highcharts资料整理
- getsockname与getpeername的使用
- msgget()函数