主机字节序转换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.**/
- 主机字节序转换htonl, 从Windows NT 10条指令到5条指令的优化
- 网络字节序与主机字节序的转换(htonl,htons,inet_addr,ntohl,ntohs,inet_ntoa)
- 主机字节序与网络字节序的转换函数:htonl、ntohl、htons、ntohs
- 主机字节序与网络字节序的转换:ntohl()与htonl()
- 主机字节序与网络字节序的转换函数:htonl、ntohl、htons、ntohs
- 主机字节序与网络字节序的转换函数:htonl、ntohl、htons、ntohs
- 基础的50条指令
- 网络字节顺序和主机字节顺序的转换(htons ntohs htonl ntohl)
- 网络字节顺序和主机字节顺序的转换(htons ntohs htonl ntohl)
- 网络字节顺序和主机字节顺序的转换(htons ntohs htonl ntohl)
- 网络字节顺序和主机字节顺序的转换(htons ntohs htonl ntohl)
- 网络字节顺序和主机字节顺序的转换(htons ntohs htonl ntohl)
- 网络字节顺序和主机字节顺序的转换(htons ntohs htonl ntohl)
- cpu第一条指令
- 几条汇编指令
- ARM指令中4条容易混淆的指令区别
- 几条预处理指令的用法
- ARM几条汇编指令的比较
- C++博客十八罗汉造像
- [体检]悲从中来,伤不起
- sql写文件
- Hibernate缓存机制
- 临界区和锁
- 主机字节序转换htonl, 从Windows NT 10条指令到5条指令的优化
- 从宗教信仰看东西方文化对人的影响
- oracle select详解
- Oracle 常用命令
- 外部排序
- 网址转换
- 不要和一个外行去说你的专业
- 文本相似度算法
- 改进联级adaboost