天天看點

byteorder.h學習

版權聲明:您好,轉載請留下本人部落格的位址,謝謝 https://blog.csdn.net/hongbochen1223/article/details/45117691

在typeorder.h頭檔案中,主要定義了下面幾個函數,__u32 ___arch__swab32(__u32 val),___arch__swab64(__u64 val);這兩個函數的含義基本上是将32位寄存器中的位元組次序變反,将64位寄存器中的位元組次序變反。

舉個列子,有一個以16進制表示的32位變量,a=0x12345678;其中由于其是十六進制的,是以12占一個位元組,34占一個位元組,56占一個位元組,78占一個位元組,則執行上述___arch__swab32(__u32 val)函數之後,其位元組次序變反,就變成了a=0x78563412了。

下面是tyepeorder.h的源代碼,其中的解釋以及學習部分都在注釋當中,中間在處理64位的時候,有一段代碼我看到就會感到很高興,在注釋中會有展現的。

#ifndef _I386_BYTEORDER_H
#define _I386_BYTEORDER_H

#include <asm/types.h>
#include <linux/compiler.h>

#ifdef __GNUC__

/* For avoiding bswap on i386 */
//未實作
#ifdef __KERNEL__
#endif

//該内聯函數的作用是将x的位元組次序反轉
static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
{
//bswap指令 是将32位寄存器中的位元組的次序變反
#ifdef CONFIG_X86_BSWAP  //如果定義了bswap指令,則直接執行該指令
    __asm__("bswap %0" : "=r" (x) : "0" (x));

//xchgb:交換字或者是位元組,至少有一個操作書是寄存器,段寄存器不能作為操作數
#else
    /*
     * 思想就是先交換低位元組,将低位元組循環左移16位,高位元組被換到了低位元組位置,再交換位元組
     */
    __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes,*/
        "rorl $16,%0\n\t"  /* swap words       */
        "xchgb %b0,%h0"     /* swap higher bytes    */
        :"=q" (x)
        : "0" (x));
#endif
    return x;
}


//該内聯函數的作用是将64位位元組的次序變反
/**
 * 他的思想是:
 * 首先,将64位的先變成兩個32位的儲存到一個結構中,
 * 同時與一個64位的變量儲存到一個共同體中,在
 * 這裡,真心能夠感受到核心代碼的能省記憶體盡量省的優雅了。
 * 雖然說這是一種不太美觀的強制類型轉換,直接将類型省了,
 * 但是這樣的處理還是非常棒的。
 *
 * 如果定義了bswap彙編指令,則現将其中的兩個32位的變量的位元組交換, 
 * 再将兩個32位的位元組交換。
 * 如果沒有定義bswap指令,則先對其中的兩個32位的變量執行上面的
 * ___arch__swab32函數,最後再将這兩函數個變量交換
 *
 */
static __inline__ __attribute_const__ __u64 ___arch__swab64(__u64 val)
{ 
    union { 
        struct { __u32 a,b; } s;
        __u64 u;
    } v;

    v.u = val;
#ifdef CONFIG_X86_BSWAP
    asm("bswapl %0 ; bswapl %1 ; xchgl %0,%1" 
        : "=r" (v.s.a), "=r" (v.s.b) 
        : "0" (v.s.a), "1" (v.s.b)); 
#else
   v.s.a = ___arch__swab32(v.s.a); 
    v.s.b = ___arch__swab32(v.s.b); 
    asm("xchgl %0,%1" : "=r" (v.s.a), "=r" (v.s.b) : "0" (v.s.a), "1" (v.s.b));
#endif
    return v.u; 
} 

/* Do not define swab16.  Gcc is smart enough to recognize "C" version and
   convert it into rotation or exhange.  */
/* 不用定義16位的位元組變反函數,因為gcc是非常聰明的,他能夠識别“C”版本,并且 
   将其轉化成旋轉或者是交換 */

#define __arch__swab64(x) ___arch__swab64(x)
#define __arch__swab32(x) ___arch__swab32(x)

#define __BYTEORDER_HAS_U64__

#endif /* __GNUC__ */

#include <linux/byteorder/little_endian.h>

#endif /* _I386_BYTEORDER_H */           

學了之前的GCC内嵌彙編之後,看其中的彙編的時候就不會那麼吃力了。

繼續閱讀