从一个乘法来分析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 ...
随机推荐
- ABAP 日期时间函数(转)
转自:http://www.sapjx.com/abap-datetime-function.html 函数名称 (内页-点击名称可查看操作) 函数说明 备注 FIMA_DATE_CREATE RP_ ...
- Exploring Python Code Objects
Exploring Python Code Objects https://late.am/post/2012/03/26/exploring-python-code-objects.html Ins ...
- SVN 冲突文件快速解决方法
精简的美丽...... 现在几乎没有几个写代码的人不用snv来存储代码了吧! 但是,在实际操作中,多人对同一文件读写造成冲突是时有发生的事.这个时候解决的方法就是打开文件找出冲突的地方.如果冲突的部分 ...
- python中文处理之encode/decode函数
python中文处理相信迷惑过不少同学.下面说说python2/3的encode和decode函数. python2中,使用decode()和encode()来进行解码和编码,以unicode类型作为 ...
- jq选择器 第一部分
没有什么新意,全是从网上摘抄的,如果哪天忘了,就来查查吧. 1. id选择器(指定id元素) 将id="one"的元素背景色设置为黑色.(id选择器返单个元素) $(documen ...
- Python学习笔记 第一课 列表
Python的列表就像是一个数组: 一.创建列表 movies=["The Holy Grail","Then Life of Brian","The ...
- Windows环境下安装导入tornado
首先,一台安装并配置好了python,我的python版本的肯定是2.7,直接进入tornado的环节: 下载tornado的压缩包,我的下载地址为:https://codeload.github.c ...
- Angular 2 从0到1 (三)
作者:王芃 wpcfan@gmail.com 第一节:Angular 2.0 从0到1 (一)第二节:Angular 2.0 从0到1 (二)第三节:Angular 2.0 从0到1 (三)第四节:A ...
- css水平居中总结
前言 看了好多篇帖子,发现没有一个能够直接让新手很快上手使用水平居中布局的,所以在此进行一番总结,也算是我对水平居中布局的一点点积累沉淀,同时也方便初学者们拿来即用. 一.元素分类 1.行内元素 行内 ...
- css hack 大全 各个浏览器的css
各个浏览器的css hack区别属性: IE6: _zoom:1; IE6/7: *zoom:1; IE6/7/8/9 :\9 各个浏览器的css hack区别规则 IE6: *html{} IE7: ...