g++提供了个内置的函数:__builtin_popcount,来统计整形数字的二进制表示中1的数量。我很好奇,就想看看库函数使用什么办法实现的。

一般我们自己来写这个函数,会是这样:

int popcount1(int x)
{
    int r = 0;
    while(x)
    {
        if(x&1)
            r++;
        x = x>>1;
    }
    return r;
}

或者是这样:

int popcount2(int x)
{
    int r = 0;
    while(x)
    {
        r++;
        x = x&(x-1);
    }
    return r;
}

那么g++中是怎么实现的呢?用gdb看看

测试函数如下:

#include <iostream>
using namespace std;
int main(int argc,char** argv)
{
    if(argc!=3)
        return -1;
    int c = stoi(argv[1]);
    int d = stoi(argv[2]);
    int a = __builtin_popcount(c^d);
    cout<<a<<endl;
    return 0;
}

在gdb中,运行到这个函数:

   0x5555555552de <main(int, char**)+217>:  xor    eax,DWORD PTR [rbp-0x18]
   0x5555555552e1 <main(int, char**)+220>:  mov    eax,eax
   0x5555555552e3 <main(int, char**)+222>:  mov    rdi,rax
=> 0x5555555552e6 <main(int, char**)+225>:  call   0x5555555550a0 <__popcountdi2@plt>
   0x5555555552eb <main(int, char**)+230>:  mov    DWORD PTR [rbp-0x1c],eax
   0x5555555552ee <main(int, char**)+233>:  mov    eax,DWORD PTR [rbp-0x1c]
   0x5555555552f1 <main(int, char**)+236>:  mov    esi,eax
   0x5555555552f3 <main(int, char**)+238>:  lea    rdi,[rip+0x2da6]        # 0x5555555580a0 <std::cout@@GLIBCXX_3.4>

看到这个函数了,叫__popcountdi2@plt,关于这个plt,涉及到了linux系统中dynamic shared objects的装载时重定位机制有关,这个plt(Procedure LInkage Table)涉及到延迟绑定机制的实现。具体的我后面应该会单独写一下。

下面看看popcount函数的内容:

=> 0x7ffff7ca50a0 <__popcountdi2>:      movabs rdx,0x5555555555555555
   0x7ffff7ca50aa <__popcountdi2+10>:   mov    rax,rdi
   0x7ffff7ca50ad <__popcountdi2+13>:   shr    rax,1
   0x7ffff7ca50b0 <__popcountdi2+16>:   and    rax,rdx
   0x7ffff7ca50b3 <__popcountdi2+19>:   movabs rdx,0x3333333333333333
   0x7ffff7ca50bd <__popcountdi2+29>:   sub    rdi,rax
   0x7ffff7ca50c0 <__popcountdi2+32>:   mov    rax,rdi
   0x7ffff7ca50c3 <__popcountdi2+35>:   shr    rdi,0x2
   0x7ffff7ca50c7 <__popcountdi2+39>:   and    rax,rdx
   0x7ffff7ca50ca <__popcountdi2+42>:   and    rdi,rdx
   0x7ffff7ca50cd <__popcountdi2+45>:   movabs rdx,0xf0f0f0f0f0f0f0f
   0x7ffff7ca50d7 <__popcountdi2+55>:   add    rdi,rax
   0x7ffff7ca50da <__popcountdi2+58>:   mov    rax,rdi
   0x7ffff7ca50dd <__popcountdi2+61>:   shr    rax,0x4
   0x7ffff7ca50e1 <__popcountdi2+65>:   add    rax,rdi
   0x7ffff7ca50e4 <__popcountdi2+68>:   and    rax,rdx
   0x7ffff7ca50e7 <__popcountdi2+71>:   movabs rdx,0x101010101010101
   0x7ffff7ca50f1 <__popcountdi2+81>:   imul   rax,rdx
   0x7ffff7ca50f5 <__popcountdi2+85>:   shr    rax,0x38
   0x7ffff7ca50f9 <__popcountdi2+89>:   ret

输入应该是edi,输出是rax

到这一步我就。。我太菜了,一时间看不懂。。不过应该还是很好翻译成c语言的。我在网上看到翻译过的代码,但是现在一时找不到了,听说是用了二分法?范增应该听巧妙地。整个函数都没有任何条件跳转语句,就完成了1的计数,厉害。

等我看懂了,就把这一章写完。。。

1 对 “探索__builtin_popcount”的想法;

  1. Shemales on youtubeSanta rosa breast enlargementUnited methodist western ohio conference homosexualAustralian celebs nudeYouth with regards to sexShe-male lipstick
    cockAmy reid interracial free onesArticle free sex xnxx
    Massive fake breastMidget eroticHolly hostel pornstarHow to
    lick your girlTeen parent support groupFree wild and crazy porn videosHose
    pantie trannyBig tits in clothing photo galleriesDo women mind exposing their breastsHarmony porn queen https://xnxxopen.com Chicks with big clitsBreast milk
    sucking sex storyQuestions to the opposite sexChick pic teenView profiles of sexy girlsPorn star kelle marieDaniella sex movie from real housewivesAss hole husband pittsburgh xnxx How to have
    sex video pornMature girl xxxBig round booty orgySister gives brother hand job videoFrankenstein fx foam latex maskFirst time amateurs 18Toronto bed breakfast gayTo meet single asian womenPink girl
    pussyFree sex life adviceNo tit cumGem jewelry stone vintageHow to play with your clitG masturbation spotAsian wedding reception venuesAsian comparison

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注