内联汇编的快速CRC32

来源:互联网 发布:知乎 李矛 编辑:程序博客网 时间:2024/05/20 05:47
typedef unsigned __int64 QWORD;

class CCrc32Static
{
public:
    CCrc32Static()
{};
    
virtual ~CCrc32Static(){};
    
static DWORD StringCrc32(LPCTSTR szString, DWORD &dwCrc32);
    
static DWORD FileCrc32Assembly(LPCTSTR szFilename, DWORD &dwCrc32);
protected:
    
static inline void CalcCrc32(const BYTE byte, DWORD &dwCrc32);
    
static DWORD s_arrdwCrc32Table[256];
}
;

#define MAX_BUFFER_SIZE 4096
//#define MAKEQWORD(a, b) ((WORD)(((BYTE)((DWORD_PTR)(a) & 0xffffffffffffffff)) | ((WORD)((BYTE)((DWORD_PTR)(b) & 0xffffffffffffffff))) << 64))
    //Powered by barenx
//#define INVALID_HANDLE_VALUE ((HANDLE)(-1))   
// Static CRC table
DWORD CCrc32Static::s_arrdwCrc32Table[256=
{
    
0x000000000x770730960xEE0E612C0x990951BA,
        
0x076DC4190x706AF48F0xE963A5350x9E6495A3,
        
0x0EDB88320x79DCB8A40xE0D5E91E0x97D2D988,
        
0x09B64C2B0x7EB17CBD0xE7B82D070x90BF1D91,
        
0x1DB710640x6AB020F20xF3B971480x84BE41DE,
        
0x1ADAD47D0x6DDDE4EB0xF4D4B5510x83D385C7,
        
0x136C98560x646BA8C00xFD62F97A0x8A65C9EC,
        
0x14015C4F0x63066CD90xFA0F3D630x8D080DF5,
        
0x3B6E20C80x4C69105E0xD56041E40xA2677172,
        
0x3C03E4D10x4B04D4470xD20D85FD0xA50AB56B,
        
0x35B5A8FA0x42B2986C0xDBBBC9D60xACBCF940,
        
0x32D86CE30x45DF5C750xDCD60DCF0xABD13D59,
        
0x26D930AC0x51DE003A0xC8D751800xBFD06116,
        
0x21B4F4B50x56B3C4230xCFBA95990xB8BDA50F,
        
0x2802B89E0x5F0588080xC60CD9B20xB10BE924,
        
0x2F6F7C870x58684C110xC1611DAB0xB6662D3D,

        
0x76DC41900x01DB71060x98D220BC0xEFD5102A,
        
0x71B185890x06B6B51F0x9FBFE4A50xE8B8D433,
        
0x7807C9A20x0F00F9340x9609A88E0xE10E9818,
        
0x7F6A0DBB0x086D3D2D0x91646C970xE6635C01,
        
0x6B6B51F40x1C6C61620x856530D80xF262004E,
        
0x6C0695ED0x1B01A57B0x8208F4C10xF50FC457,
        
0x65B0D9C60x12B7E9500x8BBEB8EA0xFCB9887C,
        
0x62DD1DDF0x15DA2D490x8CD37CF30xFBD44C65,
        
0x4DB261580x3AB551CE0xA3BC00740xD4BB30E2,
        
0x4ADFA5410x3DD895D70xA4D1C46D0xD3D6F4FB,
        
0x4369E96A0x346ED9FC0xAD6788460xDA60B8D0,
        
0x44042D730x33031DE50xAA0A4C5F0xDD0D7CC9,
        
0x5005713C0x270241AA0xBE0B10100xC90C2086,
        
0x5768B5250x206F85B30xB966D4090xCE61E49F,
        
0x5EDEF90E0x29D9C9980xB0D098220xC7D7A8B4,
        
0x59B33D170x2EB40D810xB7BD5C3B0xC0BA6CAD,

        
0xEDB883200x9ABFB3B60x03B6E20C0x74B1D29A,
        
0xEAD547390x9DD277AF0x04DB26150x73DC1683,
        
0xE3630B120x94643B840x0D6D6A3E0x7A6A5AA8,
        
0xE40ECF0B0x9309FF9D0x0A00AE270x7D079EB1,
        
0xF00F93440x8708A3D20x1E01F2680x6906C2FE,
        
0xF762575D0x806567CB0x196C36710x6E6B06E7,
        
0xFED41B760x89D32BE00x10DA7A5A0x67DD4ACC,
        
0xF9B9DF6F0x8EBEEFF90x17B7BE430x60B08ED5,
        
0xD6D6A3E80xA1D1937E0x38D8C2C40x4FDFF252,
        
0xD1BB67F10xA6BC57670x3FB506DD0x48B2364B,
        
0xD80D2BDA0xAF0A1B4C0x36034AF60x41047A60,
        
0xDF60EFC30xA867DF550x316E8EEF0x4669BE79,
        
0xCB61B38C0xBC66831A0x256FD2A00x5268E236,
        
0xCC0C77950xBB0B47030x220216B90x5505262F,
        
0xC5BA3BBE0xB2BD0B280x2BB45A920x5CB36A04,
        
0xC2D7FFA70xB5D0CF310x2CD99E8B0x5BDEAE1D,

        
0x9B64C2B00xEC63F2260x756AA39C0x026D930A,
        
0x9C0906A90xEB0E363F0x720767850x05005713,
        
0x95BF4A820xE2B87A140x7BB12BAE0x0CB61B38,
        
0x92D28E9B0xE5D5BE0D0x7CDCEFB70x0BDBDF21,
        
0x86D3D2D40xF1D4E2420x68DDB3F80x1FDA836E,
        
0x81BE16CD0xF6B9265B0x6FB077E10x18B74777,
        
0x88085AE60xFF0F6A700x66063BCA0x11010B5C,
        
0x8F659EFF0xF862AE690x616BFFD30x166CCF45,
        
0xA00AE2780xD70DD2EE0x4E0483540x3903B3C2,
        
0xA76726610xD06016F70x4969474D0x3E6E77DB,
        
0xAED16A4A0xD9D65ADC0x40DF0B660x37D83BF0,
        
0xA9BCAE530xDEBB9EC50x47B2CF7F0x30B5FFE9,
        
0xBDBDF21C0xCABAC28A0x53B393300x24B4A3A6,
        
0xBAD036050xCDD706930x54DE57290x23D967BF,
        
0xB3667A2E0xC4614AB80x5D681B020x2A6F2B94,
        
0xB40BBE370xC30C8EA10x5A05DF1B0x2D02EF8D,
}
;

inline 
void CCrc32Static::CalcCrc32(const BYTE byte, DWORD &dwCrc32)
{
    dwCrc32 
= ((dwCrc32) >> 8^ s_arrdwCrc32Table[(byte^ ((dwCrc32) & 0x000000FF)];
}


DWORD CCrc32Static::StringCrc32(LPCTSTR szString, DWORD 
&dwCrc32)
{
    DWORD dwErrorCode 
= NO_ERROR;
    dwCrc32 
= 0xFFFFFFFF;
    
while(*szString != NULL)
    
{
        CalcCrc32((BYTE)
*szString, dwCrc32);
        szString
++;
    }

    dwCrc32 
= ~dwCrc32;
    
return 0;
}


DWORD CCrc32Static::FileCrc32Assembly(LPCTSTR szFilename, DWORD 
&dwCrc32)
{
    DWORD dwErrorCode 
= NO_ERROR;
    HANDLE hFile 
= NULL;
    dwCrc32 
= 0xFFFFFFFF;
    
try
    
{
        
// Open the file
        hFile = CreateFile(szFilename,
            GENERIC_READ,
            FILE_SHARE_READ,
            NULL,
            OPEN_EXISTING,
            FILE_ATTRIBUTE_ARCHIVE 
| FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_SEQUENTIAL_SCAN,
            NULL);
        
if(hFile == INVALID_HANDLE_VALUE)
            dwErrorCode 
= GetLastError();
        
else
        
{
            
// There is a bug in the Microsoft compilers where inline assembly
            
// code cannot access static member variables.  This is a work around
            
// for that bug.  For more info see Knowledge base article Q88092
            LPVOID ptrCrc32Table = &s_arrdwCrc32Table;

            BYTE buffer[MAX_BUFFER_SIZE];
            DWORD dwBytesRead;
            BOOL bSuccess 
= ReadFile(hFile, buffer, sizeof(buffer), &dwBytesRead, NULL);
            
while(bSuccess && dwBytesRead)
            
{
                
// Register use:
                
// eax - CRC32 value
                
// ebx - a lot of things
                
// ecx - CRC32 value
                
// edx - address of end of buffer
                
// esi - address of start of buffer
                
// edi - CRC32 table
                __asm
                
{
                    
// Save the esi and edi registers
                    push esi
                    push edi

                    mov eax, dwCrc32 
// Load the pointer to dwCrc32
                    mov ecx, [eax] // Dereference the pointer to load dwCrc32

                    mov edi, ptrCrc32Table 
// Load the CRC32 table

                    lea esi, buffer 
// Load buffer
                    mov ebx, dwBytesRead // Load dwBytesRead
                    lea edx, [esi + ebx] // Calculate the end of the buffer

                    crc32loop:
                    xor eax, eax 
// Clear the eax register
                    mov bl, byte ptr [esi] // Load the current source byte

                    mov al, cl 
// Copy crc value into eax
                    inc esi // Advance the source pointer

                    xor al, bl 
// Create the index into the CRC32 table
                    shr ecx, 8

                    mov ebx, [edi 
+ eax * 4// Get the value out of the table
                    xor ecx, ebx // xor with the current byte

                    cmp edx, esi 
// Have we reached the end of the buffer?
                    jne crc32loop

                    
// Restore the edi and esi registers
                    pop edi
                    pop esi

                    mov eax, dwCrc32 
// Load the pointer to dwCrc32
                    mov [eax], ecx // Write the result
                }

                bSuccess 
= ReadFile(hFile, buffer, sizeof(buffer), &dwBytesRead, NULL);
            }

        }

    }

    
catch(...)
    
{
        dwErrorCode 
= ERROR_CRC;        // An unknown exception happened
    }

    
if(hFile != NULL) CloseHandle(hFile);
    dwCrc32 
= ~dwCrc32;
    
return dwErrorCode;
}

 

原创粉丝点击