aP_depack_asm:
; aP_depack_asm(const void *source, void *destination)
_ret$ equ 7*4
_src$ equ 8*4 + 4
_dst$ equ 8*4 + 8
pushad
mov esi, [esp + _src$] ; C calling convention
mov edi, [esp + _dst$]
cld
mov dl, 80h
xor ebx,ebx
literal:
movsb
mov bl, 2
nexttag:
call getbit
jnc literal-------jump if no carry
xor ecx, ecx
call getbit
jnc codepair
xor eax, eax
call getbit
jnc shortmatch
mov bl, 2
inc ecx
mov al, 10h
.getmorebits:
call getbit
adc al, al
jnc .getmorebits
jnz domatch
stosb
jmp nexttag
codepair:
call getgamma_no_ecx
sub ecx, ebx
jnz normalcodepair
call getgamma
jmp domatch_lastpos
shortmatch:
lodsb
shr eax, 1
jz donedepacking
adc ecx, ecx
jmp domatch_with_2inc
normalcodepair:
xchg eax, ecx
dec eax
shl eax, 8
lodsb
call getgamma
cmp eax, 32000
jae domatch_with_2inc
cmp ah, 5
jae domatch_with_inc
cmp eax, 7fh
ja domatch_new_lastpos
domatch_with_2inc:
inc ecx
domatch_with_inc:
inc ecx
domatch_new_lastpos:
xchg eax, ebp
domatch_lastpos:
mov eax, ebp
mov bl, 1
domatch:
push esi
mov esi, edi
sub esi, eax
rep movsb
pop esi
jmp nexttag
getbit:
add dl, dl
jnz .stillbitsleft
mov dl, [esi]
inc esi
adc dl, dl
.stillbitsleft:
ret
getgamma:
xor ecx, ecx
getgamma_no_ecx:
inc ecx
.getgammaloop:
call getbit
adc ecx, ecx
call getbit
jc .getgammaloop
ret
donedepacking:
sub edi, [esp + _dst$]
mov [esp + _ret$], edi ; return unpacked length in eax
popad
ret
以上是aplib减压。已经提到它是lz78的推导。
我想知道getbit
的含义,它在algorithm
中用于从字典中读取代码的方式和位置。
答案 0 :(得分:0)
函数getbit负责从输入数据流中读取一位(“混合”,即包含纯字节和8个独立位组成的组)。
通过一次将8位存储在寄存器dl中并将这些位向左移动(添加dl,dl来完成)来完成位读取。如果移位后寄存器dl等于零,则意味着所有位都已移出,并且需要从流中读取另一个字节,这在代码中完成:
getbit:
add dl, dl
jnz .stillbitsleft
mov dl, [esi]
inc esi
adc dl, dl
.stillbitsleft:
ret
ApLib中使用的实际算法是原始算法,但它是基于与LZ78完全不同的基础构建的,并且与LZ77有很多关系。基本上,在解压缩器循环的每次迭代中,都会从输入流中读取一位,如果该位为0,则会从输入流中将一个字节复制到输出中。如果另一方面,该位为1,则解压缩器知道必须从已解压缩的数据中复制一个匹配项。信号位的想法来自LZSS。匹配的详细信息也在压缩数据流中指定。该格式较不常用的功能包括可以使用rep-offsets,即允许重用偏移量的命令。这个想法很可能是从LZX借来的,与其他许多固定格式的LZ77 / LZSS压缩器相比,此功能使ApLib在压缩方面明显更好。