`
阿尔萨斯
  • 浏览: 4106928 次
社区版块
存档分类
最新评论

比较两个数大小汇编解析

 
阅读更多

比较两个数的大小, 用C语言写很容易

int compare1(int x, int y)
{
    if (x > y)
    {
        return 1;
    } 
    else if (x == y) 
    {
        return 0;
    }
    else
    {
        return -1;
    }
}

用gcc生成powerPC ppu汇编指令, 用默认的-O选项

生成的汇编代码:

.compare1:
.LFB39:
	stdu 1,-80(1)
.LCFI3:
	std 31,72(1)
.LCFI4:
	mr 31,1
.LCFI5:
	mr 0,3
	mr 9,4
	stw 0,128(31)
	stw 9,136(31)
	lwz 9,128(31)
	lwz 0,136(31)
	cmpw 7,9,0
	ble 7,.L4
	li 0,1
	stw 0,48(31)
	b .L6
.L4:
	lwz 0,128(31)
	lwz 9,136(31)
	cmpw 7,0,9
	bne 7,.L7
	li 9,0
	stw 9,48(31)
	b .L6
.L7:
	li 0,-1
	stw 0,48(31)
.L6:
	lwz 9,48(31)
	extsw 0,9
	mr 3,0
	ld 11,0(1)
	ld 31,-8(11)
	mr 1,11
	blr
当然这么多指令, 很多都不太清楚, 但是有点写操作当中是有些压栈了的,下面就用gcc 的-O3 选项就行优化
.compare1:
.LFB39:
	cmpw 7,3,4
	li 3,1
	ble 7,.L11
.L6:
	extsw 3,3
	blr
.L11:
	li 3,0
	beq 7,.L6
	li 3,-1
	b .L6
这样得到的代码还是明显少了很多, 但是我用if语句, 跳转比较多, 大家都知道跳转是比较耗时的

所以我就写了另外的一种写法:

int compare2(int x, int y)
{
    return x < y ? -1 : x == y ? 0 : 1;
}
上面的代码非常简洁, 我们看一下gcc -O3汇编出来的代码, 默认-O选项的代码我就不列出了, 读者可以自己试试以下

.compare2:
.LFB40:
	xor 0,3,4     // r3 = x, r4 = y
	cmpw 7,3,4
	srawi 11,0,31 // r0算术右移31位
	li 9,-1
	xor 3,11,0
	subf 3,3,11   // 这个指令的意思是说r3 = r11 - r3
	blt 7,.L15
	srwi 9,3,31  // r9 = r3 逻辑右移31位
.L15:
	extsw 3,9
	blr
我大概知道了编译是怎么做, 所以我自己根据编译的做法, 自己也写了一个:

        li      r9, -1           // r9 = -1
        r6, r3, r4
        cmpwi   cr7, r6, 0      // cal the diff
        blt     cr7, .Out        // jump to store -1
        li      r7, 0
        subf    r6, r6, r7      // cal 0 - diff, if the diff = 0, then r6 = 0, diff > 0, r6 < 0
        srwi    r9, r6,31       // mov the sign bit to r9, 
        .Out:
        mr      r3, r9          // r3 是存储返回值的寄存器
        blr

以上就是比较两个数的大小的C和汇编的分析, 但是用if语句的话跳转比较多。

另外比较有两个比较常用的功能就是求两个数的最大值或者是最小值
// 写法1
inline int max(int x, int y)
{
  if (x >= y)
  {
    return x;
  }
  return y;
}

inline int min(int x, int y)
{
  if (x < y)
  {
    return x;
  }
  return y;
}

// 写法2
inline int max(int x, int y)
{
  return x >= y ? x : y;
}

inline int min(int x, int y)
{
  return x < y ? x : y;
}

// 写法3
inline int max(int x, int y)
{
  int buf[] = {x, y};
  int shif = sizeof(int) * 8 - 1;                             // get the number for shif bits
  unsigned int sign = 0 ^ (((unsigned int)(x - y)) >> shif);  // if x > y, then sign = 0, then return x

  return buf[sign];
}

inline int min(int x, int y)
{
  int buf[] = { x, y };
  int shif = sizeof(int) * 8 - 1;                             // get the number for shif bits
  unsigned int sign = 1 ^ (((unsigned int)(x - y)) >> shif);  // if x < y, then sign = 0, then return x

  return buf[sign];
}
对于上面的三种方法, 大家可以反汇编一下, 看看那个生成的指令比较少, 也可以比较一下性能, 看看那个比较快, 可以把结果添加评论告诉我。
有误请指出, 分享请标明出处, 谢谢!



  


  
分享到:
评论

相关推荐

    你必须知道的495个C语言问题

    3.15 我要检查一个数是不是在另外两个数之间,为什么if(abc)不行? 3.16 为什么如下的代码不对?inta=1000,b=1000;longintc=a*b; 3.17 为什么下面的代码总是给出0?doubledegC,degF;degC=5.0/9*(degF-32); ...

    《你必须知道的495个C语言问题》

    3.15 我要检查一个数是不是在另外两个数之间,为什么if(a b c)不行? 40 3.16 为什么如下的代码不对?int a=1000, b=1000; long int c=a * b; 40 3.17 为什么下面的代码总是给出0?double degC, degF; degC= ...

    vc++ 应用源码包_6

    压缩包内有两个源码包,一个是注册机源程序,另一个是解密机的源程序,一套完整的参考实例。 VC+MapX源码含GPS跟踪演示 VC3D 利用VC编程在界面上实现3D文字 在MFC应用程序中浏览PDF、Word文档文件 vcdialog 自...

    vc++ 应用源码包_5

    压缩包内有两个源码包,一个是注册机源程序,另一个是解密机的源程序,一套完整的参考实例。 VC+MapX源码含GPS跟踪演示 VC3D 利用VC编程在界面上实现3D文字 在MFC应用程序中浏览PDF、Word文档文件 vcdialog 自...

    JAVA上百实例源码以及开源项目

    两个例子,无状态SessionBean可会话Bean必须实现SessionBean,获取系统属性,初始化JNDI,取得Home对象的引用,创建EJB对象,计算利息等;在有状态SessionBean中,用累加器,以对话状态存储起来,创建EJB对象,并将...

    JAVA上百实例源码以及开源项目源代码

    两个例子,无状态SessionBean可会话Bean必须实现SessionBean,获取系统属性,初始化JNDI,取得Home对象的引用,创建EJB对象,计算利息等;在有状态SessionBean中,用累加器,以对话状态存储起来,创建EJB对象,并将...

    1345个易语言模块

    1345个易语言模块,易语言模块大集合,够你用的啦 1亦思验证码识别1.5免费版.ec 24位转单色位图模块.ec 32张发牌.ec 3D引擎支持库-eOgre.ec 69msn.ec ACCESS 到高级表格.ec Access操作.ec Access数据库压缩修复新建....

    2020易语言模块大全持续更新2.zip

    给选择夹加两个命令.ec 绿色软件自动升级模块.ec 联众代答HTTP答题.ec 股票查询.ec 良剑科技-外挂作坊模块(新年礼品).ec 花样进度条1.0.ec 获取字符串尺寸.ec 获取本机互联网IP地址.ec 蓝风模块.ec 行数.ec 解析LRC...

    vc++ 应用源码包_1

    压缩包内有两个源码包,一个是注册机源程序,另一个是解密机的源程序,一套完整的参考实例。 VC+MapX源码含GPS跟踪演示 VC3D 利用VC编程在界面上实现3D文字 在MFC应用程序中浏览PDF、Word文档文件 vcdialog 自...

    vc++ 开发实例源码包

    大家都知道,现在流行的检测硬件软件视乎很神秘,我们要获得各种信息好像比较难.但大多数这种软件或多或少的使用了WMI,如果我们能熟练掌握相信你也做的处理.另外WMI除了查询还能修改,比如3389端口,账号,密码,服务启动...

    vc++ 应用源码包_2

    压缩包内有两个源码包,一个是注册机源程序,另一个是解密机的源程序,一套完整的参考实例。 VC+MapX源码含GPS跟踪演示 VC3D 利用VC编程在界面上实现3D文字 在MFC应用程序中浏览PDF、Word文档文件 vcdialog 自...

    vc++ 应用源码包_3

    压缩包内有两个源码包,一个是注册机源程序,另一个是解密机的源程序,一套完整的参考实例。 VC+MapX源码含GPS跟踪演示 VC3D 利用VC编程在界面上实现3D文字 在MFC应用程序中浏览PDF、Word文档文件 vcdialog 自...

    1350多个精品易语言模块

    1350多个精品易语言模块提供下载介绍 1亦思验证码识别1.5免费版.ec 24位转单色位图模块.ec 32张发牌.ec 3D引擎支持库-eOgre.ec 69msn.ec ACCESS 到高级表格.ec Access操作.ec Access数据库压缩修复新建.ec ACCSEE...

    Windows内核安全与驱动开发光盘源码

    8.5.7 打开两种键盘端口驱动寻找设备 131 8.5.8 搜索在KbdClass类驱动中的地址 133 8.6 Hook键盘中断反过滤 135 8.6.1 中断:IRQ和INT 136 8.6.2 如何修改IDT 136 8.6.3 替换IDT中的跳转地址 137 8.6.4 QQ的PS...

    Windows内核安全驱动开发(随书光盘)

    8.5.7 打开两种键盘端口驱动寻找设备 131 8.5.8 搜索在KbdClass类驱动中的地址 133 8.6 Hook键盘中断反过滤 135 8.6.1 中断:IRQ和INT 136 8.6.2 如何修改IDT 136 8.6.3 替换IDT中的跳转地址 137 8.6.4 QQ的PS...

    易语言模块914个

    取拼音首个字母.ec 取拼音首模块.ec 取按键名称模块.ec 取控件或窗口的标题.ec 取操作系统类别.ec 取文件时间.ec 取文件版本信息.ec 取文件相关联的图标.ec 取文件行数.ec 取文本行数.ec 取易模块信息.ec...

    IOI国家集训队论文集1999-2019

    饶向荣 -《病毒的DNA——剖析一道字符匹配问题解析过程》 邵烜程 -《数学思想助你一臂之力》 王知昆 -《浅谈用极大化思想解决最大子矩形问题》 伍 昱 -《由对称性解2-SAT问题》 项荣璟 -《充分利用问题性质——...

Global site tag (gtag.js) - Google Analytics