📄 crc_i86.asm
字号:
; Not copyrighted by Christian Spieler, 02 Apr 1997.; TITLE crc_i86.asm NAME crc_i86;; Optimized 8086 assembler version of the CRC32 calculation loop, intended; for real mode Info-ZIP programs (Zip 2.1, UnZip 5.2, and later versions).; Supported compilers are Microsoft C (DOS real mode) and Borland C(++); (Turbo C). Watcom C (16bit) should also work.; This module was inspired by a similar module for the Amiga (Paul Kienitz).;; It replaces the `ulg crc32(ulg crc, ZCONST uch *buf, extent len)' function; in crc32.c.;; In March/April 1997, the code has been revised to incorporate Rodney Brown's; ideas for optimized access to the data buffer. For 8086 real mode code,; the data buffer is now accessed by aligned word-wide read operations.; This new optimization may be turned off by defining the macro switch; NO_16_BIT_LOADS.;; The code in this module should work with all kinds of C memory models; (except Borland's __HUGE__ model), as long as the following; restrictions are not violated:;; - The implementation assumes that the char buffer is confined to a; 64k segment. The pointer `s' to the buffer must be in a format that; all bytes can be accessed by manipulating the offset part, only.; This means:; + no huge pointers; + char buffer size < 64 kByte;; - Since the buffer size argument `n' is of type `size_t' (= unsigned short); for this routine, the char buffer size is limited to less than 64 kByte,; anyway. So, the assumption above should be easily fulfilled.;;==============================================================================;; Do NOT assemble this source if external crc32 routine from zlib gets used.;ifndef USE_ZLIB;; Setup of amount of assemble time informational messages:;ifdef DEBUG VERBOSE_INFO EQU 1else ifdef _AS_MSG_ VERBOSE_INFO EQU 1 else VERBOSE_INFO EQU 0 endifendif;; Selection of memory model, and initialization of memory model; related macros:;ifndef __SMALL__ ifndef __COMPACT__ ifndef __MEDIUM__ ifndef __LARGE__ ifndef __HUGE__; __SMALL__ EQU 1 endif endif endif endifendififdef __HUGE__; .MODEL Huge @CodeSize EQU 1 @DataSize EQU 1 Save_DS EQU 1 if VERBOSE_INFO if1 %out Assembling for C, Huge memory model endif endifelse ifdef __LARGE__; .MODEL Large @CodeSize EQU 1 @DataSize EQU 1 if VERBOSE_INFO if1 %out Assembling for C, Large memory model endif endif else ifdef __COMPACT__; .MODEL Compact @CodeSize EQU 0 @DataSize EQU 1 if VERBOSE_INFO if1 %out Assembling for C, Compact memory model endif endif else ifdef __MEDIUM__; .MODEL Medium @CodeSize EQU 1 @DataSize EQU 0 if VERBOSE_INFO if1 %out Assembling for C, Medium memory model endif endif else; .MODEL Small @CodeSize EQU 0 @DataSize EQU 0 if VERBOSE_INFO if1 %out Assembling for C, Small memory model endif endif endif endif endifendifif @CodeSize LCOD_OFS EQU 2else LCOD_OFS EQU 0endifIF @DataSize LDAT_OFS EQU 2else LDAT_OFS EQU 0endififdef Save_DS; (di,si,ds)+(size, return address) SAVE_REGS EQU 6+(4+LCOD_OFS)else; (di,si)+(size, return address) SAVE_REGS EQU 4+(4+LCOD_OFS)endif;; Selection of the supported CPU instruction set and initialization; of CPU type related macros:;ifdef __586 Use_286_code EQU 1 Align_Size EQU 16 ; paragraph alignment on Pentium Alig_PARA EQU 1 ; paragraph aligned code segmentelseifdef __486 Use_286_code EQU 1 Align_Size EQU 4 ; dword alignment on 32 bit processors Alig_PARA EQU 1 ; paragraph aligned code segmentelseifdef __386 Use_286_code EQU 1 Align_Size EQU 4 ; dword alignment on 32 bit processors Alig_PARA EQU 1 ; paragraph aligned code segmentelseifdef __286 Use_286_code EQU 1 Align_Size EQU 2 ; word alignment on 16 bit processors Alig_PARA EQU 0 ; word aligned code segmentelseifdef __186 Use_186_code EQU 1 Align_Size EQU 2 ; word alignment on 16 bit processors Alig_PARA EQU 0 ; word aligned code segmentelse Align_Size EQU 2 ; word alignment on 16 bit processors Alig_PARA EQU 0 ; word aligned code segmentendif ;?__186endif ;?__286endif ;?__386endif ;?__486endif ;?__586ifdef Use_286_code .286 Have_80x86 EQU 1elseifdef Use_186_code .186 Have_80x86 EQU 1else .8086 Have_80x86 EQU 0endif ;?Use_186_codeendif ;?Use_286_code;; Declare the segments used in this module:;if @CodeSizeif Alig_PARACRC32_TEXT SEGMENT PARA PUBLIC 'CODE'elseCRC32_TEXT SEGMENT WORD PUBLIC 'CODE'endifCRC32_TEXT ENDSelse ;!@CodeSizeif Alig_PARA_TEXT SEGMENT PARA PUBLIC 'CODE'else_TEXT SEGMENT WORD PUBLIC 'CODE'endif_TEXT ENDSendif ;?@CodeSize_DATA SEGMENT WORD PUBLIC 'DATA'_DATA ENDS_BSS SEGMENT WORD PUBLIC 'BSS'_BSS ENDSDGROUP GROUP _BSS, _DATAif @DataSize ASSUME DS: nothing, SS: DGROUPelse ASSUME DS: DGROUP, SS: DGROUPendifif @CodeSizeEXTRN _get_crc_table:FARelseEXTRN _get_crc_table:NEARendifDo_CRC MACRO mov bl,al sub bh,bhif Have_80x86 shl bx,2else shl bx,1 shl bx,1endif mov al,ah mov ah,dl mov dl,dh sub dh,dh xor ax,WORD PTR [bx][si] xor dx,WORD PTR [bx+2][si] ENDM;Do_1 MACROif @DataSize xor al,BYTE PTR es:[di]else xor al,BYTE PTR [di]endif inc di Do_CRC ENDM;Do_2 MACROifndef NO_16_BIT_LOADSif @DataSize xor ax,WORD PTR es:[di]else xor ax,WORD PTR [di]endif add di,2 Do_CRC Do_CRCelse Do_1 Do_1endif ENDM;Do_4 MACRO Do_2 Do_2 ENDM;IF @CodeSizeCRC32_TEXT SEGMENT ASSUME CS: CRC32_TEXTelse_TEXT SEGMENT ASSUME CS: _TEXTendif; Line 37;;ulg crc32(ulg crc,; ZCONST uch *buf,; extend len); PUBLIC _crc32if @CodeSize_crc32 PROC FARelse_crc32 PROC NEARendifif Have_80x86 enter WORD PTR 0,0else push bp mov bp,spendif push di push siif @DataSize; crc = 4+LCOD_OFS DWORD (unsigned long); buf = 8+LCOD_OFS DWORD PTR BYTE (uch *); len = 12+LCOD_OFS WORD (unsigned int)else; crc = 4+LCOD_OFS DWORD (unsigned long); buf = 8+LCOD_OFS WORD PTR BYTE (uch *); len = 10+LCOD_OFS WORD (unsigned int)endif;if @DataSize mov ax,WORD PTR [bp+8+LCOD_OFS] ; buf or ax,WORD PTR [bp+10+LCOD_OFS] ; == NULL ?else cmp WORD PTR [bp+8+LCOD_OFS],0 ; buf == NULL ?endif jne crc_update sub ax,ax ; crc = 0 cwdifndef NO_UNROLLED_LOOPS jmp fineelse jmp SHORT fineendif;crc_update: call _get_crc_table; When used with compilers that conform to the Microsoft/Borland standard; C calling convention, model-dependent handling is not needed, because; _get_crc_table returns NEAR pointer.; But Watcom C is different and does not allow one to assume DS pointing to; DGROUP. So, we load DS with DGROUP, to be safe.;if @DataSize; push ds; mov ds,dx; ASSUME DS: nothing;endif mov si,ax ;crc_tableif @DataSize push ds mov ax,SEG DGROUP mov ds,ax ASSUME DS: DGROUPendif; mov ax,WORD PTR [bp+4+LCOD_OFS] ;crc mov dx,WORD PTR [bp+6+LCOD_OFS] not ax not dxif @DataSize les di,DWORD PTR [bp+8+LCOD_OFS] ;buf mov cx,WORD PTR [bp+12+LCOD_OFS] ;lenelse mov di,WORD PTR [bp+8+LCOD_OFS] ;buf mov cx,WORD PTR [bp+10+LCOD_OFS] ;lenendif;ifndef NO_UNROLLED_LOOPSifndef NO_16_BIT_LOADS test cx,cx jnz start jmp donestart: test di,1 jz is_wordaligned dec cx Do_1 mov WORD PTR [bp+10+LDAT_OFS+LCOD_OFS],cxis_wordaligned:endif ; !NO_16_BIT_LOADSif Have_80x86 shr cx,2else shr cx,1 shr cx,1endif jcxz No_Fours; align Align_Size ; align destination of branchNext_Four: Do_4 loop Next_Four;No_Fours:if @DataSize mov cx,WORD PTR [bp+12+LCOD_OFS] ;lenelse mov cx,WORD PTR [bp+10+LCOD_OFS] ;lenendif and cx,00003Hendif ; !NO_UNROLLED_LOOPS jcxz done; align Align_Size ; align destination of branchNext_Byte: Do_1 loop Next_Byte;done:if @DataSize pop ds; ASSUME DS: DGROUP ASSUME DS: nothingendif not ax not dx;fine: pop si pop diif Have_80x86 leaveelse mov sp,bp pop bpendif ret_crc32 ENDPif @CodeSizeCRC32_TEXT ENDSelse_TEXT ENDSendif;endif ;!USE_ZLIB;END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -