比较两个数的大小, 用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]; }
有误请指出, 分享请标明出处, 谢谢!