首页 / C语言 / 从一个乘法来分析C语言
从一个乘法来分析C语言
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了从一个乘法来分析C语言,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2802字,纯文字阅读大概需要5分钟。
内容图文
昨天碰到一个很奇怪的问题,首先来看这段代码:
1 #include<stdio.h> 2int main(int argc,char *argv[]) 3{ 4long num1 = 203879; 5longlong num2 = 203879; 6 7longlong res1 = num1 * num1; 8longlong res2 = num2 * num2; 910 printf("res1 = %lld\n",res1); 11 printf("res2 = %lld\n",res2); 1213return0; 14 }
程序的运行结果如下:
这里感觉很奇怪,203879并没有超过4个字节的范围,但是它的平方超过了,于是我把它的结果存放在一个8字节数中,为什么最终结果还是显示溢出了呢?
然后我又写了一段程序,把它的汇编代码拿出来分析了一下?程序如下:
1 int main(int argc,char *argv[]) 2{ 3long muln = 203879; 4longlong mulnl = 203879; 5 6longlong num1 = 203879 * 203879; 7longlong num2 = muln * muln; 8longlong num3 = mulnl * mulnl; 910return0; 11 }
这里我分成三种情况,一种是直接的一个整数当乘数,一个是long型的整数当乘数,还有一个是long long型的整数当作乘数,然后分别计算他们的平方,我用gdb调试的结果如下:
其中前两种情况都溢出了,只有第三种情况正常。然后我们再来查看一下他们的汇编代码,这是我用objdump反汇编出来的汇编代码:
1 int main(int argc,char *argv[]) 2{ 38048394: 55push %ebp 48048395: 89 e5 mov %esp,%ebp 58048397: 83 e4 f8 and $0xfffffff8,%esp 6 804839a: 83 ec 30sub $0x30,%esp 7 long muln = 203879; 8 804839d: c7 44240c67 1c 03 movl $0x31c67,0xc(%esp) 9 80483a4: 0010 long long mulnl = 203879; 11 80483a5: c7 44241067 1c 03 movl $0x31c67,0x10(%esp) 12 80483ac: 0013 80483ad: c7 442414000000 movl $0x0,0x14(%esp) 14 80483b4: 001516 long long num1 = 203879 * 203879; 17 80483b5: c7 44241871 b1 90 movl $0xad90b171,0x18(%esp) 18 80483bc: ad 19 80483bd: c7 4424 1c ff ff ff movl $0xffffffff,0x1c(%esp) 20 80483c4: ff 21 long long num2 = muln * muln; 22 80483c5: 8b 44240cmov 0xc(%esp),%eax 23 80483c9: 0f af 44240cimul 0xc(%esp),%eax 24 80483ce: 89 c2 mov %eax,%edx 25 80483d0: c1 fa 1f sar $0x1f,%edx 26 80483d3: 89442420mov %eax,0x20(%esp) 27 80483d7: 89542424mov %edx,0x24(%esp) 28 long long num3 = mulnl * mulnl; 29 80483db: 8b 442414mov 0x14(%esp),%eax 30 80483df: 89 c1 mov %eax,%ecx 31 80483e1: 0f af 4c 2410imul 0x10(%esp),%ecx 32 80483e6: 8b 442414mov 0x14(%esp),%eax 33 80483ea: 0f af 442410imul 0x10(%esp),%eax 34 80483ef: 01 c1 add %eax,%ecx 35 80483f1: 8b 442410mov 0x10(%esp),%eax 36 80483f5: f7 642410 mull 0x10(%esp) 37 80483f9: 01 d1 add %edx,%ecx 38 80483fb: 89 ca mov %ecx,%edx 39 80483fd: 89442428mov %eax,0x28(%esp) 408048401: 895424 2c mov %edx,0x2c(%esp) 418048405: 89442428mov %eax,0x28(%esp) 428048409: 895424 2c mov %edx,0x2c(%esp) 4344 return 0; 45 804840d: b8 00000000mov $0x0,%eax 46 }
首先来看num1的代码(16~20行),203879(31C67H)平方为41566646641(9AD90B171H),编译器直接把这个结果计算了出来,然后取出结果的4个字节,存放到了num1中,然后再用符号位来填充高4字节。
接下来我们再来看num2的代码(21~27行),首先它把203879存放到eax里面,再把相乘的平方结果存放到eax里面,由于eax是32位,所以存放的时候就舍去了高4位,只存放了低4个字节。接下来做的就是判断这个数的符号位是什么,然后再用移位运算得到32个1存放在edx里面,最后再把这个edx的值存放到num2的高四个字节里面。
OK,通过上面这段汇编代码分析,我们再来从C语言的概念上来分析这句代码:
long long num2 = muln * muln ;
首先muln是一个4字节的整数,然后muln * muln得到的结果也是一个四字节的整数(这里产生了溢出),然后再把这个结果转换成8字节的整数,存放到num2中。所以我们最终得到的结果也是一个溢出的结果。
分析完了之后,发现我这是舍进求远啊,现在也不知怎么了,遇到点啥就喜欢反汇编出来看看。。。
原文:http://www.cnblogs.com/bwangel23/p/4274391.html
内容总结
以上是互联网集市为您收集整理的从一个乘法来分析C语言全部内容,希望文章能够帮你解决从一个乘法来分析C语言所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。