Interesting co/decode routine

Everything else that doesn't fall into one of the other PB categories.
Seldon
Enthusiast
Enthusiast
Posts: 405
Joined: Fri Aug 22, 2003 7:12 am
Location: Italia

Interesting co/decode routine

Post by Seldon »

Hi, I've found by chance this source for PowerBasic language (that I don't own) and I thought it could be nice to convert it for PureBasic. It uses some in-line asm code and since I don't know the PureBasic asm rules I only translated the basic code and I hope we together can translate it entirely. It is a de/compression routine that is said (in that PowerBasic site) to be very fast. Most likely the built-in PureBasic compression library is far better, but it's good to try new things. :wink: Here it is the original PowerBasic code:

Code: Select all

'####################################################### 
'##   Superfast/Supertiny Compression/Decompression   ## 
'##   Original code is by "Jack Qwerty" / 29A, 1998   ## 
'##    Source: http://29a.host.sk/29a-3/29a-3.2_f      ## 
'##  Cheers to Hutcho for helping with stack issues!  ## 
'####################################################### 
'This is a good example that virus coders ARE capable of 
'creating useful things! Why they don't put their efforts 
'to such things more often, I have no idea, you'd have 
'to ask a psychologist. 8-) 
'####################################################### 

FUNCTION Compress(BYVAL ptrInData AS DWORD, BYVAL LenInData AS 
DWORD, BYVAL ptrOutData AS DWORD, BYVAL ptrTmpData AS DWORD) AS 
DWORD 
#REGISTER NONE 
  ! push    ptrTmpData 
  ! push    LenInData 
  ! push    ptrInData 
  ! push    ptrOutData 
  ! call    Start 
  ! mov     FUNCTION, eax 
  EXIT FUNCTION 
  Start: 
  ! sub     edx, edx 
  ! xchg    eax, edx 
  ! pushad 
  ! mov     ebp, esp 
  ! and     ecx, eax 
  ! mov     edi, [ebp+&h30] 
  ! cld 
  ! mov     ch, &h40 
  ! push    edi 
  ! rep     stosd 
  ! sub     edx, &h2864E25C 
  ! mov     esi, [ebp+&h28] 
  ! jnz     pack0 
  ! dec     edx 
  pack0: 
  ! push    ecx 
  ! sub     ax, &h0AEB6 
  ! mov     edi, [ebp+&h24] 
  ! pop     ebx 
  ! stosw 
  ! xchg    eax, edx 
  ! pop     ebp 
  ! stosd 
  ! push    edi 
  ! xchg    eax, edx 
  ! push    esp 
  pack1: 
  ! test    cl, 7 
  ! lodsb 
  ! jnz     pack3 
  ! xchg    edx, [esp] 
  ! adc     ah, dl 
  ! pop     edx 
  ! xchg    edi, [esp] 
  ! ror     edx, 1 
  ! mov     [edi], ah 
  ! jc      pack2 
  ! xor     edx, &h2C047C3E 
  pack2: 
  ! pop     edi 
  ! mov     ah, &h0FF 
  ! push    edi 
  ! xor     edx, &h76C52B8D 
  ! inc     edi 
  ! push    edx 
  pack3: 
  ! cmp     al, [ebx+ebp] 
  ! jz      pack5 
  ! ror     edx, 1 
  ! mov     [ebx+ebp], al 
  ! jnc     pack4 
  ! xor     edx, &h2C047C3E 
  pack4: 
  ! mov     bh, al 
  ! xor     edx, &h5AC157B3 
  ! adc     al, dl 
  ! stosb 
  ! mov     al, bh 
  ! stc 
  pack5: 
  ! inc     ecx 
  ! mov     bh, bl 
  ! rcl     ah, 1 
  ! cmp     ecx, [esp+&h34] 
  ! mov     bl, al 
  ! jc      pack1 
  ! ror     ah, cl 
  ! pop     ebx 
  ! add     ah, bl 
  ! pop     esi 
  ! mov     ebp, esp 
  ! sub     edi, [ebp+&h24] 
  ! mov     [ebp+&h14], edx 
  ! xchg    ah, [esi] 
  ! add     [ebp+&h1C], edi 
  ! popad 
  ! ret &h10 
END FUNCTION 
  
FUNCTION Decompress(BYVAL ptrInData AS DWORD, BYVAL LenInData AS 
DWORD, BYVAL ptrOutData AS DWORD, BYVAL ptrTmpData AS DWORD) AS 
DWORD 
#REGISTER NONE 
  ! push    ptrTmpData 
  ! push    LenInData 
  ! push    ptrInData 
  ! push    ptrOutData 
  ! call    Start 
  ! mov     FUNCTION, eax 
  EXIT FUNCTION 
  Start: 
  ! sub     eax, eax 
  ! pushad 
  ! mov     ebp, esp 
  ! and     ecx, eax 
  ! mov     edi, [ebp+&h30] 
  ! cld 
  ! mov     ch, &h40 
  ! push    edi 
  ! rep     stosd 
  ! mov     esi, [ebp+&h28] 
  ! xchg    ebx, eax 
  ! add     ecx, [ebp+&h2C] 
  ! lodsw 
  ! mov     edi, [ebp+&h24] 
  ! add     ecx,-6 
  ! pop     ebp 
  ! lodsd 
  ! xchg    eax, edx 
  unpack0: 
  ! test    byte ptr [esp+&h1C], 7 
  ! jnz     unpack2 
  ! ror     edx, 1 
  ! jecxz   unpack5 
  ! jnc     unpack1 
  ! xor     edx, &h2C047C3E 
  unpack1: 
  ! lodsb 
  ! dec     ecx 
  ! xor     edx, &h5AC157B3 
  ! sbb     al, dl 
  ! mov     ah, al 
  unpack2: 
  ! shl     ah, 1 
  ! inc     byte ptr [esp+&h1C] 
  ! jnc     unpack4 
  ! ror     edx, 1 
  ! jecxz   unpack5 
  ! jc      unpack3 
  ! xor     edx, &h2C047C3E 
  unpack3: 
  ! lodsb 
  ! dec     ecx 
  ! xor     edx, &h76C52B8D 
  ! sbb     al, dl 
  ! mov     [ebx+ebp], al 
  unpack4: 
  ! mov     al, [ebx+ebp] 
  ! mov     bh, bl 
  ! stosb 
  ! mov     bl, al 
  ! jmp     unpack0 
  ! dec     edx 
  ! push    ecx 
  unpack5: 
  ! sub     edi, [esp+&h24] 
  ! mov     [esp+&h1C], edi 
  ! popad 
  ! ret     &h10 
END FUNCTION 
  
FUNCTION PBMAIN() AS LONG 
DIM sInData AS STRING, sOutData AS STRING, sTmpData AS STRING * 
65535, OutSize AS DWORD 
'// Data to compress 
sInData = REPEAT$(1000, "testing") 
'// Compress it ... 
sOutData = STRING$(LEN(sInData),0) 
OutSize = Compress(BYVAL STRPTR(sInData), BYVAL LEN(sInData), 
BYVAL STRPTR(sOutData), BYVAL VARPTR(sTmpData)) 
IF OutSize > LEN(sInData) THEN 
    STDOUT "Unable to compress this data (probably not enough 
repetition)." 
    WAITKEY$ 
    EXIT FUNCTION 
END IF 
STDOUT "Original size     = " & STR$(LEN(sInData)) & " bytes" 
STDOUT "Compressed size   = " & STR$(OutSize) & " bytes (" & 
TRIM$(STR$((OutSize / LEN(sInData)) * 100)) & "%)" 
sInData = LEFT$(sOutData, OutSize) '// sInData now contains the 
compressed string. 
  
'// Decompress sInData 
sOutData = STRING$(LEN(sInData) * 10,0) '// allocate enough space 
OutSize = Decompress(BYVAL STRPTR(sInData), BYVAL LEN(sInData), 
BYVAL STRPTR(sOutData), BYVAL VARPTR(sTmpData)) 
STDOUT "Decompressed size = " & STR$(OutSize) & " bytes" 
sInData = LEFT$(sOutData, OutSize) 
  
WAITKEY$ 
END FUNCTION
And here it is the PureBasic version (what I did sofar). Basically, just the asm part should be translated:

Code: Select all

OpenConsole()

Procedure.l Compress(PtrInData.l,LenInData.l,PtrOutData.l,PtrTmpData.l) 
EndProcedure 

Procedure.l Decompress(PtrInData.l,LenInData.l,PtrOutData.l,PtrTmpData.l)
EndProcedure

sInData.s=Space(1000)                ;Input buffer (maybe AllocateMemory would be better)
sOutData.s=Space(Len(sInData.s)*10)  ;Compressed string 
*TmpData.l=AllocateMemory(0,65535,0) ;Working buffer

stringa$="Nel mezzo del cammin di nostra vita" ;String to compress

;// Data to compress
For i.b=1 To Len(stringa$)
 PokeB(@sInData.s+i.b-1,Asc(Mid(stringa$,i.b,1)))
Next
; Why DOESN'T [ CopyMemoryString("Test",@sInData.s) ] work ?

PrintN(sInData.s)

;// Compress it ...
;OutSize.l = Compress(@sInData.s, Len(sInData.s), @sOutData.s, *TmpData.l) 

If OutSize.l > Len(sInData.s) 
 PrintN("Unable to compress this data (probably not enough repetition).")
Else
 PrintN("Original size     = "+Str(Len(sInData.s))+" bytes")
 PrintN("Compressed size   = "+Str(OutSize.l)+" bytes ("+Trim(Str((OutSize.l / Len(sInData.s)) * 100))+"%)") 
 sInData.s = Left(sOutData.s,OutSize.l) ;sInData now contains the compressed string. 

;// Decompress sInData 

;OutSize.l = Decompress(@sInData.s, Len(sInData.s), @sOutData.s, *TmpData.l) 
PrintN("Decompressed size = "+Str(OutSize.l)+" bytes") 
sInData.s = Left(sOutData.s, OutSize.l) 

EndIf

tasto$=Input()
CloseConsole()
End
Shannara
Addict
Addict
Posts: 1808
Joined: Thu Oct 30, 2003 11:19 pm
Location: Emerald Cove, Unformed

Post by Shannara »

Im bumping this topic for obvious reasons.. anybody have an answer?
El_Choni
TailBite Expert
TailBite Expert
Posts: 1007
Joined: Fri Apr 25, 2003 6:09 pm
Location: Spain

Post by El_Choni »

Hi, tried this and crashes:

Code: Select all

OpenConsole()

Procedure.l Compress(PtrInData.l, LenInData.l, PtrOutData.l, PtrTmpData.l)
  PUSH    ptrTmpData
  PUSH    LenInData
  PUSH    ptrInData
  PUSH    ptrOutData
  !CALL    CompressStart
  ProcedureReturn
  !CompressStart:
  SUB     edx, edx
  XCHG    eax, edx
  PUSHAD
  MOV     ebp, esp
  AND     ecx, eax
  MOV     edi, [ebp+$30]
  CLD
  MOV     ch, $40
  PUSH    edi
  REP     stosd
  SUB     edx, $2864E25C
  MOV     esi, [ebp+$28]
  !JNZ     pack0
  DEC     edx
  !pack0:
  PUSH    ecx
  SUB     ax, $0AEB6
  MOV     edi, [ebp+$24]
  POP     ebx
  !stosw
  XCHG    eax, edx
  POP     ebp
  !stosd
  PUSH    edi
  XCHG    eax, edx
  PUSH    esp
  !pack1:
  TEST    cl, 7
  LODSB
  !JNZ     pack3
  XCHG    edx, [esp]
  ADC     ah, dl
  POP     edx
  XCHG    edi, [esp]
  ROR     edx, 1
  MOV     [edi], ah
  !JC      pack2
  XOR     edx, $2C047C3E
  !pack2:
  POP     edi
  MOV     ah, $0FF
  PUSH    edi
  XOR     edx, $76C52B8D
  INC     edi
  PUSH    edx
  !pack3:
  CMP     al, [ebx+ebp]
  !JZ      pack5
  ROR     edx, 1
  MOV     [ebx+ebp], al
  !JNC     pack4
  XOR     edx, $2C047C3E
  !pack4:
  MOV     bh, al
  XOR     edx, $5AC157B3
  ADC     al, dl
  !stosb
  MOV     al, bh
  STC
  !pack5:
  INC     ecx
  MOV     bh, bl
  RCL     ah, 1
  CMP     ecx, [esp+$34]
  MOV     bl, al
  !JC      pack1
  ROR     ah, cl
  POP     ebx
  ADD     ah, bl
  POP     esi
  MOV     ebp, esp
  SUB     edi, [ebp+$24]
  MOV     [ebp+$14], edx
  XCHG    ah, [esi]
  ADD     [ebp+$1C], edi
  POPAD
  RET $10
EndProcedure

Procedure.l Decompress(PtrInData.l,LenInData.l,PtrOutData.l,PtrTmpData.l)
  PUSH    ptrTmpData
  PUSH    LenInData
  PUSH    ptrInData
  PUSH    ptrOutData
  !CALL    DecompressStart
  ProcedureReturn
  !DecompressStart:
  SUB     eax, eax
  PUSHAD
  MOV     ebp, esp
  AND     ecx, eax
  MOV     edi, [ebp+$30]
  CLD
  MOV     ch, $40
  PUSH    edi
  REP     stosd
  MOV     esi, [ebp+$28]
  XCHG    ebx, eax
  ADD     ecx, [ebp+$2C]
  LODSW
  MOV     edi, [ebp+$24]
  ADD     ecx,-6
  POP     ebp
  !lodsd
  XCHG    eax, edx
  !unpack0:
  TEST    byte [esp+$1C], 7
  !JNZ     unpack2
  ROR     edx, 1
  TEST ecx, ecx
  !JZ      unpack5
  !JNC     unpack1
  XOR     edx, $2C047C3E
  !unpack1:
  LODSB
  DEC     ecx
  XOR     edx, $5AC157B3
  SBB     al, dl
  MOV     ah, al
  !unpack2:
  SHL     ah, 1
  INC     byte [esp+$1C]
  !JNC     unpack4
  ROR     edx, 1
  TEST ecx, ecx
  !JZ      unpack5
  !JC      unpack3
  XOR     edx, $2C047C3E
  !unpack3:
  LODSB
  DEC     ecx
  XOR     edx, $76C52B8D
  SBB     al, dl
  MOV     [ebx+ebp], al
  !unpack4:
  MOV     al, [ebx+ebp]
  MOV     bh, bl
  !stosb
  MOV     bl, al
  !JMP     unpack0
  DEC     edx
  PUSH    ecx
  !unpack5:
  SUB     edi, [esp+$24]
  MOV     [esp+$1C], edi
  POPAD
  RET     $10
EndProcedure

sInData.s=Space(1000)                ;Input buffer (maybe AllocateMemory would be better)
sOutData.s=Space(Len(sInData.s)*10)  ;Compressed string
*TmpData.l=AllocateMemory(65535) ;Working buffer

stringa$="Nel mezzo del cammin di nostra vita" ;String to compress

;// Data to compress
For i.b=1 To Len(stringa$)
PokeB(@sInData.s+i.b-1,Asc(Mid(stringa$,i.b,1)))
Next
; Why DOESN'T [ CopyMemoryString("Test",@sInData.s) ] work ?

PrintN(sInData.s)

;// Compress it ...
OutSize.l = Compress(@sInData.s, Len(sInData.s), @sOutData.s, *TmpData.l)

If OutSize.l > Len(sInData.s)
PrintN("Unable to compress this data (probably not enough repetition).")
Else
PrintN("Original size     = "+Str(Len(sInData.s))+" bytes")
PrintN("Compressed size   = "+Str(OutSize.l)+" bytes ("+Trim(Str((OutSize.l / Len(sInData.s)) * 100))+"%)")
sInData.s = Left(sOutData.s,OutSize.l) ;sInData now contains the compressed string.

;// Decompress sInData

OutSize.l = Decompress(@sInData.s, Len(sInData.s), @sOutData.s, *TmpData.l)
PrintN("Decompressed size = "+Str(OutSize.l)+" bytes")
sInData.s = Left(sOutData.s, OutSize.l)

EndIf

tasto$=Input()
CloseConsole()
End 
El_Choni
Num3
PureBasic Expert
PureBasic Expert
Posts: 2812
Joined: Fri Apr 25, 2003 4:51 pm
Location: Portugal, Lisbon
Contact:

Post by Num3 »

Well it does look good, but it does crash :(
thefool
Always Here
Always Here
Posts: 5875
Joined: Sat Aug 30, 2003 5:58 pm
Location: Denmark

Post by thefool »

yes it looks good, but crashes. But i added an onerror description and it told me this:
An attemped read or write to/from an address to which that process isn't allowed
El_Choni
TailBite Expert
TailBite Expert
Posts: 1007
Joined: Fri Apr 25, 2003 6:09 pm
Location: Spain

Post by El_Choni »

Someone can test it with OllyDbg to see where the error is? I don't have OllyDbg here.
El_Choni
Post Reply