比較两个数的大小, 用C语言写非常easy
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 ?上面的代码很简洁。 我们看一下gcc -O3汇编出来的代码, 默认-O选项的代码我就不列出了, 读者能够自己试试下面0 : 1; }
.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]; }对于上面的三种方法, 大家能够反汇编一下, 看看那个生成的指令比較少, 也能够比較一下性能, 看看那个比較快。 能够把结果加入评论告诉我。
有误请指出。 分享请标明出处, 谢谢!