?? crc_i86.asm
字號:
;===========================================================================; Copyright (c) 1990-2001 Info-ZIP. All rights reserved.;; See the accompanying file LICENSE, version 2000-Apr-09 or later; (the contents of which are also included in zip.h) for terms of use.; If, for some reason, all these files are missing, the Info-ZIP license; also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html;===========================================================================; Created by Christian Spieler, last modified 24 Dec 1998.; 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.;; In December 1998, the loop branch commands were changed from "loop dest"; into "dec cx; jnz dest". On modern systems (486 and newer), the latter; code is usually much faster (e.g. 1 clock cycle compared to 5 for "loop"; on Pentium MMX). For the 286, the penalty of "dec cx; jnz" is one clock; cycle (12 vs. 11 cycles); on an 8088 the cycle counts are 22 (dec cx; jnz); vs. 18 (loop). I decided to optimize for newer CPU models by default, because; I expect that old 80286 or 8088 dinosaurier machines may be rarely used; nowadays. In case you want optimum performance for these old CPU models; you should define the OPTIMIZE_286_88 macro switch on the assembler's; command line.; Likewise, "jcxz" was replaced by "jz", because the latter is faster on; 486 and newer CPUs (without any penalty on 80286 and older CPU models).;; 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 4 ; dword 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,; extent 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 jz No_Fours; align Align_Size ; align destination of branchNext_Four: Do_4ifndef OPTIMIZE_286_88 dec cx ; on 286, "loop Next_Four" needs 11 jnz Next_Four ; clocks, one less than this codeelse loop Next_Fourendif;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 jz done; align Align_Size ; align destination of branchNext_Byte: Do_1ifndef OPTIMIZE_286_88 dec cx ; on 286, "loop Next_Four" needs 11 jnz Next_Byte ; clocks, one less than this codeelse loop Next_Fourendif;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
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -