;=====================================; ; S T R C ; ;-------------------------------------; ; Super Tiny Reloc Compressor ; ;=====================================; ; Made by Super/29A ; ;=====================================; Pushd equ 4 Pushad_edi equ 00h Pushad_esi equ 04h Pushad_ebp equ 08h Pushad_esp equ 0ch Pushad_ebx equ 10h Pushad_edx equ 14h Pushad_ecx equ 18h Pushad_eax equ 1ch ;-----------------------------------------------------------; ; Routine "STRC_max_compress" ; ; Tries different methods and compresses with the best ratio. ; ; INPUT: ; ESI = offset of start of reloc section ; EDI = buffer to store the compressed reloc data ; ECX = number of *bytes* of reloc section (not aligned) ; ; OUTPUT: ; BL = selected method of compression ; (number of bits to encode relative offset) ; ECX = number of *bits* of compressed reloc data ;-----------------------------------------------------------; STRC_max_compress proc near push eax stc sbb eax,eax ;eax=-1 mov bl,0eh ;try with 14 bits @@1: inc ebx push ecx call STRC_compress ;compress it cmp ecx,eax ;this method better? jnb @@2 ;jump if not xchg ecx,eax dec ebx dec ebx ;go for next method @@2: pop ecx jnz @@1 ;try again if we havent found the perfect method xchg ecx,eax pop eax ret STRC_max_compress endp ;-----------------------------------------------------------; ; Routine "STRC_compress" ; ; Compresses the reloc section. ; ; INPUT: ; BL = method of compression ; (number of bits to encode relative offset) ; ESI = offset of start of reloc section ; EDI = buffer to store the compressed reloc data ; ECX = number of *bytes* of reloc section (not aligned) ; ; OUTPUT: ; ECX = number of *bits* of compressed reloc data ;-----------------------------------------------------------; STRC_compress proc near add ecx,esi ;ecx=end of input buffer pushad xor ebp,ebp xor ebx,ebx ;bit count @@1: lodsd xchg edx,eax ;edx=virtual address lodsd lea ecx,[eax-8] ;ecx=size of this block @@2: push ecx push edx lodsw sub ah,40h jnb @@6 ;jump if invalid relocation add ah,10h jnb @@6 ;jump if invalid relocation cwde add eax,edx ;add the virtual address of actual page sub eax,ebp ;calculate relative address add ebp,eax ;update last virtual address push ebx db 0fh,0bdh,0d8h ; bsr ebx,eax ;calculate number of bits taken movzx ecx,byte ptr [esp+(Pushd*3)+Pushad_ebx] ;cl=bits chosen for this method cmp bl,cl ;we need more bits to store it? jb @@3 ;nope shld edx,eax,cl ; shl eax,cl ; shr ebx,3 ; or al,bl ; insert number of bytes needed to store it lea ecx,[ecx+(ebx*8)+8] ; @@3: pop ebx @@4: btr [edi],ebx ; shr edx,1 ; rcr eax,1 ; jnb @@5 ; bts [edi],ebx ; store information bit by bit @@5: ; inc ebx ; loop @@4 ; @@6: pop edx pop ecx dec ecx loop @@2 ;next word of actual block cmp esi,[esp+Pushad_ecx] ;have we processed all blocks? jb @@1 ;nope STRC_exit: mov [esp+Pushad_ecx],ebx ;return number of bits of compressed data popad ret STRC_compress endp ;-----------------------------------------------------------; ; Routine "STRC_decompress" ; ; Decompresses the reloc section. ; ; INPUT: ; BL = method of compression ; (number of bits to encode relative offset) ; ESI = offset of compressed reloc data ; EDI = buffer to store the reloc section ; ECX = number of *bits* of compressed reloc data ; ; OUTPUT: ; ECX = number of *bytes* of decompressed reloc section ;-----------------------------------------------------------; STRC_decompress proc near pushad xor ebp,ebp xor ebx,ebx @@1: cmp ebx,ecx ;have we finished? jnb @@7 ;nope push ecx movzx ecx,byte ptr [esp+(Pushd*1)+Pushad_ebx] ;cl=bits chosen for this method @@2: xor eax,eax push ecx @@3: bt [esi],ebx ; rcr eax,1 ; inc ebx ; get relative offset loop @@3 ; pop ecx ; rol eax,cl ; lea ecx,[(eax*8)+8] ;ax=0--> 8 bits ;ax=1--> 16 bits ;ax=2--> 24 bits ;ax=3--> 32 bits cmp eax,4 ;do we need to read more bits to get the whole relative offset jb @@2 ;yes pop ecx add eax,ebp dec ebp mov ebp,eax ;update last virtual address jns @@5 ;jump if this is not the first time @@4: mov eax,ebp and eax,-1000h stosd ;store start virtual address of this page xor eax,eax mov al,8 mov edx,edi stosd ;store size of this block @@5: mov eax,ebp sub eax,[edx-4] cmp eax,1000h jnb @@7 ;jump if we are in next page sub ah,-30h ;make it of type 3 :-) @@6: stosw ;store relocation inc dword ptr [edx] ; inc dword ptr [edx] ; increment block size by two jb @@1 @@7: xor eax,eax test byte ptr [edx],2 jnz @@6 ;align this block if necesary cmp ebx,ecx ;finished? jb @@4 ;nope mov ebx,edi sub ebx,[esp] ;calculate size of decompressed data jmp STRC_exit STRC_decompress endp ;------------------------------------------------------------------- ends end start