⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bitstream.asm

📁 这是一个JPEG解码器,里面使用了MMX,SSE等汇编指令集
💻 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 + -