📄 depptiny.nas
字号:
;;
;; aPLib compression library - the smaller the better :)
;;
;; NASM 16bit assembler tiny depacker example
;;
;; Copyright (c) 1998-2002 by Joergen Ibsen / Jibz
;; All Rights Reserved
;;
;; -> 16bit by Metalbrain (metalbrain_coder@gmx.net)
;;
;;*************************************************************************
;; WARNING!!!! : New headers NOT supported. Cut 24 bytes from packed file
;; to make it work
;;*************************************************************************
org 256
cld ;Clear direction flag for safety
mov ah,4ah ;Modify memory block size (on start,
; the .COM program is given all free
; memory, but this could be less than
; the needed amount (162K). As a nice
; side effect, we are freeing unused
; memory, but who cares under DOS?
mov bh,41 ;Number of needed paragraphs
; (rounded up)
call int_n_check ;Resize or exit if error
pop cx ;CX=0 (useful later)
mov si,129 ;Arguments from PSP start here
mov di,testitnow ;This will be called quite a few times
; and later will be used to place
; variables
mov bx,tmpname+1
space1 mov dx,si ;Keep start infile name in DX
call di ;Parse...
jz space1 ;Search for non-space
space2 call di ;Keep parsing
jnz space2 ;Till a space appears
mov [si-1],dh ;Make infile ASCIIZ
space3 push si ;Keep start outfile name in stack
call di ;Still parsing
jz space3 ;Now search a non-space again
mov [unitoutfile],al;Set unit for temporal outfile
space4 lodsb ;Final parse
cmp al,":" ;Is there's a unit in outfile name?
jnz nounit ;No-> skip next
sub byte [bx],bh ;Yes-> temporal outfile includes unit
nounit cmp al," "
ja space4 ;Space or below means end of filename
mov [si-1],dh ;Make ASCIIZ this one too
mov ax,3d00h ;Function to open infile
call int_n_check ;Try it
stosw ;Store infile handle at handlein
mov dx,[bx] ;Get outfile name position
mov ah,3ch
call int_n_check ;Create temporal outfile: "NOT OK$"
stosw ;Store temporal outfile handle
xchg ax,dx ;And place it in DX
xor ebx,ebx ;EBX=0
pop si ;Pop outfile name address from stack
mov bh,8 ;BX=inbuff
mov sp,bx ;Set stack before inbuff
mov ax,es ;Segment
add ax,bx ; +32K in AX
imul eax,eax,byte 16 ;32 bit start of segment address+32K
add eax,ebx ;EAX=freemem 32 bit address
push si ;Push again outfile name address
mov dl,128 ;Reset bit counter in DL, and DX=0080h
stosd ;Set EAX at freemem32
stosd ; and limit32
add [di-2],byte 2 ;Now limit32=freemem32+128K
xchg eax,edi ;Set freemem32 at EDI
mov esi,edi ;And ESI
;Starting point for DEPACK16
push edi ;Store freemem32
literal call getesi ;Copy a byte from [esi] to [edi]
putedi_nexttag call putedi
mov dh,1 ;Set lastwasmatch marker in dh
call newtest ;Here EAX=0
jmp short nexttag ;Decode next tag bits...
normalcodepair xchg ax,cx ;High part of distance in AX
dec ax ;Subtract 1. Min value is 0
shl eax,8 ;EAX=00dddd00h
call getesi ;Fill distance in AL
call getgamma ;Take gamma encoded ECX
cmp eax,32000
jae domatch_with_2inc ;Above 31999: ECX+=2
cmp ah,5
jae domatch_with_inc ;1279<EAX<32000: ECX=+1
cmp ax,byte 127
ja domatch_new_lastpos ;EAX<128: ECX+=2
domatch_with_2inc
inc ecx
domatch_with_inc
inc ecx
domatch_new_lastpos
xchg eax,ebp ;Store EAX in EBP (lastpos)
domatch_lastpos mov eax,ebp ;Take EAX from last EBP (lastpos)
mov dh,0 ;Clear lastwasmatch marker
domatch
;Here EAX=match distance
; ECX=match lenght
push esi ;Store current read pointer
mov esi,edi
sub esi,eax ;ESI=EDI-EAX > origin pointer
cmp esi,[freemem32] ;Test for bad infile #1: Limit crossed
call finerr01 ;Exit if error
repmovsb call dontread ;getesi without checking limit
call putedi ;and with putedi completes the movsb
mov ah,128 ;Here EAX=32768 (in case of writing
call newtest ; data, update esi too)
loop repmovsb,ecx ;Do it ecx times
pop esi ;Recover read pointer
nexttag call getbit ;Get a bit
jnc literal ;0: literal, go for it
xor ecx,ecx ;Clear ECX
cbw ;and AX (AX was 0 or 32K)
call getbit ;Get another bit
jnc codepair ;10: codepair, go for it
call getbit ;Get yet another one
jnc shortmatch ;110: shortmatch
mov dh,1 ;Set lastwasmatch marker in dh
inc cx ;CX=1
mov al,16 ;Set marker bit
getmorebits call getbit ;Get a bit
adc al,al ;Set it in AL
jnc getmorebits ;Do it till marker is out (4 times)
jnz domatch ;111xxxx: continue, AL has distance
jmp short putedi_nexttag ;1110000: Put a zero byte
codepair call getgamma ;Get gamma encoded first part of
; distance in CX. Min value is 2
shr dh,1 ;Fix distance taking lastwasmatch
sbb cx,byte 1 ; marker in consideration
jnz normalcodepair ;If not zero, it's a normal codepair
push word domatch_lastpos ;Get gamma encoded lenght in ECX
; then jump to domatch_lastpos (use
; last distance)
getgamma inc cx ;First bit is always 1
getgammaloop call getbit ;Get next bit
adc ecx,ecx ;Put it in ECX
call getbit ;Get gamma bit
jc getgammaloop ;If it's 1, continue growing ECX
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -