比较两个数大小汇编解析

15 篇文章 0 订阅

比较两个数的大小, 用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];
}
对于上面的三种方法, 大家可以反汇编一下, 看看那个生成的指令比较少, 也可以比较一下性能, 看看那个比较快, 可以把结果添加评论告诉我。
有误请指出, 分享请标明出处, 谢谢!


                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值