加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

关于bit操作(备忘)

(2011-06-07 15:26:41)
标签:

杂谈

  今天发现一个奇怪的现象,用linux内核的bitops.h里面的bit_set和test_bit居然没有不用汇编的代码快。
  记录下来,备忘。
  下面是可执行程序,THUIRDB暂时没有bitops里面的实现,改用我自己写的实现了。当然bitops里的实现,nr可以很大,而我的代码nr只能是0-63之间的一个数,对THUIRDB的应用来说,足够了。


#include "stdint.h"
#include <iostream>
using namespace std;

#define BITOP_ADDR(x) "=m" (*(volatile long *) (x))

#define ADDR                            BITOP_ADDR(addr)
#ifdef CONFIG_SMP
#define LOCK_PREFIX \
                ".section .smp_locks,\"a\"\n"   \
                _ASM_ALIGN "\n"                 \
                _ASM_PTR "661f\n" \
                ".previous\n"                   \
                "661:\n\tlock; "

#else
#define LOCK_PREFIX ""
#endif

static inline void
set_bit(unsigned int nr, volatile unsigned long *addr)
{
        __asm__ volatile(LOCK_PREFIX "bts %1,%0"
                   : BITOP_ADDR(addr) : "Ir" (nr) : "memory");
}

static inline bool test_bit(int nr, volatile const unsigned long *addr)
{
        int oldbit;

        asm volatile("bt %2,%1\n\t"
                     "sbb %0,%0"
                     : "=r" (oldbit)
                     : "m" (*(unsigned long *)addr), "Ir" (nr));

        return oldbit!=0;
}
static  void _set_bit(int nr, uint64_t* addr)
{
        addr[0] |= ( 1UL << nr);
};

static bool _test_bit(int nr,uint64_t* addr)
{
        return  (0 < (addr[0] & (1UL<<nr)));
};


int main(void)
{
        uint64_t bit_arr=0;
        #ifdef T1
        for(int i = 0; i<1000000;++i)
        {
                _set_bit(id,&bit_arr);
        }
        #endif
        #ifdef T2
        for(int i = 0; i<1000000;++i)
        {
                set_bit(id,&bit_arr);
        }
        #endif
        #ifdef T3
        for(int i = 0; i<1000000;++i)
        {
                _test_bit(id,&bit_arr);
        }
        #endif
        #ifdef T4
        for(int i = 0; i<1000000;++i)
        {
                test_bit(id,&bit_arr);
        }
        #endif
        return 0;
}


以下是反汇编的结果,可以看出用内核的方法,代码短小,但效率较低,用移位与或的方法代码多,但效率高。
部分地方%和寄存器分离,因为新浪微博很土,把% eax搞成了�x,必须分开才行。
000000000040067c <_ZL7set_bitjPVm>: //set_bit
  40067c:       55                      push   %rbp
  40067d:       48 89 e5                mov    %rsp,%rbp
  400680:       89 7d fc                mov    % edi,-0x4(%rbp)
  400683:       48 89 75 f0             mov    %rsi,-0x10(%rbp)
  400687:       48 8b 45 f0             mov    -0x10(%rbp),%rax
  40068b:       8b 55 fc                mov    -0x4(%rbp),% edx
  40068e:       0f ab 10                bts    % edx,(%rax)
  400691:       c9                      leaveq 
  400692:       c3                      retq   

0000000000400693 <_ZL8test_bitiPVKm>://test_bit
  400693:       55                      push   %rbp
  400694:       48 89 e5                mov    %rsp,%rbp
  400697:       89 7d ec                mov    % edi,-0x14(%rbp)
  40069a:       48 89 75 e0             mov    %rsi,-0x20(%rbp)
  40069e:       48 8b 45 e0             mov    -0x20(%rbp),%rax
  4006a2:       8b 55 ec                mov    -0x14(%rbp),% edx
  4006a5:       0f a3 10                bt     % edx,(%rax)
  4006a8:       19 c0                   sbb    % eax,% eax
  4006aa:       89 45 fc                mov    % eax,-0x4(%rbp)
  4006ad:       83 7d fc 00             cmpl   $0x0,-0x4(%rbp)
  4006b1:       0f 95 c0                setne  %al
  4006b4:       c9                      leaveq 
  4006b5:       c3                      retq   

00000000004006b6 <_ZL8_set_bitiPm>://_set_bit
  4006b6:       55                      push   %rbp
  4006b7:       48 89 e5                mov    %rsp,%rbp
  4006ba:       53                      push   %rbx
  4006bb:       89 7d f4                mov    % edi,-0xc(%rbp)
  4006be:       48 89 75 e8             mov    %rsi,-0x18(%rbp)
  4006c2:       48 8b 45 e8             mov    -0x18(%rbp),%rax
  4006c6:       48 8b 10                mov    (%rax),%rdx
  4006c9:       8b 45 f4                mov    -0xc(%rbp),% eax
  4006cc:       bb 01 00 00 00          mov    $0x1,% ebx
  4006d1:       48 89 de                mov    %rbx,%rsi
  4006d4:       89 c1                   mov    % eax,% ecx
  4006d6:       48 d3 e6                shl    %cl,%rsi
  4006d9:       48 89 f0                mov    %rsi,%rax
  4006dc:       48 09 c2                or     %rax,%rdx
  4006df:       48 8b 45 e8             mov    -0x18(%rbp),%rax
  4006e3:       48 89 10                mov    %rdx,(%rax)
  4006e6:       5b                      pop    %rbx
  4006e7:       c9                      leaveq 
  4006e8:       c3                      retq   

00000000004006e9 <_ZL9_test_bitiPm>://_test_bit
  4006e9:       55                      push   %rbp
  4006ea:       48 89 e5                mov    %rsp,%rbp
  4006ed:       53                      push   %rbx
  4006ee:       89 7d f4                mov    % edi,-0xc(%rbp)
  4006f1:       48 89 75 e8             mov    %rsi,-0x18(%rbp)
  4006f5:       48 8b 45 e8             mov    -0x18(%rbp),%rax
  4006f9:       48 8b 10                mov    (%rax),%rdx
  4006fc:       8b 45 f4                mov    -0xc(%rbp),% eax
  4006ff:       48 89 d3                mov    %rdx,%rbx
  400702:       89 c1                   mov    % eax,% ecx
  400704:       48 d3 eb                shr    %cl,%rbx
  400707:       48 89 d8                mov    %rbx,%rax
  40070a:       83 e0 01                and    $0x1,% eax
  40070d:       5b                      pop    %rbx
  40070e:       c9                      leaveq 
  40070f:       c3                      retq   


用-O2编译,反编译,全部内联进main函数了。
T2
0000000000400680 <main>:
  400680:       48 8d 4c 24 f8          lea    -0x8(%rsp),%rcx
  400685:       48 c7 44 24 f8 00 00    movq   $0x0,-0x8(%rsp)
  40068c:       00 00 
  40068e:       31 c0                   xor    �x,�x
  400690:       89 c2                   mov    �x,�x
  400692:       83 e2 3f                and    $0x3f,�x
  400695:       0f ab 11                bts    �x,(%rcx)
  400698:       83 c0 01                add    $0x1,�x
  40069b:       3d 40 42 0f 00          cmp    $0xf4240,�x
  4006a0:       75 ee                   jne    400690 <main+0x10>
  4006a2:       31 c0                   xor    �x,�x
  4006a4:       c3                      retq   
  4006a5:       66 66 2e 0f 1f 84 00    nopw   %cs:0x0(%rax,%rax,1)
  4006ac:       00 00 00 00

T4
0000000000400680 <main>:
  400680:       48 8d 4c 24 f8          lea    -0x8(%rsp),%rcx
  400685:       48 c7 44 24 f8 00 00    movq   $0x0,-0x8(%rsp)
  40068c:       00 00 
  40068e:       31 c0                   xor    �x,�x
  400690:       89 c2                   mov    �x,�x
  400692:       83 e2 3f                and    $0x3f,�x
  400695:       0f a3 11                bt     �x,(%rcx)
  400698:       19 d2                   sbb    �x,�x
  40069a:       83 c0 01                add    $0x1,�x
  40069d:       3d 40 42 0f 00          cmp    $0xf4240,�x
  4006a2:       75 ec                   jne    400690 <main+0x10>
  4006a4:       31 c0                   xor    �x,�x
  4006a6:       c3                      retq   
  4006a7:       66 0f 1f 84 00 00 00    nopw   0x0(%rax,%rax,1)
  4006ae:       00 00

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有