📄 bitstream.asm
字号:
;// Bitstream
.686P
.MODEL FLAT, STDCALL
OPTION CASEMAP:NONE
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
.MMX
.XMM
INCLUDE jpeg.inc
.CODE
;//=========================================================================
;// Init bitstream
;// params : ESI : pointer to start of bitstream
;// params : ECX : number of bytes in bitstream
;//=========================================================================
BS_Init PROC
push esi
;// init bitstream variables
mov BS.CurrentPtr, esi
mov BS.NbLeft, ecx
add esi, ecx
mov BS.Limit, esi
DBG_CHECKBS
;// align bitstream
call BS_Align
pop esi
ret
BS_Init ENDP
;//=========================================================================
;// Align bitstream pointer
;//=========================================================================
BS_Align PROC
push esi
push edi
push ebx
call BS_GetPtr
mov esi, eax
lea edi, BS.Temp
pxor mm0, mm0
movq [edi], mm0
lea ecx, [eax+7]
and ecx, NOT(7)
sub ecx, eax
mov edx, BS.NbLeft
MIN ecx, edx
mov eax, ecx
shl eax, 3
sub BS.NbLeft, ecx
rep movsb
mov BS.Bits, eax
mov BS.CurrentPtr, esi
mov eax, DPTR BS.Temp[0]
mov ecx, DPTR BS.Temp[4]
bswap eax
bswap ecx
movd mm0, eax
movd mm1, ecx
psllq mm0, 32
por mm0, mm1
DBG_CHECKBS
pop ebx
pop edi
pop esi
ret
BS_Align ENDP
;//=========================================================================
;// Read bits
;// params : EAX : number of bits
;// returns : bits in eax and mm2
;// returns : JC if end of bitstream
;//=========================================================================
BS_GetBits PROC
;// Based on Intel AppNote 527
ASSERT(eax !>= 0)
ASSERT(eax !< 64)
PROFILE_IN
sub BS.Bits, eax
jl Refill
movd mm1, eax
movq mm2, mm0
psrlq mm2, TBL_64[8*eax]
psllq mm0, mm1
movd eax, mm2
PROFILE_OUT "BS_GetBits (no refill)"
DBG_CHECKBS
ret
Refill:
PROFILE_IN
mov edx, BS.CurrentPtr
sub BS.NbLeft, 8
jl Less8
;// read 64 bits
New64:
add BS.CurrentPtr, 8
mov ecx, [edx]
mov edx, [edx+4]
bswap ecx
bswap edx
movd mm1, ecx
movd mm2, edx
psllq mm1, 32
mov ecx, BS.Bits
por mm1, mm2
add ecx, 64
movq mm2, mm1
mov BS.Bits, ecx
movq mm3, TBL_64[8*ecx]
lea ecx, [ecx+eax-64]
movd mm4, ecx
psrlq mm1, mm4
por mm0, mm1
psrlq mm0, TBL_64[8*eax]
movd eax, mm0
psllq mm2, mm3
sub ecx, ecx
movq mm0, mm2
PROFILE_OUT "BS_GetBits (refill)"
DBG_CHECKBS
ret
Less8:
;// less than 8 bytes available
sub esp, 8*2
N EQU <DPTR [esp]>
K EQU <DPTR [esp+8]>
pxor mm1, mm1
movq QPTR N, mm1
movq QPTR K, mm1
mov N, eax
mov ecx, BS.Bits
add ecx, eax
mov K, ecx
sub ecx, ecx
L8Loop:
cmp edx, BS.Limit
jae EL8Loop
mov al, [edx]
mov BPTR BS.Temp[ecx], al
inc ecx
inc edx
jmp L8Loop
EL8Loop:
mov BS.NbLeft, 0
mov BS.CurrentPtr, edx
shl ecx, 3
add BS.Bits, ecx
jl Eob
Update:
mov eax, DPTR BS.Temp[0]
mov ecx, DPTR BS.Temp[4]
bswap eax
bswap ecx
movd mm1, eax
movd mm2, ecx
psllq mm1, 32
por mm1, mm2
movq mm2, mm1
psrlq mm1, QPTR K
por mm0, mm1
mov eax, N
psrlq mm0, TBL_64[8*eax]
sub eax, K
movd mm3, eax
psllq mm2, mm3
movd eax, mm0
movq mm0, mm2
add esp, 8*2
sub ecx, ecx
DBG_CHECKBS
ret
Eob:
mov BS.Bits, 0
add esp, 8*2
stc
DBG_CHECKBS
ret
BS_GetBits ENDP
;//=========================================================================
;// Read bits in ECS segment
;// params : EAX : number of bits
;// returns : bits
;// returns : JC if end of bitstream
;//=========================================================================
BS_GetBitsECS PROC
ASSERT(eax !>= 0)
ASSERT(eax !< 64)
PROFILE_IN
sub BS.Bits, eax
jl Refill
movd mm1, eax
movq mm2, mm0
psrlq mm2, TBL_64[8*eax]
psllq mm0, mm1
movd eax, mm2
PROFILE_OUT "BS_GetBitsECS (no refill)"
DBG_CHECKBS
ret
Refill:
PROFILE_IN
mov edx, BS.CurrentPtr
sub BS.NbLeft, 8
jl Special
;// test alignment
test edx, 7
jnz Special
;// test the presence of FF
pcmpeqd mm1, mm1
pcmpeqb mm1, [edx]
pmovmskb ecx, mm1
test ecx, ecx
jnz Special
;// normal refill
add BS.CurrentPtr, 8
mov ecx, [edx]
mov edx, [edx+4]
bswap ecx
bswap edx
movd mm1, ecx
movd mm2, edx
psllq mm1, 32
mov ecx, BS.Bits
por mm1, mm2
add ecx, 64
movq mm2, mm1
mov BS.Bits, ecx
movq mm3, TBL_64[8*ecx]
lea ecx, [ecx+eax-64]
movd mm4, ecx
psrlq mm1, mm4
por mm0, mm1
psrlq mm0, TBL_64[8*eax]
movd eax, mm0
psllq mm2, mm3
sub ecx, ecx
movq mm0, mm2
PROFILE_OUT "BS_GetBitsECS (refill)"
DBG_CHECKBS
ret
;// ptr not aligned, FF found or nbytes < 8
Special:
PROFILE_IN
sub esp, 8*2
N TEXTEQU <DPTR [esp]>
K TEXTEQU <DPTR [esp+8]>
SRC TEXTEQU <edx>
DST TEXTEQU <ebx>
NB TEXTEQU <BS.NbLeft>
;// save ebx
mov N[4], ebx
;// save number of requested bits
mov N, eax
mov ecx, BS.Bits
mov ebx, 7
add eax, ecx
mov K, eax
;// calculate nb of bytes to get
;// nbytes = max( (-bits+7) / 8, 8 - src & 7)
;// nbytes = - min(( bits - 7) / 8, src & 7 - 8)
sub ecx, ebx
and ebx, SRC
sar ecx, 3
sub ebx, 8
MIN ecx, ebx
;// set src and dst pointer
lea DST, BS.Temp[0]
pxor mm1, mm1
movq [DST], mm1
sub DST, ecx
;// read bytes
add NB, 8
RLoop:
cmp NB, 0
jz RDone
mov al, [SRC]
inc SRC
mov [DST][ecx], al
dec NB
cmp al, 0FFh
jne NextR
;// FF found : FF 00 <=> FF, FF xx <=> marker
cmp NB, 0
jz RDone
mov al, [SRC]
test al, al
jnz Marker
inc SRC
dec NB
NextR:
add BS.Bits, 8
inc ecx
jnz RLoop
RDone:
sub ecx, ecx
mov ebx, N[4]
mov N[4], ecx
mov K[4], ecx
mov BS.CurrentPtr, SRC
cmp BS.Bits, ecx
jl Eob
Update:
mov eax, DPTR BS.Temp[0]
mov ecx, DPTR BS.Temp[4]
bswap eax
bswap ecx
movd mm1, eax
movd mm2, ecx
psllq mm1, 32
por mm1, mm2
movq mm2, mm1
psrlq mm1, QPTR K
por mm0, mm1
mov eax, N
psrlq mm0, TBL_64[8*eax]
sub eax, K
movd mm3, eax
psllq mm2, mm3
movd eax, mm0
movq mm0, mm2
add esp, 8*2
sub ecx, ecx
PROFILE_OUT "BS_GetBitsECS (special)"
DBG_CHECKBS
ret
Marker:
;// marker found
dec SRC
inc NB
mov byte ptr [DST][ecx], 0
jmp RDone
;// end of bitstream
Eob:
mov BS.Bits, 0
add esp, 8*2
stc
DBG_CHECKBS
ret
BS_GetBitsECS ENDP
;//========================================================================
;// Test the number of bytes in the bitstream
;// Params : eax : number of bytes to test (nb)
;// returns : eax : number of bytes to test
;// returns : JLE : left >= nb, JNLE : left < nb
;//=========================================================================
BS_Test PROC
;// condition :
;// BsPtr - BsBits / 8 + size <= BsEnd
mov edx, eax
mov ecx, BS.Bits
add edx, BS.CurrentPtr
shr ecx, 3
sub edx, ecx
cmp edx, BS.Limit
ret
BS_Test ENDP
;//========================================================================
;// Skip bytes
;// Params : EAX : nb of bytes
;//========================================================================
BS_SkipBytes PROC
sub BS.NbLeft, eax
mov ecx, BS.Bits
add eax, BS.CurrentPtr
shr ecx, 3
sub eax, ecx
mov BS.Bits, 0
mov BS.CurrentPtr, eax
add BS.NbLeft, ecx
DBG_CHECKBS
call BS_Align
ret
BS_SkipBytes ENDP
;//========================================================================
;// Return the current pointer in the bitstream
;// returns : pointer to the bitstream
;//========================================================================
BS_GetPtr PROC
mov ecx, BS.Bits
mov eax, BS.CurrentPtr
shr ecx, 3
sub eax, ecx
mov BS.Bits, 0
add BS.NbLeft, ecx
mov BS.CurrentPtr, eax
DBG_CHECKBS
ret
BS_GetPtr ENDP
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -