| ||||||||||||||||
|
Order-0 Adaptive Arithmetic Encoding
by herm1t
See also the project folder
; By using this file, you agree to the terms and conditions set
; forth in the COPYING file which can be found at the top level
; of this distribution.
;
; Order-0 Adaptive Arithmetic Encoding (c) herm1t@vx.netlux.org, 2006-04-16
;
; extern int ari_compress(uchar *src, uchar *dst, int src_len, uchar *temp);
; extern int ari_expand(uchar *src, uchar *dst, uchar *temp);
;
; * src is data to be encoded(ari_cpmpress) or decoded (ari_decode)
; * dst is encoded data (ari_compress) or decoded (ari_decode)
; * src_len is the length of input data
; * temp is a working buffer 3374 bytes long
;
; if the size of compressed data in ari_compress will exceed the
; size of the source buffer function returns zero, size of the
; compressed data otherwise.
;
%define First_qtr 0x4000
%define Half 0x8000
%define Third_qtr 0xc000
%define Top_value 0xffff
%define No_of_chars 0x0100
%define No_of_symbols 0x0101
%define Max_frequency 0x3fff
%define EOF_symbol 0x0101
%define Code_value_bits 16
%define high [ebp + 0] ;4
%define low [ebp + 4] ;4
%define bits_to_follow [ebp + 8] ;4
%define pos [ebp + 12] ;4
%define buf [ebp + 16] ;4
%define buf_len [ebp + 20] ;4
%define save_esp [ebp + 24] ;4
%define char_to_index [ebp + 28] ;1024
%define index_to_char [ebp + 1052] ;258
%define freq [ebp + 1310] ;1032
%define cum_freq [ebp + 2342] ;1032
; 3374
%define value [ebp + 8] ;4
BITS 32
CPU 386
global ari_compress, ari_expand
ari_compress:
pusha
cld
mov esi, [esp + 36]
mov eax, [esp + 40]
mov ecx, [esp + 44]
mov ebp, [esp + 48]
mov save_esp, esp
mov buf_len, ecx
mov buf, eax
xor eax, eax
mov pos, eax
call start_model
call start_encoding
lea ebx, char_to_index
.for: xor eax, eax
lodsb
mov eax, [ebx + eax * 4]
push eax
call encode_symbol
call update_model
add esp, 4
loop .for
push EOF_symbol
call encode_symbol
add esp, 4
call done_encoding
mov eax, pos
cdq
push byte 8
pop ebx
div ebx
or edx, edx
jz .L1
inc eax
.L1: mov [esp + 28], eax
popa
ret
bit_plus_follow:
pusha
mov edi, buf
mov edx, pos
mov ecx, bits_to_follow
mov eax, [esp + 36]
call output_bit
xor al, 1
.L0: jcxz .L1
call output_bit
loop .L0
mov bits_to_follow, ecx
.L1: mov pos, edx
push edx
shr edx, 3
cmp edx, buf_len
jb .ok
mov esp, save_esp
xor eax, eax
jmp ari_compress.L1
.ok: pop edx
popa
retn 4
output_bit:
or eax, eax
jz .L0
bts [edi], edx
jmp .L1
.L0: btr [edi], edx
.L1: inc edx
ret
ari_expand:
pusha
cld
mov eax, [esp + 36]
mov edi, [esp + 40]
mov ebp, [esp + 44]
mov buf, eax
xor eax, eax
mov pos, eax
lea esi, index_to_char
call start_model
call start_decoding
.for: call decode_symbol
mov ebx, eax
cmp eax, EOF_symbol
je .end_for
mov al, [esi + ebx]
stosb
push ebx
call update_model
add esp, 4
jmp .for
.end_for:
sub edi, [esp + 40]
mov [esp + 28], edi
popa
ret
start_encoding:
xor eax, eax
mov bits_to_follow, eax
.common:xor eax, eax
mov low, eax
dec ax
mov high, eax
ret
start_decoding:
pusha
push byte Code_value_bits
pop ecx
xor ebx, ebx
.for: call input_bit
shl ebx, 1
or ebx, eax
loop .for
mov value, ebx
popa
jmp start_encoding.common
done_encoding:
inc dword bits_to_follow
cmp dword low, First_qtr
jae .L0
push 0
jmp .bits
.L0: push 1
.bits: call bit_plus_follow
ret
start_model:
pusha
lea edi, char_to_index
lea esi, index_to_char
xor ecx, ecx
.for1: mov eax, ecx
inc eax
stosd
mov [esi + eax], cl
inc ecx
cmp ecx, No_of_chars
jb .for1
lea esi, freq
lea edi, cum_freq
xor ecx, ecx
mov edx, No_of_symbols
.for2: xor eax, eax
inc eax
mov [esi + ecx * 4], eax
mov eax, edx
sub eax, ecx
stosd
inc ecx
cmp ecx, edx
jbe .for2
xor eax, eax
mov [esi], eax
popa
ret
update_model:
pusha
mov edx, [esp + 36]
lea esi, cum_freq
lea edi, freq
cmp dword [esi], Max_frequency
jne .end_if1
xor eax, eax
mov ecx, No_of_symbols
.for1: mov ebx, [edi + ecx * 4]
inc ebx
shr ebx, 1
mov [edi + ecx * 4], ebx
mov [esi + ecx * 4], eax
add eax, ebx
dec ecx
jns .for1
.end_if1:
mov ecx, edx
.for2: mov eax, [edi + ecx * 4]
cmp eax, [edi + ecx * 4 - 4]
jne .end_for2
dec ecx
jmp .for2
.end_for2:
inc dword [edi + ecx * 4]
cmp ecx, edx
jae .while
lea edi, index_to_char
movzx eax, byte [edi + ecx]
movzx ebx, byte [edi + edx]
mov [edi + ecx], bl
mov [edi + edx], al
lea edi, char_to_index
mov [edi + eax * 4], edx
mov [edi + ebx * 4], ecx
.while: or ecx, ecx
jz .end_while
dec ecx
inc dword [esi + ecx * 4]
jmp .while
.end_while:
popa
ret
encode_symbol:
pusha
lea edi, cum_freq
mov esi, [esp + 36]
mov ebx, low
mov ecx, high
mov eax, ecx
sub eax, ebx
inc eax
push eax
mul dword [edi + esi * 4 - 4]
div dword [edi]
dec eax
mov ecx, eax
add ecx, ebx
pop eax
mul dword [edi + esi * 4]
div dword [edi]
add ebx, eax
.for:
mov eax, Half
cmp ecx, eax
jae .L0
push 0
call bit_plus_follow
jmp .end_if
.L0: cmp ebx, eax
jb .L1
push 1
call bit_plus_follow
sub ebx, eax
sub ecx, eax
jmp .end_if
.L1: mov eax, First_qtr
cmp ebx, eax
jb .end_for
cmp ecx, Third_qtr
jae .end_for
inc dword bits_to_follow
sub ebx, eax
sub ecx, eax
.end_if:
shl ebx, 1
shl ecx, 1
inc ecx
jmp .for
.end_for:
mov low, ebx
mov high, ecx
popa
ret
decode_symbol:
pusha
lea esi, cum_freq
mov ebx, high
sub ebx, low
inc ebx
mov eax, value
sub eax, low
inc eax
mul dword [esi]
dec eax
div ebx
xor ecx, ecx
inc ecx
.for: cmp [esi + ecx * 4], eax
jbe .end_for
inc ecx
jmp .for
.end_for:
mov eax, ebx
mul dword [esi + ecx * 4 - 4]
div dword [esi]
add eax, low
dec eax
mov edi, eax
mov eax, ebx
mul dword [esi + ecx * 4]
div dword [esi]
add eax, low
mov edx, eax
mov ebx, value
.main:
cmp edi, Half
jb .end_if
mov eax, Half
cmp edx, eax
jb .L0
sub ebx, eax
sub edx, eax
sub edi, eax
jmp .end_if
.L0:
mov eax, First_qtr
cmp edx, eax
jb .end_main
cmp edi, Third_qtr
jae .end_main
sub ebx, eax
sub edx, eax
sub edi, eax
.end_if:
shl edx, 1
shl edi, 1
inc edi
call input_bit
shl ebx, 1
or ebx, eax
jmp .main
.end_main:
mov low, edx
mov high, edi
mov value, ebx
mov [esp + 28], ecx
popa
ret
input_bit:
pusha
xor eax, eax
mov edi, buf
mov ecx, pos
bt [edi], ecx
jnc .L0
inc eax
.L0: inc dword pos
mov [esp + 28], eax
popa
ret
| ||||||||||||||||