感谢 DelphiGuy 于 2010-10-08 17:27:37 给出的提醒 function GetSizeCoder3To4(InputCount: Integer): Integer; inline; begin Result := (InputCount+2) div 3 * 4 end; procedure Base64Encode(InputCount: Integer; const Input: Pointer; Output: Pointer); assembler; asm //感谢 DelphiGuy 于 2010-10-08 17:27:37 给出的提醒,防止 "ECX and EDX = 0" 的情况发生异常 { TEST ECX, EDX // Input = Nil or Output = Nil ? jz @ret // if (Input = Nil) or (Output = Nil) then Exit; } TEST ECX, ECX jz @ret TEST EDX, EDX jz @ret push esi //saving Registers push edi push ebx push ebp lea ebp, @codetable //load B64-CodeTable-8bit mov esi, edx //ESI := Input mov edi, ecx //EDI := Output xor edx, edx mov ecx, 3 div ecx //EAX := InputCount div 3, EDX := InputCount mod 3 push edx xor ebx,ebx //Clear EBX dec esi test eax, eax //InputCount div 3 = 0 ? jz @next //if InputCount div 3 = 0 then Do Next with (InputCount mod 3) Bytes mov ecx, [esi+1] //ECX := 0x44332211 , Bits = 44444444 33333333 22222222 11111111 bswap ecx //ECX := 0x11223344 , Bits = 11111111 22222222 33333333 44444444 mov bl, ch //BL := 0x33 , Bits = 33333333, valid-Bits: 00333333 mov dh,[ebp + ebx] //DH := CodeTable[Bits: **333333] shr ecx, 14 //Prior 6-bits, Bits = 00000000 00000011 11111122 22222233 mov bl, cl //BL := Bits:22222233, valid-Bits: 00222233 mov dl,[ebp + ebx] //DL := CodeTable[Bits: **222233] mov [edi+2], dx //Output[2] := DX shr ecx, 6 //Prior 6-bits, Bits = 0000000 00000000 00001111 11112222 mov bl, cl //BL := Bits:11112222, valid-Bits: 00112222 mov dh, [ebp + ebx] //DH := CodeTable[Bits: **112222] shr ecx, 6 //First 6-bits, Bits = 00000000 00000000 00000000 00111111 mov bl, cl //BL := Bits:00111111 mov dl,[ebp + ebx] //DL := CodeTable[Bits: **111111] mov [edi], dx //Output[0] := DX add edi,4 //Inc(Output, 4) add esi,3 //Inc(Input, 3) Dec EAX //Dec EAX jz @next //if EAX = 0 then Goto @Next @loop: mov ecx, [esi] //ECX := 0x66554433 , Bits = 66666666 55555555 44444444 33333333 bswap ecx //ECX := 0x33445566 , Bits = 33333333 44444444 55555555 66666666 mov bl, cl //BL := 0x66 , Bits = 66666666, valid-Bits: 00666666 mov dh, [ebp + ebx] //DH := CodeTable[Bits: **666666] shr ecx, 6 //Prior 6-bits, Bits = 00000033 33333344 44444455 55555566 mov bl, cl //BL := Bits:55555566, valid-Bits: 00555566 mov dl,[ebp + ebx] //DL := CodeTable[Bits: **555566] mov [edi+2], dx //Output[2] := DX shr ecx, 6 //Prior 6-bits, Bits = 0000000 00003333 33334444 44445555 mov bl, cl //BL := Bits:44445555, valid-Bits: 00445555 mov dh,[ebp + ebx] //DH := CodeTable[Bits: **445555] shr ecx, 6 //First 6-bits, Bits = 00000000 00000000 00333333 33444444 mov bl, cl //BL := Bits:33444444, valid-Bits: 00444444 mov dl,[ebp + ebx] //DL := CodeTable[Bits: **444444] mov [edi], dx //Output[0] := DX add edi,4 //Inc(Output, 4) add esi,3 //Inc(Input, 3) Dec EAX jnz @loop //Dec ECX, if ECX <> 0 then Goto @Loop @next: pop edx dec edx // EDX := (InputCount mod 3) - 1 jz @OneByte // if EDX = 0 then GOTO One-Byte jns @TwoBytes // if EDX <> -1 then GOTO Two-Bytes pop ebp pop ebx pop edi pop esi ret //Last two-Bytes @TwoBytes: mov ax, [esi + 1] //Bits: 22222222 11111111 xchg al, ah //Bits: 11111111 22222222 lea eax, [eax * 4] //shl ecx, 2 ,Bits: 00000000 00000011 11111122 22222200 mov bl, al //Bits: 22222200, valid-Bits: 00222200 mov dh, [ebp + ebx] //DH := CodeTable[Bits: **222200] shr eax, 6 //Bits: 00000000 00000000 00001111 11112222 mov bl, al //Bits: 11112222, valid-Bits: 00112222 mov dl, [ebp + ebx] //DL := CodeTable[Bits: **112222] mov [edi + 1], dx shr eax, 6 //Bits: 00000000 00000000 00000000 00111111 mov dl, [ebp + eax] //DL := CodeTable[Bits: 00111111] mov [edi], dl mov Byte ptr [edi + 3], 61 //'=' pop ebp pop ebx pop edi pop esi ret //Last one-Byte @OneByte: mov al, [esi + 1] // Bits: 11111111 lea ebx, [eax * 8] // EBX := EAX SHL 3, Bits: 00000000 00000000 00000111 11111000 and ebx, $18 // Bits: 00000000 00000000 00000000 00011000 mov dh, [ebp + ebx * 2] // Bits: 00000000 00000000 00000000 00110000 // DH := CodeTable[Bits: **110000] shr eax, 2 // Bits: 00000000 00000000 00000000 00111111 mov dl, [ebp + eax] // DL := CodeTable[Bits: **111111] mov [edi], dx mov Byte ptr [edi + 2], 61 //'=' mov Byte ptr [edi + 3], 61 //'=' pop ebp pop ebx pop edi pop esi @ret: ret @CodeTable: //Bits: 00****** db 65, 66, 67, 68, 69, 70, 71, 72 db 73, 74, 75, 76, 77, 78, 79, 80 db 81, 82, 83, 84, 85, 86, 87, 88 db 89, 90, 97, 98, 99,100,101,102 db 103,104,105,106,107,108,109,110 db 111,112,113,114,115,116,117,118 db 119,120,121,122, 48, 49, 50, 51 db 52, 53, 54, 55, 56, 57, 43, 47 //Bits: 01****** db 65, 66, 67, 68, 69, 70, 71, 72 db 73, 74, 75, 76, 77, 78, 79, 80 db 81, 82, 83, 84, 85, 86, 87, 88 db 89, 90, 97, 98, 99,100,101,102 db 103,104,105,106,107,108,109,110 db 111,112,113,114,115,116,117,118 db 119,120,121,122, 48, 49, 50, 51 db 52, 53, 54, 55, 56, 57, 43, 47 //Bits: 10****** db 65, 66, 67, 68, 69, 70, 71, 72 db 73, 74, 75, 76, 77, 78, 79, 80 db 81, 82, 83, 84, 85, 86, 87, 88 db 89, 90, 97, 98, 99,100,101,102 db 103,104,105,106,107,108,109,110 db 111,112,113,114,115,116,117,118 db 119,120,121,122, 48, 49, 50, 51 db 52, 53, 54, 55, 56, 57, 43, 47 //Bits: 11****** db 65, 66, 67, 68, 69, 70, 71, 72 db 73, 74, 75, 76, 77, 78, 79, 80 db 81, 82, 83, 84, 85, 86, 86, 88 db 89, 90, 97, 98, 99,100,101,102 db 103,104,105,106,107,108,109,110 db 111,112,113,114,115,116,117,118 db 119,120,121,122, 48, 49, 50, 51 db 52, 53, 54, 55, 56, 57, 43, 47 end; //测试代码 procedure TForm1.Button1Click(Sender: TObject); var StrSrc, StrDst: AnsiString; begin StrSrc := '测试一下Base64编码,看看结果是什么...'; SetLength(StrDst, GetSizeCoder3To4(Length(StrSrc))); Base64Encode(Length(StrSrc), Pointer(StrSrc), Pointer(StrDst)); MessageBox(GetActiveWindow,PAnsiChar(StrDst),'Base64编码输出',MB_OK or MB_ICONINFORMATION); end;