【问题标题】:CRC32 assembler function called from C console app从 C 控制台应用程序调用的 CRC32 汇编程序函数
【发布时间】:2013-11-09 11:56:35
【问题描述】:

我正在尝试从 C 代码中的外部文件调用 asm 函数。它构建得很好,但结果并不像它应该的那样。我看到的不是文件校验和,而是一些奇怪的字符。

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/stat.h>

    extern "C" unsigned long __stdcall CRC32(size_t sizeOfFile, char buffer[]);


    int fsize(char* file) {
        int size;
        FILE* fh;

        fopen_s(&fh, file, "rb" );
        if(fh != NULL){
            if( fseek(fh, 0, SEEK_END) ){
                fclose(fh);
                return -1;
            }

            size = ftell(fh);
            fclose(fh);
            return size;
        }

        return -1; //error
    }

    void calculateChecksum(char * filename, char * checksum){
        FILE *file = NULL;

        unsigned long crc32;


        char hex[10];
        fopen_s(&file, filename, "rb" );
        size_t size = fsize(filename);
        char *buffer=(char*)malloc(size);
        fread_s(buffer,size,size,1,file);
        crc32=CRC32(size,buffer);
        int n = sprintf_s(hex,"%x",crc32);

        for (int i=0;i<8;i++){
            checksum[i]=hex[i];
        }
        fclose(file);
        file = NULL;
    }




    int main(){
        char checksum[8];
        calculateChecksum("B:\\secretMessageC#.txt",checksum);

        char hex[10];

        for (int i=0;i<8;i++){
            checksum[i]=hex[i];
            printf("%c",checksum[i]);
        }

        getchar();
        return 0;
    }

我的外部汇编代码:

    .586
    .model flat, stdcall 
    .xmm
    .data
    .code
    CRC32 proc sizeOfFile:DWORD, file:DWORD
        push    esi
        push    ecx
        push    edx

        mov esi, file
        xor edx, edx
        or  eax, -1
        mov ecx, sizeOfFile

    CRC32_loop:
        mov dl, byte ptr [esi]
        xor dl, al
        shr eax, 8
        xor eax, dword ptr [crc32_table + 4*edx]
        inc esi
        dec ecx
        jnz CRC32_loop

        not eax

        pop edx
        pop ecx
        pop esi
        ret
            CRC32 endp
    crc32_table dd 000000000h, 077073096h, 0EE0E612Ch, 0990951BAh, 0076DC419h, 0706AF48Fh, 0E963A535h, 09E6495A3h, 00EDB8832h, 079DCB8A4h
                dd 0E0D5E91Eh, 097D2D988h, 009B64C2Bh, 07EB17CBDh, 0E7B82D07h, 090BF1D91h, 01DB71064h, 06AB020F2h, 0F3B97148h, 084BE41DEh
                dd 01ADAD47Dh, 06DDDE4EBh, 0F4D4B551h, 083D385C7h, 0136C9856h, 0646BA8C0h, 0FD62F97Ah, 08A65C9ECh, 014015C4Fh, 063066CD9h
                dd 0FA0F3D63h, 08D080DF5h, 03B6E20C8h, 04C69105Eh, 0D56041E4h, 0A2677172h, 03C03E4D1h, 04B04D447h, 0D20D85FDh, 0A50AB56Bh
                dd 035B5A8FAh, 042B2986Ch, 0DBBBC9D6h, 0ACBCF940h, 032D86CE3h, 045DF5C75h, 0DCD60DCFh, 0ABD13D59h, 026D930ACh, 051DE003Ah
                dd 0C8D75180h, 0BFD06116h, 021B4F4B5h, 056B3C423h, 0CFBA9599h, 0B8BDA50Fh, 02802B89Eh, 05F058808h, 0C60CD9B2h, 0B10BE924h
                dd 02F6F7C87h, 058684C11h, 0C1611DABh, 0B6662D3Dh, 076DC4190h, 001DB7106h, 098D220BCh, 0EFD5102Ah, 071B18589h, 006B6B51Fh
                dd 09FBFE4A5h, 0E8B8D433h, 07807C9A2h, 00F00F934h, 09609A88Eh, 0E10E9818h, 07F6A0DBBh, 0086D3D2Dh, 091646C97h, 0E6635C01h
                dd 06B6B51F4h, 01C6C6162h, 0856530D8h, 0F262004Eh, 06C0695EDh, 01B01A57Bh, 08208F4C1h, 0F50FC457h, 065B0D9C6h, 012B7E950h
                dd 08BBEB8EAh, 0FCB9887Ch, 062DD1DDFh, 015DA2D49h, 08CD37CF3h, 0FBD44C65h, 04DB26158h, 03AB551CEh, 0A3BC0074h, 0D4BB30E2h
                dd 04ADFA541h, 03DD895D7h, 0A4D1C46Dh, 0D3D6F4FBh, 04369E96Ah, 0346ED9FCh, 0AD678846h, 0DA60B8D0h, 044042D73h, 033031DE5h 
                dd 0AA0A4C5Fh, 0DD0D7CC9h, 05005713Ch, 0270241AAh, 0BE0B1010h, 0C90C2086h, 05768B525h, 0206F85B3h, 0B966D409h, 0CE61E49Fh
                dd 05EDEF90Eh, 029D9C998h, 0B0D09822h, 0C7D7A8B4h, 059B33D17h, 02EB40D81h, 0B7BD5C3Bh, 0C0BA6CADh, 0EDB88320h, 09ABFB3B6h
                dd 003B6E20Ch, 074B1D29Ah, 0EAD54739h, 09DD277AFh, 004DB2615h, 073DC1683h, 0E3630B12h, 094643B84h, 00D6D6A3Eh, 07A6A5AA8h 
                dd 0E40ECF0Bh, 09309FF9Dh, 00A00AE27h, 07D079EB1h, 0F00F9344h, 08708A3D2h, 01E01F268h, 06906C2FEh, 0F762575Dh, 0806567CBh
                dd 0196C3671h, 06E6B06E7h, 0FED41B76h, 089D32BE0h, 010DA7A5Ah, 067DD4ACCh, 0F9B9DF6Fh, 08EBEEFF9h, 017B7BE43h, 060B08ED5h
                dd 0D6D6A3E8h, 0A1D1937Eh, 038D8C2C4h, 04FDFF252h, 0D1BB67F1h, 0A6BC5767h, 03FB506DDh, 048B2364Bh, 0D80D2BDAh, 0AF0A1B4Ch
                dd 036034AF6h, 041047A60h, 0DF60EFC3h, 0A867DF55h, 0316E8EEFh, 04669BE79h, 0CB61B38Ch, 0BC66831Ah, 0256FD2A0h, 05268E236h
                dd 0CC0C7795h, 0BB0B4703h, 0220216B9h, 05505262Fh, 0C5BA3BBEh, 0B2BD0B28h, 02BB45A92h, 05CB36A04h, 0C2D7FFA7h, 0B5D0CF31h
                dd 02CD99E8Bh, 05BDEAE1Dh, 09B64C2B0h, 0EC63F226h, 0756AA39Ch, 0026D930Ah, 09C0906A9h, 0EB0E363Fh, 072076785h, 005005713h
                dd 095BF4A82h, 0E2B87A14h, 07BB12BAEh, 00CB61B38h, 092D28E9Bh, 0E5D5BE0Dh, 07CDCEFB7h, 00BDBDF21h, 086D3D2D4h, 0F1D4E242h 
                dd 068DDB3F8h, 01FDA836Eh, 081BE16CDh, 0F6B9265Bh, 06FB077E1h, 018B74777h, 088085AE6h, 0FF0F6A70h, 066063BCAh, 011010B5Ch
                dd 08F659EFFh, 0F862AE69h, 0616BFFD3h, 0166CCF45h, 0A00AE278h, 0D70DD2EEh, 04E048354h, 03903B3C2h, 0A7672661h, 0D06016F7h
                dd 04969474Dh, 03E6E77DBh, 0AED16A4Ah, 0D9D65ADCh, 040DF0B66h, 037D83BF0h, 0A9BCAE53h, 0DEBB9EC5h, 047B2CF7Fh, 030B5FFE9h
                dd 0BDBDF21Ch, 0CABAC28Ah, 053B39330h, 024B4A3A6h, 0BAD03605h, 0CDD70693h, 054DE5729h, 023D967BFh, 0B3667A2Eh, 0C4614AB8h
                dd 05D681B02h, 02A6F2B94h, 0B40BBE37h, 0C30C8EA1h, 05A05DF1Bh, 02D02EF8Dh   
    end

【问题讨论】:

  • 您犯了一个标准错误,即没有描述您期望发生的事情。 CRC32 的结果是字节,而不是字符。当字节碰巧没有映射到 ASCII 码时,它们看起来很有趣。他们很少这样做,几率只有四分之一。验证程序的一种简单方法是将得到的结果与已知良好的 CRC32 C 实现的结果进行比较,谷歌知道很多。如果不匹配,那么保留 C 实现是完成此项目的好方法。
  • 感谢汉斯的回复。我只是希望它使用十六进制系统打印文件的校验和,例如92e362f0 .
  • 那么不要使用 %c,使用 %x。
  • 我在 calculateChecksum 函数中使用 %x 将 long 转换为我的 char 数组。 %c 仅用于在 main 函数中打印 char 数组
  • C 字符串必须以零结尾,您忘记复制 0。

标签: c assembly x86


【解决方案1】:

您的 calculateChecksum 名称有点错误,而且工作方式也错误。

  • 您没有正确检查fread_s() 是否真的读取了所有请求的字节。 (也许我错了……)
  • 字符串后面缺少终止 NUL 字节。
  • 你没有free(buffer),所以你有内存泄漏。

如果满足这些条件,你就可以做

printf("%s", hex);

main() 函数中。

但是,你做的事情太复杂了。

我愿意

void calculateChecksum(char * filename, unsigned long * crc32){
    FILE *file;
    fopen_s(&file, filename, "rb");
    size_t size = fsize(filename);
    char *buffer = malloc(size);
    // TODO: If (!buffer) -> bail out.
    size_t td, crsr=0;
    do {
        rd = fread_s(buffer+crsr,size-crsr,size-crsr,1,file);
        if (rd > 0) crsr += rd;
    } while (rd > 0 && crsr < size)
    fclose(file);

    *crc32=CRC32(size,buffer);
    free(buffer);
}

这会将 CRC32 直接作为unsigned long 提供给调用者,可以使用printf("%08lx", crc32) 直接打印。

(顺便说一句,增强 CRC32() 以将 CRC 的初始值作为第三个参数可能会更好。在这种情况下,可以按块计算 CRC。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多