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 }
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无法保存,所以处理也是白处理