主机字节序转换htonl, 从Windows NT 10条指令到5条指令的优化

1. 首先要说明的是: htonl, ntohl是同一份代码, htons, ntohs是同一份代码

2. 以下值列出Windows NT ntohl/htonl的实现代码:

    mov         edi,edi 
    push        ebp 
    mov         ebp,esp 
    mov         edx,dword ptr [ebp+8] 
    mov         eax,edx ; 保存参数 
    mov         ecx,edx  ; 保存参数
    shl         ecx,10h  ;        开始转换的第1条指令
    and         eax,0FF00h  ; 开始转换的第2条指令
    or          eax,ecx          ; 开始转换的第3条指令 
    mov         ecx,edx       ; 开始转换的第4条指令
    and         ecx,0FF0000h  ; 开始转换的第5条指令
    shr         edx,10h  ; 开始转换的第6条指令
    or          ecx,edx  ; 开始转换的第7条指令
    shl         eax,8  ; 开始转换的第8条指令
    shr         ecx,8  ; 开始转换的第9条指令
    or          eax,ecx  ; 开始转换的第10条指令
    pop         ebp  ;  恢复
    ret  4; 返回调用点__stdcall调用约定

3. 以下便是ntohl/htonl 5条指令的实现代码:

static
__declspec(naked) uint32_t __bswap32(uint32_t)
{
    __asm
    {
        mov         eax, dword ptr[esp + 4]; // 保存参数
        mov         ecx, eax; // 保存参数

        ror         ecx, 8;          ecx = 0x44112233
        and         ecx, 0xFF00FF00; ecx = 0x44002200

        rol         eax, 8;          eax = 0x22334411
        and         eax, 0x00FF00FF; eax = 0x00330011

        or          eax, ecx;        eax = 0x44332211

        ret         ; // 返回调用 调用约定为__cdecl
    }

}

4. 下面给出ntohll/htonll的实现:

#ifndef _WIN32
static
__declspec(naked) uint64_t __bswap64(uint64_t)
{
    __asm 
    {
        mov         edx, dword ptr[esp + 4];
        mov         eax, dword ptr[esp + 8];

        ; --- swap low 4 bytes
        mov         ecx, eax;        ecx = eax = 0x11223344
        ror         ecx, 8;          ecx = 0x44112233
        and         ecx, 0xFF00FF00; ecx = 0x44002200

        rol         eax, 8;          eax = 0x22334411
        and         eax, 0x00FF00FF; eax = 0x00330011

        or          eax, ecx;        eax = 0x44332211

        ; --- swap high 4 bytes
        mov         ecx, edx;        ecx = edx = 0x55667788
        ror         ecx, 8;          ecx = 0x88556677
        and         ecx, 0xFF00FF00; ecx = 0x88006600

        rol         edx, 8;          edx = 0x66778855
        and         edx, 0x00FF00FF; edx = 0x00770055

        or          edx, ecx;        edx = 0x88776655

        ret         ;
    }
}
#endif
</pre><div style="top: 758px;">5. windows & linux完整代码:(xxbswap.h)</div><div style="top: 758px;"><pre class="cpp" name="code" snippet_file_name="blog_20140123_35_7163998" code_snippet_id="167708">#ifndef _XXBSWAP_H_
#define _XXBSWAP_H_

#ifdef _WIN32
/*
*
__declspec(naked) uint16_t __cdecl __bswap16(uint16_t)
{
    __asm
    {
        // 保存寄存器(若没有寄存器需要存,以下3条指令代码可省略)
        push        ebp;  
        mov         ebp, esp; 
        push        esi

        mov         eax, dword ptr[ebp + 8]; // 这里如果没有寄存保存,可直接使用esp, 注: 16汇编不支持esp作为基地址寄存器
        ror         ax, 8;

        // 恢复寄存器(若没有寄存器需要存,以下3条指令代码可省略)
        pop         esi;
        mov         esp ebp
        pop         ebp;

        ret         ;
    }
}
* 
*/
inline
__declspec(naked) uint16_t __cdecl __bswap16(uint16_t)
{
    __asm
    {
        mov         eax, dword ptr[esp + 4];
        mov         ecx, eax;
        shl         eax, 8; eax = 0x00112200;
        sar         ecx, 8; ecx = 0x00000011;
        or          eax, ecx;         
        ret         ;
    }
}

inline
__declspec(naked) uint32_t __cdecl __bswap32(uint32_t)
{
    __asm
    {
        mov         eax, dword ptr[esp + 4];
        mov         ecx, eax;

        ror         ecx, 8;          ecx = 0x44112233
        and         ecx, 0xFF00FF00; ecx = 0x44002200

        rol         eax, 8;          eax = 0x22334411
        and         eax, 0x00FF00FF; eax = 0x00330011

        or          eax, ecx;        eax = 0x44332211

        ret         ;
    }
}

/* 当release模式是,编译器优化代码可能会使用除了作为返回值寄存器
   (edx:eax) 之外的其他寄存器,因此在写naked内联汇编函数时,必须
   保存相关寄存器,否则会产生意想不到的后果。
   而由windows htons和htonl可知,ecx也不需要保存, 以下汇编代码
   只适用于windows 平台
*/
inline
__declspec(naked) uint64_t __cdecl __bswap64(uint64_t)
{
    __asm 
    {
        mov         edx, dword ptr[esp + 4];
        mov         eax, dword ptr[esp + 8];

        ; --- swap low 4 bytes
        mov         ecx, eax;        ecx = eax = 0x11223344
        ror         ecx, 8;          ecx = 0x44112233
        and         ecx, 0xFF00FF00; ecx = 0x44002200

        rol         eax, 8;          eax = 0x22334411
        and         eax, 0x00FF00FF; eax = 0x00330011

        or          eax, ecx;        eax = 0x44332211

        ; --- swap high 4 bytes
        mov         ecx, edx;        ecx = edx = 0x55667788
        ror         ecx, 8;          ecx = 0x88556677
        and         ecx, 0xFF00FF00; ecx = 0x88006600

        rol         edx, 8;          edx = 0x66778855
        and         edx, 0x00FF00FF; edx = 0x00770055

        or          edx, ecx;        edx = 0x88776655

        ret         ;
    }
}

#else

#define __BSWAP16(from,to)                                           \
{                                                                    \
  __asm__ __volatile__(                                              \
        "mov %1, %%ax\n\t"                                           \
        "ror $8, %%ax\n\t"                                           \
        "mov %%ax, %0\n\t"                                           \
        : "=r"(to)                                                   \
        : "r"(from)                                                  \
        : "cc", "memory", "ax"                                       \
         );                                                          \
}


#define __BSWAP32(from,to)                                           \
{                                                                    \
  __asm__ __volatile__(                                              \
        "movl %1, %%eax\n\t"                                         \
        "movl %%eax, %%ecx\n\t"                                      \
        "rorl $8, %%ecx\n\t"                                         \
        "andl $0xff00ff00, %%ecx\n\t"                                \
        "roll $8, %%eax\n\t"                                         \
        "andl $0x00ff00ff, %%eax\n\t"                                \
        "orl  %%ecx, %%eax\n\t"                                      \
        "movl %%eax, %0\n\t"                                         \
        : "=r"(to)                                                   \
        : "r"((uint32_t)from)                                        \
        : "cc", "memory"                               \
         );                                                          \
}

#define __BSWAP64(from,to)                                           \
{                                                                    \
  uint32_t& l_ref = *( (uint32_t*)&to );                             \
  uint32_t& h_ref = *( (uint32_t*)&to + 1 );                         \
  __asm__ __volatile__(                                              \
        "movl %3, %%eax\n\t"                                         \
        "movl %%eax, %%ecx\n\t"                                      \
        "rorl $8, %%ecx\n\t"                                         \
        "andl $0xff00ff00, %%ecx\n\t"                                \
        "roll $8, %%eax\n\t"                                         \
        "andl $0x00ff00ff, %%eax\n\t"                                \
        "orl  %%ecx, %%eax\n\t"                                      \
        "movl %%eax, %0\n\t"                                         \
        "movl %2, %%eax\n\t"                                         \
        "movl %%eax, %%ecx\n\t"                                      \
        "rorl $8, %%ecx\n\t"                                         \
        "andl $0xff00ff00, %%ecx\n\t"                                \
        "roll $8, %%eax\n\t"                                         \
        "andl $0x00ff00ff, %%eax\n\t"                                \
        "orl  %%ecx, %%eax\n\t"                                      \
        "movl %%eax, %1\n\t"                                         \
        : "=r"(l_ref), "=r"(h_ref)                                   \
        : "r"(*( (uint32_t*)&from )), "r"(*( (uint32_t*)&from + 1 )) \
        : "cc", "memory", "eax", "ecx"                               \
         );                                                          \
}

inline uint16_t  __bswap16(uint16_t fromval)
{
    uint16_t toval = 0;
    __BSWAP16(fromval, toval);
    return toval;
}

inline uint32_t  __bswap32(uint32_t fromval)
{
    uint32_t toval = 0;
    __BSWAP32(fromval, toval);
    return toval;
}

inline uint64_t  __bswap64(uint64_t fromval)
{
    uint64_t toval = 0;
    __BSWAP64(fromval, toval);
    return toval;
}

#endif

#endif
/*
* Copyright (c) 2012-2014 by X.D. Guo  ALL RIGHTS RESERVED.
* Consult your license regarding permissions and restrictions.
**/



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值