首页 > 代码库 > 判断某个值是否在某个范围汇编优化

判断某个值是否在某个范围汇编优化

判断某个值是否在某个范围是否在某个区间范围的代码是经常用到的,处理图片是否超出某个边界范围的时候, 我像素点设置为零, 否只做点别的

在这个过程中, 我们可能要进行一次饱和处理, 于是乎写下面的代码:

if (val > 0 && val < 256)
{
     // do something
}
else 
{
    // do something
}

于是乎我就写了下面这样一个函数来讨论我们的问题

bool isRangAt1(int val, int min, int max)
{
    if (val > min && val < max)
    {
        return true;
    }
    return false;
}
这个函数很简单, 就是判断一个value是否是在(min, max) 这个范围内, 

当然这里我没有考虑min < max 的容错处理;

这样的代码好不好呢, 我们有没有别的实现方式呢, 当然有, 至少我们可以把if语句换成条件语句,如下:

bool isRangAt2(int val, int min, int max)
{
    return val <= min ? false : val < max ? true : false;
}
当然我认为是第二个实现比叫好(从反汇编的生成的指令看), 但是可读性可能就差一些, 我们 还有另外一种实现

bool isRangAt3(int val, int min, int max)
{
    return (val > min) ^ (val > max);
}
以上三种实现功能上都是一个样的, 但是可读性递减, 效率应该是递增, 

特别是第三种, 用了比较和异或运算实现的, 这样就消除了if语句的跳转, 从而提高效率,

这也是汇编里面优化的一种策略, 当然这种方法我开始我也想到能这么做, 我是通过放会变出来看出来的

这是前面两种方法的汇编(大家可以在ubutnu装一个交差编译工具, 这个汇编是powerpc 的), 大家可以比较一下:

	.file	"range.cpp"
	.section	".toc","aw"
	.section	".text"
	.align 2
	.globl isRangAt1
	.section	".opd","aw"
	.align 2
isRangAt1:
	.long	.isRangAt1,.TOC.@tocbase32
	.size	isRangAt1,.-isRangAt1
	.previous
	.type	.isRangAt1,@function
	.globl	.isRangAt1
.isRangAt1:
.LFB11:
	cmpw 7,3,4
	li 9,1
	li 0,0
	cmpw 6,3,5
	ble 7,.L4
	bge 6,.L8
.L5:
	mr 0,9
.L4:
	extsw 3,0
	blr
.L8:
	li 9,0
	b .L5
.LFE11:
	.size	.isRangAt1,.-.isRangAt1
	.globl __gxx_personality_v0
	.align 2
	.globl isRangAt2
	.section	".opd","aw"
	.align 2
isRangAt2:
	.long	.isRangAt2,.TOC.@tocbase32
	.size	isRangAt2,.-isRangAt2
	.previous
	.type	.isRangAt2,@function
	.globl	.isRangAt2
.isRangAt2:
.LFB12:
	cmpw 7,3,4
	li 9,1
	li 0,0
	cmpw 6,3,5
	ble 7,.L12
	ble 6,.L15
.L13:
	mr 0,9
.L12:
	extsw 3,0
	blr
.L15:
	li 9,0
	b .L13
.LFE12:
	.size	.isRangAt2,.-.isRangAt2
	.ident	"GCC: (GNU) 4.1.1 (SDK420, $Rev: 3547 $)"
比较一下大家会发现, 方法1和方法二几乎没有一样, 当然这里我想说的一下, 这个汇编是我用gcc -O3出来的结果, 有些没有的指令可能已经被删除了, 所以一样,

但是很多时候我还是觉得第二种比第一种简洁, 对于第三中方法实现的汇编, 我暂时不给出汇编, 读者可以自己反汇编出来看看, 记得-O3哦。


有错欢迎指出, 分享请标明出处, 谢谢!







判断某个值是否在某个范围汇编优化