gnu cc扩展和ABI

gnc cc扩展标准c的语法,非常强大!!!详情请见:

http://uw714doc.sco.com/cgi-bin/info2html?%28gcc.info%29C%2520Extensions&lang=en

http://tigcc.ticalc.org/doc/gnuexts.html#SEC104

https://gcc.gnu.org/onlinedocs/gcc-4.4.5/gcc/C-Extensions.html#C-Extensions

 

ABI是application binary interface的缩写,规定了struct布局,函数调用规则,数据大小等。

非常值得研究。

比如:x86-64下,rbx,rbp,r12-r15是called saved registers。

参考文献:http://www.x86-64.org/documentation/abi.pdf

people.freebsd.org/~obrien/amd64-elf-abi.pdf

 

#define my_min(x, y)  ({const typeof(x) __x = x; \
    const typeof(y) __y = y; \
    (void) (&__x == &__y); \
    __x < __y ? __x : __y;})

struct Str
{
    int a;
    char b;
    short c;
} __attribute__((packed));

#define ERR_PRINTF(fmt, args...) {\
    char msg[1024]; \
    snprintf(msg, sizeof(msg), "%s:%d "fmt"\n", __FUNCTION__, __LINE__, ##args);\
    printf("%s", msg); \
}

#define ERR_PRINTF2(fmt, ...) \
    printf("%s:%d "fmt"\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)

#define likely(x)  __builtin_expect((x), 1)
#define unlikely(x)  __builtin_expect((x), 0)

__attribute__ ((noinline))   bool CAS_64b(uint64_t* ptr, uint32_t* oldv, uint32_t* newv)
{
    bool ret = false;
    __asm__ __volatile__ ( 
        "pushl %%ebx;"
        "movl %4, %%ebx;"
        "lock cmpxchg8b %1;\n"
        "sete %0;\n"
        "popl %%ebx;\n"
        :"=m"(ret),"+m"(*(uint64_t volatile*)(ptr)) 
        :"a"(oldv[0]), "d"(oldv[1]), "D"(newv[0]), "c"(newv[1]) 
        :"memory"); 
        return ret;
}

//#if defined(__x86_64__)
//#define CAS(ptr, oldv, newv)  __sync_bool_compare_and_swap((uint64_t*)(ptr), *(uint64_t*)(&oldv), *(uint64_t*)(&newv))
//#else
#define CAS(ptr, oldv, newv) CAS_64b((uint64_t*)(ptr), (uint32_t*)(&oldv), (uint32_t*)(&newv))
//#endif
struct A
{
    int a;
    int b;
};

void test_CAS()
{
    struct A sa = {1, 2};    
    struct A sb = {3, 4};    
    struct A sc = sa;
    if(CAS(&sc, sa, sb))
        printf("success, %d %d\n", sb.a, sb.b) ;
    else
        printf("fail, %d %d\n", sb.a, sb.b); 
}

void f_unlikely()
{
    printf("go unlikely\n"); 
}


void f_likely()
{
    printf("go likely\n"); 
}

void test_aligned(char* p)
{
    char* q = (char*)((((size_t)p + 3)>>2)<<2);
    *((int*)(q+1)) = 3;
}

void test_likely(int x)
{
    if(unlikely(x))
        f_unlikely();
    else
        f_likely();
}

void test_return_addr()
{
    void* p = __builtin_return_address(0);
    printf("address \t %p\n", p);
}

void test_frame_addr()
{
    void* p = __builtin_frame_address(0);
    printf("address \t %p\n", p);
}

int main()
{
    //typeof
    //statement expression
    int c = my_min(1, 2);
    printf("%d\n", c);

    //packed
    printf("sizeof(Str) = %u\n", (uint32_t)sizeof(Str));

    //##
    ERR_PRINTF("%d test", 1);
    ERR_PRINTF("test2");

    ERR_PRINTF2("%d test", 1);
    //printf("%s:%d ""test2""\n", __FUNCTION__, 80, ); // the , still exists
    ERR_PRINTF2("test2");

    //__builtin_expect
    test_likely(1);

    //__builtin_return_address
    test_return_addr();

    //__builtin_frame_address
    test_frame_addr();

    //test aligned
    char pp[11] = {0};
    test_aligned(pp);

    //test CAS
    test_CAS();

    while(1)
        sleep(10);
    return 0;
}

  

执行结果:

[ ~/code/test_sighup]$ ./test_gcc_ex 
1
sizeof(Str) = 7
main:120 1 test
main:121 test2
main:123 1 test
main:125 test2
go unlikely
address          0x804882b
address          0xffb33aa8
success, 3 4

 

objdump -DC ./test_gcc_ex

00000000004006a0 <test_likely(int)>:
  4006a0:       85 ff                   test   %edi,%edi
  4006a2:       75 05                   jne    4006a9 <test_likely(int)+0x9>
  4006a4:       e9 d7 ff ff ff          jmpq   400680 <f_likely()>
  4006a9:       e9 e2 ff ff ff          jmpq   400690 <f_unlikely()>
  4006ae:       66 90                   xchg   %ax,%ax

 

参考代码:

http://blog.csdn.net/cugxueyu/article/details/1955372

posted on 2017-03-11 19:01  Torstan  阅读(469)  评论(0编辑  收藏  举报

导航