UTF8转换UTF16(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/p/2307150.html