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

来源:互联网 发布:手机淘宝如何刷新秒杀 编辑:程序博客网 时间:2024/06/06 18:57

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.**/


原创粉丝点击