前段时间,我有坚持在线学习了一门课程 Stanford 的 《编程范式》
http://v.163.com/special/opencourse/paradigms.html
自认为也学习了很多年计算机语言,C,C++,Java,Python等都有间断或者不间断的应用。但是总是有种高空架楼之感。跟着上完这门课,因为它对基础知识讲解的非常透彻,从下到上,明白了语言的内存操作,再写或者读代码都会有些高屋建瓴的效果。
今天和我的一个同事一起翻译了一段PPC 下的汇编代码,顿时又觉得自己确实差了一大截,C语言的那点零星知识又变成了渣渣...:(
懂汇编的人绝对是精通C语言,对内存数据结构的领悟都不是一个层次上滴。
遥想起当年学习微机原理8086 汇编语言的情景,清晰的竟然只有那个儒雅老头的中山装了,可惜可惜
常用的PPC 的汇编指令也就那么多,认为最关键有两点:
1>. 要从内存的角度知道数据结构是如何操作的,程序归根到底无非是对数据的处理,所以根据内存操作猜出全局的结构和变量是很有益的
2>. 流程控制上经常会有编译器的优化,不要急着决定使用哪一种流程控制,先逐行翻译过来,尽量把所有的变量替换后再选择合适的流程控制组织函数代码
Detail Info:
- 在PPC下的汇编代码
0012b7b0 <findSymbol>: 12b7b0: 94 21 ff e0 stwu r1,-32(r1) 12b7b4: 7c 08 02 a6 mflr r0 12b7b8: 7f 86 28 00 cmpw cr7,r6,r5 12b7bc: 93 41 00 08 stw r26,8(r1) 12b7c0: 7c 9a 23 78 mr r26,r4 12b7c4: 93 61 00 0c stw r27,12(r1) 12b7c8: 7c 7b 1b 78 mr r27,r3 12b7cc: 93 a1 00 14 stw r29,20(r1) 12b7d0: 7c bd 2b 78 mr r29,r5 12b7d4: 93 c1 00 18 stw r30,24(r1) 12b7d8: 7c de 33 78 mr r30,r6 12b7dc: 90 01 00 24 stw r0,36(r1) 12b7e0: 93 81 00 10 stw r28,16(r1) 12b7e4: 93 e1 00 1c stw r31,28(r1) 12b7e8: 40 bc 00 14 bge cr7,12b7fc <findSymbol+0x4c> 12b7ec: 48 00 00 48 b 12b834 <findSymbol+0x84> 12b7f0: 3b df ff ff addi r30,r31,-1 12b7f4: 7f 9e e8 00 cmpw cr7,r30,r29 12b7f8: 41 9c 00 3c blt cr7,12b834 <findSymbol+0x84> 12b7fc: 7c 1d f2 14 add r0,r29,r30 12b800: 7f 44 d3 78 mr r4,r26 12b804: 7c 1f 0e 70 srawi r31,r0,1 12b808: 7f ff 01 94 addze r31,r31 12b80c: 57 e9 18 38 rlwinm r9,r31,3,0,28 12b810: 7c 69 d8 2e lwzx r3,r9,r27 12b814: 7f 89 da 14 add r28,r9,r27 12b818: 4b ff fe 59 bl 12b670 <verStrcmp> 12b81c: 2f 83 00 00 cmpwi cr7,r3,0 12b820: 41 9e 00 40 beq cr7,12b860 <findSymbol+0xb0> 12b824: 41 9d ff cc bgt cr7,12b7f0 <findSymbol+0x40> 12b828: 3b bf 00 01 addi r29,r31,1 12b82c: 7f 9e e8 00 cmpw cr7,r30,r29 12b830: 40 9c ff cc bge cr7,12b7fc <findSymbol+0x4c> 12b834: 80 01 00 24 lwz r0,36(r1) 12b838: 38 60 00 00 li r3,0 12b83c: 83 41 00 08 lwz r26,8(r1) 12b840: 83 61 00 0c lwz r27,12(r1) 12b844: 83 81 00 10 lwz r28,16(r1) 12b848: 7c 08 03 a6 mtlr r0 12b84c: 83 a1 00 14 lwz r29,20(r1) 12b850: 83 c1 00 18 lwz r30,24(r1) 12b854: 83 e1 00 1c lwz r31,28(r1) 12b858: 38 21 00 20 addi r1,r1,32 12b85c: 4e 80 00 20 blr 12b860: 80 01 00 24 lwz r0,36(r1) 12b864: 80 7c 00 04 lwz r3,4(r28) 12b868: 83 41 00 08 lwz r26,8(r1) 12b86c: 83 61 00 0c lwz r27,12(r1) 12b870: 7c 08 03 a6 mtlr r0 12b874: 83 81 00 10 lwz r28,16(r1) 12b878: 83 a1 00 14 lwz r29,20(r1) 12b87c: 83 c1 00 18 lwz r30,24(r1) 12b880: 83 e1 00 1c lwz r31,28(r1) 12b884: 38 21 00 20 addi r1,r1,32 12b888: 4e 80 00 20 blr
- 翻译出来的C (原来是二分法递归查找)
typedef struct{ char* name; void* addr; } VerSymbolEntry; void* findSymbol(VerSymbolEntry* symtbl, char* name, UINT32 begin, UINT32 end) { int i,status; char* p; while(1) { if(end < begin) return NULL; i = (begin + end) >> 1; p = (char*)symtbl + (i <<3 ) & (~0x7); status = verStrcmp(p,name); if( status == 0) retrun (void*) (p + 4); else if(status >0) end = i - 1; else begin = i + 1; } }
在网上搜索到了另一种二分法递归实现的方法 我会觉得我们写的一段更简洁明了一些

/************************************************************************** 函数名称:用递归实现二分法查找 功能描述: 输入参数: 返 回: **************************************************************************/ int binarysearch2(int array[],int key,int low,int high) { if (low >= high) return (-1); int midle = (low + high)/2; if(array[midle] == key) return midle; if(midle == high || midle == low) //此时,只剩下了下标为high和low的两个数,确定另一个数不是key后,就确定查找完毕,并且未找到目标值 { if(array[high] == key) return high; else if(array[low] == key) return low; else return (-1); } else if(array[midle] > key) return binarysearch2(array,key,low,midle); //由于不确定排序方向,所以此处只能用midle值,而不能加1或减1 else if(array[midle] < key) //当中间值小于目标值时,在high的一侧继续查找,low变到midle位置上 return binarysearch2(array,key,midle,high); }