• 汇编写的BASE64


    汇编写的BASE64

    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.
    

      

  • 相关阅读:
    洛谷 P1200.[USACO1.1]你的飞碟在这儿Your Ride Is Here
    洛谷 P1055.ISBN号码
    洛谷 P1567.统计天数
    洛谷 P2141.珠心算测验
    洛谷 P1428.小鱼比可爱
    洛谷 P1427.小鱼的数字游戏
    洛谷 P1047.校门外的树
    洛谷 P1046.陶陶摘苹果
    洛谷 P1980.计数问题
    洛谷 P1424.小鱼的航程(改进版)
  • 原文地址:https://www.cnblogs.com/hnxxcxg/p/11797077.html
Copyright © 2020-2023  润新知