UTF-8转换UTF-16(Unicode) 汇编实现

 

  1 DWORD UTF8ToUnicode(LPVOID utf8Bytes,DWORD bytesLength,LPVOID *unicodeBytes)
  2 {
  3     DWORD charsCount= 0 ;
  4      DWORD result ;
  5      LPDWORD pResult=&result ;
  6      LPVOID tmpBuffer=NULL ;
  7      LPBYTE tmpData=(LPBYTE)utf8Bytes ;
  8      if(IsUTF8Data(tmpData))
  9     {
 10         utf8Bytes=tmpData+ 3 ;
 11          bytesLength-= 3 ;
 12      }
 13     *unicodeBytes=malloc(bytesLength* 2) ; //分配最大可能需要的内存
 14      //EAX:需要计算的数据
 15     //EBX:操作状态
 16     //ECX:最大源地址
 17     //EDX:计算结果
 18     //ESI:源
 19     //EDI:目标
 20     __asm
 21     {
 22         // push eax ;                 //对使用到的寄存器进行保存
 23          // push ebx ;                 //对使用到的寄存器进行保存
 24          // push ecx ;
 25          // push edx ;
 26          // push esi ;
 27          // push edi ;
 28           pushad ;
 29           MOV eax, 0 ;                 
 30           mov esi,utf8Bytes ;             //设置源地址
 31           mov edi,DWORD PTR[unicodeBytes] ;             //设置目标地址
 32           mov edi,DWORD PTR[EDI] ;
 33           mov ecx,bytesLength ;     
 34           add ecx,esi ;             //计算源数据最高地址
 35           MOV EBX,pResult
 36              XOR EAX,EAX ;
 37           XOR EDX,EDX ;
 38  LoopStart: ;
 39           mov EAX,DWORD PTR[ESI] ; //读取数据
 40 
 41          test al,0x80 ;
 42           jz L1 ;
 43           test al,0x40 ;
 44           JZ LoopEnd ;             //错误数据
 45           TEST AL,0x20 ;
 46           JZ    L2 ;
 47           JNZ L3 ;
 48 
 49          NOT EBX ;      //遇到无效字符(不支持四字节字符)
 50           JMP    LoopEnd ;
 51  L3: ;
 52           AND EAX,0x003F3F0F ;
 53           ADD DL,AL ;
 54           SHL EDX, 6 ;
 55           SHR EAX, 8 ;
 56           ADD DL,AL ;
 57           SHL EDX, 6 ;
 58          // SHR EAX, 8 ;
 59           ADD DL,AH ;
 60           ADD ESI, 3 ;
 61           JMP END ;
 62  L2: ;
 63           AND EAX,0x00003F1F ;
 64           ADD DL,AL ;
 65           SHL EDX, 6 ;
 66          // SHR EAX, 8 ;
 67           ADD DL,AH ;
 68           ADD ESI, 2 ;
 69           JMP END ;
 70  L1: ;
 71           MOV DL,AL ;
 72           ADD ESI, 1 ;
 73          // SHL EDX, 8 ;
 74  END: ;
 75           MOV WORD PTR [EDI],DX ;
 76           XOR EDX,EDX ;
 77           ADD EDI, 2 ;
 78 
 79          CMP ESI,ECX ;
 80           JNGE LoopStart ; //如果ESI小于ECX 继续循环
 81 
 82          MOV WORD PTR [EDI], 0 ;
 83           MOV DWORD PTR[EBX],EDI ;
 84  LoopEnd: ;
 85          //错误的数据
 86          popad
 87             // pop edi ;     //恢复使用到的寄存器
 88              // pop esi ;
 89              // pop edx ;
 90              // pop ecx ;
 91              // pop ebx ;
 92              // pop eax ;
 93      }
 94     if(result!=- 1)
 95     {
 96         charsCount=result-(DWORD)*unicodeBytes ;
 97          tmpBuffer=malloc(charsCount+ 4) ;
 98          memset(tmpBuffer, 0,charsCount+ 4) ;
 99          memcpy(tmpBuffer,*unicodeBytes,charsCount) ;
100          free(*unicodeBytes) ;
101          *unicodeBytes=tmpBuffer ;
102      }
103     return charsCount ;
104  }

UTF-8编码转换Utf-16

以上代码不转换4字节Utf-8编码字符,因为4字节Utf-8编码字符无法在UTF-16保存,最大0X1FFFF而Utf-16最大0xFFFF;utf-32可以保存

Utf-16编码和Unicode是一一对应的,Unicode程序中使用的也就是utf-16;

所以很多时候需要进行转换,utf-8保存英文字符占用空间小于utf-16,但是对于中文大于utf-16占用的空间

 

首先一次性取4个字节(对于32位机器取一个字节的消耗和4个字节一样),然后判断第一个字节(因为使用了寄存器,那么第一个字节就在最低位,低位低字节,高位高字节),

8 7 6 5 4

0 x x x x 单字节

1 1 0 x x 双字节

1 1 1 0 x 三字节

1 1 1 1 0四字节

1 0 x x x多字节的话处第一个字节外其余字节以这个开头

低位低字节,高位高字节。Unicode有两种表示一种高位在前,另外1种高位在后

11011111,10001111

那么结果是11001111,00001111//部分编码选择这种方式

那么结果是00001111,11001111//目前大多数是这样的

 

其实就是高低字节顺序的问题

 

更多信息请参见Utf-8编码的标准文档

 

上边代码对四字节处理基本忽略掉了,因为出现4字节Utf-16无法保存,所以处理也是白处理

转载于:https://www.cnblogs.com/a185771876/archive/2011/12/30/2307150.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值