16,748
社区成员
发帖
与我相关
我的任务
分享
unit uEncoder3To4_12BitsCoderTable;
{
2010-09-28 创建 by unsigned(僵哥)
}
interface
procedure Base64EncodeEx(InputCount: Integer; const Input: Pointer; Output: Pointer); assembler;
function GetSizeCoder3To4(InputCount: Integer): Integer; inline;
implementation
var
B64Table:array[0..65535] of Word;
function GetSizeCoder3To4(InputCount: Integer): Integer; inline;
begin
Result := (InputCount+2) div 3 * 4
end;
procedure Base64EncodeEx(InputCount: Integer; const Input: Pointer; Output: Pointer); assembler;
asm
TEST ECX, EDX // Input = Nil or Output = Nil ?
jz @end // if (Input = Nil) or (Output = Nil) then Exit;
Test EAX, EAX // InputCount = 0?
jz @end // if InputCount = 0 then Exit;
push esi //saving Registers
push edi
push ebx
push ebp
lea ebp,[B64Table] //load B64-CodeTable-16Bits
mov esi, edx //ESI := Input
mov edi, ecx //EDI := Output
mov edx, 0
mov ecx, 3
div ecx //EAX := InputCount div 3, EDX := InputCount mod 3
mov ecx, eax //ECX := (InputCount div 3), (Loop Count)
push edx //Saving (InputCount mod 3)
xor ebx,ebx //Clear EBX
dec esi
test ecx, ecx //InputCount div 3 = 0 ?
jz @next //if InputCount div 3 = 0 then Do Next with (InputCount mod 3) Bytes
mov eax, [esi+1] //EAX := 0x44332211 , Bits = 44444444 33333333 22222222 11111111
bswap eax //EAX := 0x11223344 , Bits = 11111111 22222222 33333333 44444444
shr eax, 8 //EAX := 0x00112233, valid-Bits: 00000000 11111111 22222222 33333333
mov bx, ax //BX := 0x2233, , Bits = 22222222 33333333, valid-Bits: 2222 33333333
mov dx,[ebp + ebx * 2] //DX := CodeTable[Bits:00000000 00000000 00002222 33333333]
mov [edi+2], dx //PWord(@Output[2])^ := DX
shr eax, 12 //First 12-bits, Bits = 00000000 0000000 00001111 11112222
mov bx, ax //BX := Bits:00001111 11112222
mov dx,[ebp + ebx * 2] //DX := CodeTable[Bits:00000000 00000000 00001111 11112222]
mov [edi], dx //PWord(@Output[0])^ := DX
add edi,4 //Inc(Output, 4)
add esi,3 //Inc(Input, 3)
Dec ECX
jz @next //Dec ECX, if ECX = 0 then Goto @next
@loop:
mov eax, [esi] //EAX := 0x66554433 , Bits = 66666666 55555555 44444444 33333333
bswap eax //EAX := 0x33445566 , Bits = 33333333 44444444 55555555 66666666
//valid-Bits: 00000000 44444444 55555555 66666666
mov bx, ax //BX := 0x5566', , Bits = 55555555 66666666, valid-Bits: 5555 66666666
mov dx,[ebp + ebx * 2] //DX := CodeTable[Bits:00000000 00000000 00005555 66666666]
mov [edi+2], dx //PWord(@Output[2])^ := DX
shr eax, 12 //First 12-bits, Bits = 00000000 0000000 00004444 444455555
mov bx, ax //BX := Bits:00004444 44445555
mov dx,[ebp + ebx * 2] //DX := CodeTable[Bits:00000000 00000000 00004444 44445555]
mov [edi], dx //PWord(@Output[0])^ := DX
add edi,4 //Inc(Output, 4)
add esi,3 //Inc(Input, 3)
Dec ECX
jnz @loop //Dec ECX, if ECX <> 0 then Goto @Loop
@next:
inc esi
pop edx //Restore (InputCount mod 3)
test edx, edx // (InputCount mod 3) = 0?
jz @ret //if (InputCount mod 3) = 0 then Exit
//Last one or two Byte(s)
lea ebx, [edx - 4]
neg ebx
sub esi, ebx
mov ax, [esi + 2] //Bits: 11111111 00000000 ( 22222222 11111111 )
xchg ah, al //Bits: 00000000 11111111 ( 11111111 22222222 )
lea ecx, [edx*8]
mov esi, 1
shl esi, cl
dec esi
and eax,esi //Set valid-Bits: 00000000 00000000 00000000 11111111 ( 00000000 00000000 11111111 22222222 )
lea ecx,[edx * 4]
shl eax,cl //last Byte, valid-Bits: 00000000 00000000 00001111 11110000 ( 00000000 00000011 11111122 22222200 )
//last-Byte-valid-Bits: 00110000 ( 00222200 )
mov esi,edx
xor ebx,ebx
@loop2:
//1. valid-Bits: 00001111 11110000 ( 00001122 22222200 )
//2. valid-Bits: N/A ( 00000000 00111111 )
mov bx, ax
mov cx, [ebp + ebx * 2]
mov [edi+edx*2-2], cx
shr eax, 12
dec edx
jnz @loop2
add edi,esi
sub esi,3
neg esi
@loop3:
//Fill-Char(s)
mov Byte ptr [edi+1], 61
inc edi
dec esi
jnz @loop3
@ret:
pop ebp
pop ebx
pop edi
pop esi
@end:
ret
end;
var
i: Integer;
const
Base64_Chars: array[0..63] of AnsiChar = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
//0123456789012345678901234567890123456789012345678901234567890123
//0 1 2 3 4 5 6
initialization
for I := 0 to 65536 - 1 do begin
B64Table[I] := (Word(Byte(Base64_Chars[I and $3f])) shl 8 ) or (Word(Byte(Base64_Chars[(I shr 6) and $3f])));
if I = $e2ca then begin
B64Table[I] := (Word(Byte(Base64_Chars[I and $3f])) shl 8 ) or (Word(Byte(Base64_Chars[(I shr 6) and $3f])));
end;
end;
end.
unit uDecoder4To3_14BitsCoderTable;
{
2010-10-01 Create by Unsigned(僵哥)
2010-10-08 增加 Base64Decode 用于编码数据中存在非BASE64有效字符时的解码 by Unsigned(僵哥)
}
interface
function Base64DecodeEx( const Input: Pointer
; const Output: Pointer
; InputCount: Integer
): Integer; assembler;
function Base64Decode( const Input: Pointer
; const Output: Pointer
; InputCount: Integer
): Integer; assembler;
function GetSizeDecoder4To3(InputCount: Integer): Integer; inline;
implementation
//根据DelphiGuy的提醒,将码表增大到足够安全
{
const B_0 = -11051;
const B_1 = 9253;
const B_2 = 29557;
const B_3 = 60912;
var
CoderTable: array[0..60911 + 256] of Byte;
}
const B_0 = 0;
const B_1 = 65536;
const B_2 = 131072;
const B_3 = 196608;
var
CoderTable: array[0..196607 + 256] of Byte;
function GetSizeDecoder4To3(InputCount: Integer): Integer; inline;
begin
Result := (InputCount) div 4 * 3;
end;
function Base64DecodeEx( const Input: Pointer
; const Output: Pointer
; InputCount: Integer
): Integer; assembler;
asm
//根据DelphiGuy的提醒,防止 EAX = Not EDX的情况
{
TEST EAX, EDX
JZ @RET
}
TEST EAX, EAX
JZ @RET
TEST EDX, EDX
JZ @RET
SHR ECX, 2
TEST ECX, ECX
JZ @RET
PUSH ESI
PUSH EDI
PUSH EBP
PUSH EBX
PUSH EDX
LEA EBP, [CoderTable]
MOV ESI, EAX
MOV EDI, EDX
XOR EDX, EDX
XOR EAX, EAX
@LOOP:
MOV AX, [ESI] //Bits: 00222211 00111111
MOV DX, [ESI + 2] //Bits: 00333333 00332222
MOV BL, [EBP + EAX + B_0] //CoderTable[Bits: 00222211 00111111]
MOV AL, DL //EAX := Bits: 0000000 0000000 00222211 00332222
MOV BH, [EBP + EAX + B_1] //CoderTable[Bits: 00222211 00332222]
MOV [EDI], BX
MOV BL, [EBP + EDX + B_2] //CoderTable[Bits: 00333333 00332222]
MOV [EDI + 2], BL
ADD ESI, 4
ADD EDI, 3
DEC ECX
JNZ @LOOP
POP EAX
NEG EAX
ADD EAX, EDI
CMP DH, $3D
JNZ @END
DEC EAX
CMP DL, $3D
JNZ @END
DEC EAX
@END:
POP EBX
POP EBP
POP EDI
POP ESI
@RET:
end;
function Base64Decode( const Input: Pointer
; const Output: Pointer
; InputCount: Integer
): Integer; assembler;
asm
//根据DelphiGuy的提醒,防止 EAX = Not EDX的情况
{
TEST EAX, EDX
JZ @RET
}
TEST EAX, EAX
JZ @RET
TEST EDX, EDX
JZ @RET
SHR ECX, 2
TEST ECX, ECX
JZ @RET
PUSH ESI
PUSH EDI
PUSH EBP
PUSH EBX
PUSH EDX
LEA EBP, [CoderTable]
MOV ESI, EAX
MOV EDI, EDX
XOR EDX, EDX
XOR EAX, EAX
XOR EBX, EBX
@@0:
MOV BL, [ESI + 0] //Bits: 00111111
CMP Byte ptr [EBP + EBX + B_3], 1
JE @AL
INC ESI
DEC ECX
JZ @ENDLOOP
JMP @@0
@AL:
MOV AL, BL
@@1:
MOV BL, [ESI + 1] //Bits: 00222211
CMP Byte ptr [EBP + EBX + B_3], 1
JE @AH
INC ESI
DEC ECX
JNZ @@1
JMP @ENDLOOP
@AH:
MOV AH, BL
@@2:
MOV BL, [ESI + 2] //Bits: 00332222
CMP Byte ptr [EBP + EBX + B_3], 1
JE @DL
INC ESI
DEC ECX
JNZ @@2
JMP @ENDLOOP
@DL:
MOV DL, BL
@@3:
MOV BL, [ESI + 3] //Bits: 00333333
CMP Byte ptr [EBP + EBX + B_3], 1
JE @DH
INC ESI
DEC ECX
JNZ @@3
JMP @ENDLOOP
@DH:
MOV DH, BL
MOV BL, [EBP + EAX + B_0] //CoderTable[Bits: 00222211 00111111]
MOV [EDI + 0], BL
MOV AL, DL //EAX := Bits: 0000000 0000000 00222211 00332222
MOV BL, [EBP + EAX + B_1] //CoderTable[Bits: 00222211 00332222]
MOV [EDI + 1], BL
MOV BL, [EBP + EDX + B_2] //CoderTable[Bits: 00333333 00332222]
MOV [EDI + 2], BL
ADD ESI, 4
ADD EDI, 3
SUB ECX, 4
JNZ @LOOP
@ENDLOOP:
POP EAX
NEG EAX
ADD EAX, EDI
CMP DH, $3D
JNZ @END
DEC EAX
CMP DL, $3D
JNZ @END
DEC EAX
@END:
POP EBX
POP EBP
POP EDI
POP ESI
@RET:
end;
{$REGION 'InitTable'}
procedure InitTable; inline;
var
I,J: Integer;
Index_I, Bits_I_0, Bits_I_1, Bits_I_2: Integer;
begin
FillChar(CoderTable, SizeOf(CoderTable), 0);
for I := 0 to 64 do begin
Bits_I_0 := (I shr 4) and $3;
Bits_I_1 := (I shl 4) and $F0;
Bits_I_2 := I;
case I of
0..25: begin
Index_I := (I + 65) shl 8;
CoderTable[B_3 + I + 65] := 1;
end;
26..51: begin
Index_I := (I - 26 + 97) shl 8;
CoderTable[B_3 + I - 26 + 97] := 1;
end;
52..61: begin
Index_I := (I - 52 + 48) shl 8;
CoderTable[B_3 + I - 52 + 48] := 1;
end;
62: begin
Index_I := 43 shl 8;
CoderTable[B_3 + 43] := 1;
end;
63: begin
Index_I := 47 shl 8;
CoderTable[B_3 + 47] := 1;
end
else begin
Index_I := 61 shl 8;
CoderTable[B_3 + 61] := 1;
Bits_I_0 := 0;
Bits_I_1 := 0;
Bits_I_2 := 0;
end;
end;
for J := 0 to 9 do begin
CoderTable[(Index_I or (J + 48)) + B_0] := Bits_I_0 or ((J + 52) shl 2);
CoderTable[(Index_I or (J + 65)) + B_0] := Bits_I_0 or ((J + 0) shl 2);
CoderTable[(Index_I or (J + 97)) + B_0] := Bits_I_0 or ((J + 26) shl 2 );
CoderTable[(Index_I or (J + 48)) + B_1] := Bits_I_1 or ((J + 52) shr 2);
CoderTable[(Index_I or (J + 65)) + B_1] := Bits_I_1 or ((J + 0) shr 2);
CoderTable[(Index_I or (J + 97)) + B_1] := Bits_I_1 or ((J + 26) shr 2);
CoderTable[(Index_I or (J + 48)) + B_2] := Bits_I_2 or (((J + 52) shl 6) and $C0);
CoderTable[(Index_I or (J + 65)) + B_2] := Bits_I_2 or (((J + 0) shl 6) and $C0);
CoderTable[(Index_I or (J + 97)) + B_2] := Bits_I_2 or (((J + 26) shl 6) and $C0);
end;
for J := 10 to 25 do begin
CoderTable[(Index_I or (J + 65)) + B_0] := Bits_I_0 or ((J + 0) shl 2);
CoderTable[(Index_I or (J + 97)) + B_0] := Bits_I_0 or ((J + 26) shl 2);
CoderTable[(Index_I or (J + 65)) + B_1] := Bits_I_1 or ((J + 0) shr 2);
CoderTable[(Index_I or (J + 97)) + B_1] := Bits_I_1 or ((J + 26) shr 2);
CoderTable[(Index_I or (J + 65)) + B_2] := Bits_I_2 or (((J + 0) shl 6) and $C0);
CoderTable[(Index_I or (J + 97)) + B_2] := Bits_I_2 or (((J + 26) shl 6) and $C0);
end;
CoderTable[(Index_I or 43) + B_0] := Bits_I_0 or 248;
CoderTable[(Index_I or 47) + B_0] := Bits_I_0 or 252;
CoderTable[(Index_I or 61) + B_0] := Bits_I_0 or 0;
CoderTable[(Index_I or 43) + B_1] := Bits_I_1 or 15;
CoderTable[(Index_I or 47) + B_1] := Bits_I_1 or 15;
CoderTable[(Index_I or 61) + B_1] := Bits_I_1 or 0;
CoderTable[(Index_I or 43) + B_2] := Bits_I_2 or 128;
CoderTable[(Index_I or 47) + B_2] := Bits_I_2 or 192;
CoderTable[(Index_I or 61) + B_2] := Bits_I_2 or 0;
end;
end;
{$ENDREGION}
initialization
InitTable;
end.
{ 返回一个整型数的某二进位值 }
function TestBit(Value, Index : integer) : Byte;
asm
BT EAX, Index //检测Index位是否为1,如为1则置PSW寄存器的CF位为1
SETB AL // CF -> AL
end;