从一个乘法来分析C语言
昨天碰到一个很奇怪的问题,首先来看这段代码:
#include<stdio.h>
int main(int argc,char *argv[])
{
long num1 = ;
long long num2 = ; long long res1 = num1 * num1;
long long res2 = num2 * num2; printf("res1 = %lld\n",res1);
printf("res2 = %lld\n",res2); return ;
}
程序的运行结果如下:
这里感觉很奇怪,203879并没有超过4个字节的范围,但是它的平方超过了,于是我把它的结果存放在一个8字节数中,为什么最终结果还是显示溢出了呢?
然后我又写了一段程序,把它的汇编代码拿出来分析了一下?程序如下:
int main(int argc,char *argv[])
{
long muln = ;
long long mulnl = ; long long num1 = * ;
long long num2 = muln * muln;
long long num3 = mulnl * mulnl; return ;
}
这里我分成三种情况,一种是直接的一个整数当乘数,一个是long型的整数当乘数,还有一个是long long型的整数当作乘数,然后分别计算他们的平方,我用gdb调试的结果如下:
其中前两种情况都溢出了,只有第三种情况正常。然后我们再来查看一下他们的汇编代码,这是我用objdump反汇编出来的汇编代码:
int main(int argc,char *argv[])
{
: push %ebp
: e5 mov %esp,%ebp
: e4 f8 and $0xfffffff8,%esp
804839a: ec sub $0x30,%esp
long muln = ;
804839d: c7 0c 1c movl $0x31c67,0xc(%esp)
80483a4:
long long mulnl = ;
80483a5: c7 1c movl $0x31c67,0x10(%esp)
80483ac:
80483ad: c7 movl $0x0,0x14(%esp)
80483b4: long long num1 = * ;
80483b5: c7 b1 movl $0xad90b171,0x18(%esp)
80483bc: ad
80483bd: c7 1c ff ff ff movl $0xffffffff,0x1c(%esp)
80483c4: ff
long long num2 = muln * muln;
80483c5: 8b 0c mov 0xc(%esp),%eax
80483c9: 0f af 0c imul 0xc(%esp),%eax
80483ce: c2 mov %eax,%edx
80483d0: c1 fa 1f sar $0x1f,%edx
80483d3: mov %eax,0x20(%esp)
80483d7: mov %edx,0x24(%esp)
long long num3 = mulnl * mulnl;
80483db: 8b mov 0x14(%esp),%eax
80483df: c1 mov %eax,%ecx
80483e1: 0f af 4c imul 0x10(%esp),%ecx
80483e6: 8b mov 0x14(%esp),%eax
80483ea: 0f af imul 0x10(%esp),%eax
80483ef: c1 add %eax,%ecx
80483f1: 8b mov 0x10(%esp),%eax
80483f5: f7 mull 0x10(%esp)
80483f9: d1 add %edx,%ecx
80483fb: ca mov %ecx,%edx
80483fd: mov %eax,0x28(%esp)
: 2c mov %edx,0x2c(%esp)
: mov %eax,0x28(%esp)
: 2c mov %edx,0x2c(%esp) return ;
804840d: b8 mov $0x0,%eax
}
首先来看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中。所以我们最终得到的结果也是一个溢出的结果。
分析完了之后,发现我这是舍进求远啊,现在也不知怎么了,遇到点啥就喜欢反汇编出来看看。。。
从一个乘法来分析C语言的更多相关文章
- C++写一个简单的解析器(分析C语言)
该方案实现了一个分析C语言的词法分析+解析. 注意: 1.简单语法,部分秕.它可以在本文法的基础上进行扩展,此过程使用自上而下LL(1)语法. 2.自己主动能达到求First 集和 Follow 集. ...
- Go将统治下一个10年?Go语言发展现状分析
“本文是国内Go语言大中华区首席布道师——许式伟,在QCon2015上海站上的分享.他预测Go语言10年内一定会超过C和java,并且统治这一个10年. Go语言语法及标准库变化 Go从1.0版本到现 ...
- 《C专家编程》第三章——分析C语言的声明
前面一章我们已经说过C语言存在的一些问题和它晦涩的地方,让我们对这门神奇的语言有了更深的了解.现在这一章则集中精力来讨论C语言的声明,分为三块,首先是说明C语言声明晦涩难懂的原因和声明是如何形成的,其 ...
- 基于Spark和SparkSQL的NetFlow流量的初步分析——scala语言
基于Spark和SparkSQL的NetFlow流量的初步分析--scala语言 标签: NetFlow Spark SparkSQL 本文主要是介绍如何使用Spark做一些简单的NetFlow数据的 ...
- 以杨辉三角为例,从内存角度简单分析C语言中的动态二维数组
学C语言,一定绕不过指针这一大难关,而指针最让人头疼的就是各种指向关系,一阶的指针还比较容易掌握,但一旦阶数一高,就很容易理不清楚其中的指向关系,现在我将通过杨辉三角为例,我会用四种方法从内存的角度简 ...
- AI 的下一个重大挑战:理解语言的细微差别
简评:人类语言非常博大精妙,同一句话在不同的语境下,就有不同的含义.连人类有时候都不能辨别其中细微的差别,机器能吗?这就是人工智能的下一个巨大挑战:理解语言的细微差别.本文原作者是 Salesforc ...
- 框架源码系列四:手写Spring-配置(为什么要提供配置的方法、选择什么样的配置方式、配置方式的工作过程是怎样的、分步骤一个一个的去分析和设计)
一.为什么要提供配置的方法 经过前面的手写Spring IOC.手写Spring DI.手写Spring AOP,我们知道要创建一个bean对象,需要用户先定义好bean,然后注册到bean工厂才能创 ...
- 32 Profiling Go Programs 分析go语言项目
Profiling Go Programs 分析go语言项目 24 June 2011 At Scala Days 2011, Robert Hundt presented a paper titl ...
- 18 A GIF decoder: an exercise in Go interfaces 一个GIF解码器:go语言接口训练
A GIF decoder: an exercise in Go interfaces 一个GIF解码器:go语言接口训练 25 May 2011 Introduction At the Googl ...
随机推荐
- Quart 2D 绘制图形简单总结
0 CGContextRef context = UIGraphicsGetCurrentContext(); 设置上下文 1 CGContextMoveToPoint 开始画线 2 CGConte ...
- MySQL · 特性分析 · MDL 实现分析
http://mysql.taobao.org/monthly/2015/11/04/ 前言 在MySQL中,DDL是不属于事务范畴的,如果事务和DDL并行执行,操作相关联的表的话,会出现各种意想不到 ...
- STOMP协议规范--转载
原文地址:http://simlegate.com/2013/10/17/stomp-specification-1.2/ 摘要 STOMP是一个简单的可互操作的协议, 被用于通过中间服务器在客户端之 ...
- HBase shell 常用指令
HBase shell 常用指令 连接HBase $ ./bin/hbase shell 打开帮助 hbase(main):001:0> help 创建表 hbase(main):003:0&g ...
- Helpers\Document
Helpers\Document The document class is a collection of useful methods for working with files. To get ...
- Spket在Eclipse/MyEclipse下的安装和配置支持Ext(图文教程)
一.安装Spket 第一种方法:网上更新方式 1.插件首页:http://www.spket.com2.插件名称:Spket IDE3.更新连接(Update Site):http://www.spk ...
- js中将字符串转换成json的方式
1.eval 方式解析,实际中用的还是比较少 function evalJson(str){ var json = eval('(' + str + ')'); return json; } 2.使用 ...
- [转]永久告别Android的背景选择器Selector!无需切很多图了!
package com.zoke.custom.autobg; import android.content.Context; import android.content.res.TypedArra ...
- LeetCode 231
Power of Two Given an integer, write a function to determine if it is a power of two. /************* ...
- 逆向+两次bfs(UVA 1599)
为什么都说简单好想咧.坦白从宽看了人家的代码,涨了好多姿势,, http://blog.csdn.net/u013382399/article/details/38227917 被一个细节坑了.. 2 ...