汇编写的BASE64

汇编写的BASE64

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
unit Base64;
{
procedure TForm1.Button1Click(Sender: TObject);
var
  Source, Dest: TStream;
begin
  if OpenDialog1.Execute then
  begin
    Source := TFileStream.Create(OpenDialog1.FileName, fmOpenRead); // 打开源文件
    Dest := TFileStream.Create('Base64EncodeTest.txt', fmCreate); // Base64编码文件
    try
      Base64Encode(Source, Dest);
    finally
      Source.Free;
      Dest.Free;
    end;
 
    Source := TFileStream.Create('Base64EncodeTest.txt', fmOpenRead); // 打开编码文件
    Dest := TFileStream.Create('2.exe', fmCreate); // 还原源文件内容
    try
      Base64Decode(Source, Dest);
      Dest.Position := 0;
    finally
      Source.Free;
      Dest.Free;
    end;
  end;
end;
}
 
interface
 
uses
  SysUtils, Classes;
 
type
{$IFDEF UNICODE}
  Base64String = AnsiString;
{$ELSE}
 
  Base64String = string;
{$ENDIF}
 
// 按源长度SourceSize返回Base64编码所需缓冲区字节数
 
function Base64EncodeBufSize(SourceSize: Integer): Integer;
// 获取Sourec的Base64编码,Base64Buf必须有足够长度。返回实际编码字节数
 
function Base64Encode(const Source; SourceSize: Integer; var Base64Buf): Integer; overload;
// 将Source编码为Base64字符串返回
 
function Base64Encode(const Source; SourceSize: Integer): Base64String; overload;
// 将Source从StartPos开始的Size长度的内容源编码为Base64,写入流Dest。
// Size=0 表示一直编码到文件尾
 
procedure Base64Encode(Source, Dest: TStream; StartPos: Int64 = 0; Size: Int64 = 0); overload;
// 把字符串Str编码为Base64字符串返回
{$IFDEF UNICODE}
 
function StrToBase64(const Str: AnsiString): Base64String; overload;
 
function StrToBase64(const Str: string): Base64String; overload;
{$ELSE}
 
function StrToBase64(const Str: string): Base64String;
{$ENDIF}
 
// 按给定的编码源Source和长度SourceSize计算并返回解码缓冲区所需字节数
 
function Base64DecodeBufSize(const Base64Source; SourceSize: Integer): Integer;
// 将Base64编码源Base64Source解码,Buf必须有足够长度。返回实际解码字节数
 
function Base64Decode(const Base64Source; SourceSize: Integer; var Buf): Integer; overload;
// 将Source从StartPos开始的Size长度的Base64编码内容解码,写入流Dest。
// Size=0 表示一直解码到文件尾
 
procedure Base64Decode(Source, Dest: TStream; StartPos: Int64 = 0; Size: Int64 = 0); overload;
// 将Base64编码源Base64Source解码为字符串返回
 
function Base64Decode(const Base64Source; SourceSize: Integer): string; overload;
// 把Base64字符串Base64Str解码为字符串返回
 
function Base64ToStr(const Base64Str: Base64String): string;
 
implementation
 
const
  Base64_Chars: array[0..63] of AnsiChar = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  Base64_Bytes: array[0..79] of Byte = (62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51);
 
type
  Base64Proc = function(const Source; SourceSize: Integer; var Buf): Integer;
 
procedure Base64Stream(Source, Dest: TStream; Proc: Base64Proc; StartPos, Size: Int64; RBufSize, WBufSize: Integer);
var
  RBuf: array of Byte;
  WBuf: array of Byte;
  RSize, WSize: Integer;
begin
  if (StartPos < 0) or (StartPos >= Source.Size) then
    Exit;
  Source.Position := StartPos;
  if (Size <= 0) or (Size > Source.Size - Source.Position) then
    Size := Source.Size
  else
    Size := Size + Source.Position;
  SetLength(RBuf, RBufSize);
  SetLength(WBuf, WBufSize);
  while Size <> Source.Position do
  begin
    if RBufSize > Size - Source.Position then
      RBufSize := Size - Source.Position;
    RSize := Source.Read(RBuf[0], RBufSize);
    WSize := Proc(RBuf[0], RSize, WBuf[0]);
    Dest.Write(WBuf[0], WSize);
  end;
end;
 
function Base64EncodeBufSize(SourceSize: Integer): Integer;
begin
  Result := ((SourceSize + 2) div 3) shl 2;
end;
 
(****************************************************************************
* *
* BASE64 Encode hint: *
* *
* addr: (high) 4 byte 3 byte 2 byte 1 byte (low) *
* sourec ASCII(3 bytes): 33333333 22222222 11111111 *
* bswap: 11111111 22222222 33333333 00000000 *
* b4 = Base64_Chars[(source >> 8) & 63]: [00333333]->44444444 *
* b3 = Base64_Chars[(source >> 14) & 63]: [00222233]->33333333 *
* b2 = Base64_Chars[(source >> 20) & 63]: [00112222]->22222222 *
* b1 = Base64_Chars[source >> 26]: [00111111]->11111111 *
* b4 << 24 b3 << 16 b2 << 8 b1 *
* dest BASE64(4 bytes) 44444444 33333333 22222222 11111111 *
* *
****************************************************************************)
 
function Base64Encode(const Source; SourceSize: Integer; var Base64Buf): Integer;
asm
        push    ebp
        push    esi
        push    edi
        push    ebx
        mov     esi, eax // esi = Source
        mov     edi, ecx // edi = Buf
        mov     eax, edx
        cdq
        mov     ecx, 3
        DIV     ecx // edx = SourceSize % 3
        mov     ecx, eax // ecx = SourceSize / 3
        test    edx, edx
        jz      @@1
        inc     eax // eax = (SourceSize + 2) / 3
 
@@1:
        push    eax
        push    edx
        lea     ebp, Base64_Chars
        jecxz   @Last
        cld
 
@EncodeLoop: // while (ecx > 0){
        mov     edx, [esi] // edx = 00000000 33333333 22222222 11111111
        bswap   edx // edx = 11111111 22222222 33333333 00000000
        push    edx
        push    edx
        push    edx
        pop     ebx // ebx = edx
        SHR     edx, 20
        SHR     ebx, 26 // ebx = 00111111
        AND     edx, 63 // edx = 00112222
        mov     ah, [ebp + edx] // *(word*)edi = (Base64_Chars[edx] << 8) |
        mov     al, [ebp + ebx] // Base64_Chars[ebx]
        stosw // edi += 2
        pop     edx // edx = 11111111 22222222 33333333 00000000
        pop     ebx // ebx = edx
        SHR     edx, 8
        SHR     ebx, 14
        AND     edx, 63 // edx = 00333333
        AND     ebx, 63 // ebx = 00222233
        mov     ah, [ebp + edx] // *(word*)edi = (Base64_Chars[edx] << 8) |
        mov     al, [ebp + ebx] // Base64_Chars[ebx]
        stosw // edi += 2
        add     esi, 3 // esi += 3
        loop    @EncodeLoop // }
 
@Last:
        pop     ecx // ecx = SourceSize % 3
        jecxz   @END // if (ecx == 0) return
        mov     eax, 3d3d0000h // preset 2 bytes '='
        mov     [edi], eax
        test    ecx, 2
        jnz     @@3
        mov     al, [esi] // if (ecx == 1)
        SHL     eax, 4 // eax = *esi << 4
        jmp     @@4
 
@@3:
        mov     ax, [esi] // else
        xchg    al, ah // eax = ((*esi << 8) or *(esi + 1)) << 2
        SHL     eax, 2
 
@@4:
        add     edi, ecx // edi += ecx
        inc     ecx // ecx = last encode bytes
 
@LastLoop:
        mov     edx, eax // for (; cex > 0; ecx --, edi --)
        AND     edx, 63 // {
        mov     dl, [ebp + edx] // edx = eax & 63
        mov     [edi], dl // *edi = Base64_Chars[edx]
        SHR     eax, 6 // eax >>= 6
        dec     edi // }
        loop    @LastLoop
 
@end:
        pop     eax
        SHL     eax, 2 // return encode bytes
        pop     ebx
        pop     edi
        pop     esi
        pop     ebp
end;
 
function Base64Encode(const Source; SourceSize: Integer): Base64String;
begin
  SetLength(Result, Base64EncodeBufSize(SourceSize));
  Base64Encode(Source, SourceSize, Result[1]);
end;
 
procedure Base64Encode(Source, Dest: TStream; StartPos: Int64; Size: Int64);
begin
  Base64Stream(Source, Dest, Base64Encode, StartPos, Size, 6144, 8192);
end;
 
{$IFDEF UNICODE}
function StrToBase64(const Str: AnsiString): Base64String;
begin
  Result := Base64Encode(Str[1], Length(Str));
end;
 
function StrToBase64(const Str: string): Base64String;
begin
  Result := StrToBase64(AnsiString(Str));
end;
{$ELSE}
 
function StrToBase64(const Str: string): Base64String;
begin
  Result := Base64Encode(Str[1], Length(Str));
end;
{$ENDIF}
 
function Base64DecodeBufSize(const Base64Source; SourceSize: Integer): Integer;
asm
        mov     ecx, eax // ecx = Source + Size
        add     ecx, edx
        mov     eax, edx // eax = Size / 4 * 3
        SHR     edx, 2
        SHR     eax, 1
        add     eax, edx
        mov     edx, eax
        jz      @@2
 
@@1:
        dec     ecx
        cmp     byte ptr[ecx], 61
        jne     @@2 // if (*--ecx == '=')
        dec     eax // eax --
        jmp     @@1
 
@@2: // return eax: BufSize; edx: Size / 4 * 3
end;
 
function Base64Decode(const Base64Source; SourceSize: Integer; var Buf): Integer;
asm
        push    ebp
        push    esi
        push    edi
        push    ebx
        mov     esi, eax // esi = Source
        mov     edi, ecx // edi = Buf
        mov     ebx, edx
        call    Base64DecodeBufSize
        push    eax // eax = Base64DecodeBufSize(Source, SourceSize)
        sub     edx, eax // edx -= eax // edx: '=' count
        lea     ebp, Base64_Bytes
        SHR     ebx, 2 // ebx = SourceSize / 4
        test    ebx, ebx
        jz      @END
        push    edx
        cld
 
@DecodeLoop: // for (; ebx > 0; ebx --; edi += 3)
        mov     ecx, 4 // {
        XOR     eax, eax
 
@xchgLoop: // for (ecx = 4, eax = 0; ecx > 0; ecx --)
        movzx   edx, [esi] // {
        sub     edx, 43 // edx = *(int*)esi - 43
        SHL     eax, 6 // eax <<= 6
        OR      al, [ebp + edx]// al |= Base64_Bytes[edx]
        inc     esi // esi ++
        loop    @xchgLoop // }
        bswap   eax // bswap(eax)
        dec     ebx // if (ebx == 1) break
        jz      @Last
        SHR     eax, 8 // eax >>= 8
        stosw // *edi = ax; edi += 2
        SHR     eax, 16 // eax >>= 16
        stosb // *edi++ = al
        jmp     @DecodeLoop // }
 
@Last:
        pop     ecx
        XOR     ecx, 3 // ecx = last bytes
 
@LastLoop: // for (; ecx > 0; ecx --)
        SHR     eax, 8 // {
        stosb // eax >>= 8; *edi ++ = al
        loop    @LastLoop // }
 
@end:
        pop     eax // return eax
        pop     ebx
        pop     edi
        pop     esi
        pop     ebp
end;
 
procedure Base64Decode(Source, Dest: TStream; StartPos: Int64; Size: Int64);
begin
  Base64Stream(Source, Dest, Base64Decode, StartPos, Size, 8192, 6144);
end;
 
{$IFDEF UNICODE}
function Base64Decode(const Base64Source; SourceSize: Integer): string;
var
  s: AnsiString;
begin
  SetLength(s, Base64DecodeBufSize(Base64Source, SourceSize));
  Base64Decode(Base64Source, SourceSize, s[1]);
  Result := string(s);
end;
{$ELSE}
 
function Base64Decode(const Base64Source; SourceSize: Integer): string;
begin
  SetLength(Result, Base64DecodeBufSize(Base64Source, SourceSize));
  Base64Decode(Base64Source, SourceSize, Result[1]);
end;
{$ENDIF}
 
function Base64ToStr(const Base64Str: Base64String): string;
begin
  Result := Base64Decode(Base64Str[1], Length(Base64Str));
end;
 
end.

  

posted @   delphi中间件  阅读(587)  评论(0编辑  收藏  举报
努力加载评论中...
点击右上角即可分享
微信分享提示