PowerPC 反汇编二分法查找

前段时间,我有坚持在线学习了一门课程 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);
}
View Code
原文地址:https://www.cnblogs.com/2000km/p/3682469.html