home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / zip21.zip / msdos / crc_i86.asm next >
Assembly Source File  |  1996-02-12  |  8KB  |  401 lines

  1. ; Not copyrighted by Christian Spieler, 11 Feb 1996.
  2. ;
  3.     TITLE   crc_i86.asm
  4.     NAME    crc_i86
  5. ;
  6. ; Optimized 8086 assembler version of the CRC32 calculation loop, intended
  7. ; for real mode Info-Zip programs (Zip 2.1, UnZip 5.2, and later versions).
  8. ; Supported compilers are Microsoft C (DOS real mode) and Borland C(++)
  9. ; (Turbo C). Watcom C (16bit) should also work.
  10. ; This module was inspired by a similar module for the Amiga (Paul Kienitz).
  11. ;
  12. ; It replaces the `ulg crc32(ulg c, char *s, extent n)' function
  13. ; in crc32.c.
  14. ;
  15. ; The code in this module should work with all kinds of C memory models
  16. ; (except Borland's __HUGE__ model), as long as the following
  17. ; restrictions are not violated:
  18. ;
  19. ; - The implementation assumes that the char buffer is confined to a
  20. ;   64k segment. The pointer `s' to the buffer must be in a format that
  21. ;   all bytes can be accessed by manipulating the offset part, only.
  22. ;   This means:
  23. ;   + no huge pointers
  24. ;   + char buffer size < 64 kByte
  25. ;
  26. ; - Since the buffer size argument `n' is of type `size_t' (= unsigned short)
  27. ;   for this routine, the char buffer size is limited to less than 64 kByte,
  28. ;   anyway. So, the assumption above should be easily fulfilled.
  29. ;
  30. ;==============================================================================
  31. ;
  32. ; Do NOT assemble this source if external crc32 routine from zlib gets used.
  33. ;
  34. ifndef USE_ZLIB
  35. ;
  36. ; Setup of amount of assemble time informational messages:
  37. ;
  38. ifdef     DEBUG
  39.   VERBOSE_INFO EQU 1
  40. else
  41.   ifdef _AS_MSG_
  42.     VERBOSE_INFO EQU 1
  43.   else
  44.     VERBOSE_INFO EQU 0
  45.   endif
  46. endif
  47. ;
  48. ; Selection of memory model, and initialization of memory model
  49. ; related macros:
  50. ;
  51. ifndef __SMALL__
  52.   ifndef __COMPACT__
  53.     ifndef __MEDIUM__
  54.       ifndef __LARGE__
  55.         ifndef __HUGE__
  56. ;         __SMALL__ EQU 1
  57.         endif
  58.       endif
  59.     endif
  60.   endif
  61. endif
  62.  
  63. ifdef __HUGE__
  64. ; .MODEL Huge
  65.    @CodeSize  EQU 1
  66.    @DataSize  EQU 1
  67.    Save_DS    EQU 1
  68.    if VERBOSE_INFO
  69.     if1
  70.       %out Assembling for C, Huge memory model
  71.     endif
  72.    endif
  73. else
  74.    ifdef __LARGE__
  75. ;      .MODEL Large
  76.       @CodeSize  EQU 1
  77.       @DataSize  EQU 1
  78.       if VERBOSE_INFO
  79.        if1
  80.          %out Assembling for C, Large memory model
  81.        endif
  82.       endif
  83.    else
  84.       ifdef __COMPACT__
  85. ;         .MODEL Compact
  86.          @CodeSize  EQU 0
  87.          @DataSize  EQU 1
  88.          if VERBOSE_INFO
  89.           if1
  90.             %out Assembling for C, Compact memory model
  91.           endif
  92.          endif
  93.       else
  94.          ifdef __MEDIUM__
  95. ;            .MODEL Medium
  96.             @CodeSize  EQU 1
  97.             @DataSize  EQU 0
  98.             if VERBOSE_INFO
  99.              if1
  100.                %out Assembling for C, Medium memory model
  101.              endif
  102.             endif
  103.          else
  104. ;            .MODEL Small
  105.             @CodeSize  EQU 0
  106.             @DataSize  EQU 0
  107.             if VERBOSE_INFO
  108.              if1
  109.                %out Assembling for C, Small memory model
  110.              endif
  111.             endif
  112.          endif
  113.       endif
  114.    endif
  115. endif
  116.  
  117. if @CodeSize
  118.     LCOD_OFS    EQU    2
  119. else
  120.     LCOD_OFS    EQU    0
  121. endif
  122.  
  123. IF @DataSize
  124.     LDAT_OFS    EQU    2
  125. else
  126.     LDAT_OFS    EQU    0
  127. endif
  128.  
  129. ifdef Save_DS
  130. ;            (di,si,ds)+(size, return address)
  131.     SAVE_REGS    EQU    6+(4+LCOD_OFS)
  132. else
  133. ;            (di,si)+(size, return address)
  134.     SAVE_REGS    EQU    4+(4+LCOD_OFS)
  135. endif
  136.  
  137. ;
  138. ; Selection of the supported CPU instruction set and initialization
  139. ; of CPU type related macros:
  140. ;
  141. ifdef __586
  142.     Use_286_code    EQU    1
  143.     Align_Size    EQU    16    ; paragraph alignment on Pentium
  144.         Alig_PARA    EQU    1    ; paragraph aligned code segment
  145. else
  146. ifdef __486
  147.     Use_286_code    EQU    1
  148.     Align_Size    EQU    4    ; dword alignment on 32 bit processors
  149.         Alig_PARA    EQU    1    ; paragraph aligned code segment
  150. else
  151. ifdef __386
  152.     Use_286_code    EQU    1
  153.     Align_Size    EQU    4    ; dword alignment on 32 bit processors
  154.         Alig_PARA    EQU    1    ; paragraph aligned code segment
  155. else
  156. ifdef __286
  157.     Use_286_code    EQU    1
  158.     Align_Size    EQU    2    ; word alignment on 16 bit processors
  159.         Alig_PARA    EQU    0    ; word aligned code segment
  160. else
  161. ifdef __186
  162.     Use_186_code    EQU    1
  163.     Align_Size    EQU    2    ; word alignment on 16 bit processors
  164.         Alig_PARA    EQU    0    ; word aligned code segment
  165. else
  166.     Align_Size    EQU    2    ; word alignment on 16 bit processors
  167.         Alig_PARA    EQU    0    ; word aligned code segment
  168. endif    ;?__186
  169. endif    ;?__286
  170. endif    ;?__386
  171. endif    ;?__486
  172. endif    ;?__586
  173.  
  174. ifdef Use_286_code
  175.     .286
  176.     Have_80x86    EQU    1
  177. else
  178. ifdef Use_186_code
  179.     .186
  180.     Have_80x86    EQU    1
  181. else
  182.     .8086
  183.     Have_80x86    EQU    0
  184. endif    ;?Use_186_code
  185. endif    ;?Use_286_code
  186.  
  187. ;
  188. ; Declare the segments used in this module:
  189. ;
  190. if @CodeSize
  191. if Alig_PARA
  192. CRC32_TEXT    SEGMENT  PARA PUBLIC 'CODE'
  193. else
  194. CRC32_TEXT    SEGMENT  WORD PUBLIC 'CODE'
  195. endif
  196. CRC32_TEXT    ENDS
  197. else    ;!@CodeSize
  198. if Alig_PARA
  199. _TEXT    SEGMENT  PARA PUBLIC 'CODE'
  200. else
  201. _TEXT    SEGMENT  WORD PUBLIC 'CODE'
  202. endif
  203. _TEXT    ENDS
  204. endif    ;?@CodeSize
  205. _DATA    SEGMENT  WORD PUBLIC 'DATA'
  206. _DATA    ENDS
  207. _BSS    SEGMENT  WORD PUBLIC 'BSS'
  208. _BSS    ENDS
  209. DGROUP    GROUP    _BSS, _DATA
  210. if @DataSize
  211.     ASSUME  DS: nothing, SS: DGROUP
  212. else
  213.     ASSUME  DS: DGROUP, SS: DGROUP
  214. endif
  215.  
  216. if @CodeSize
  217. EXTRN    _get_crc_table:FAR
  218. else
  219. EXTRN    _get_crc_table:NEAR
  220. endif
  221.  
  222.  
  223. Do_CRC    MACRO
  224.     mov    bl,al
  225. if @DataSize
  226.     xor    bl,BYTE PTR es:[di]
  227. else
  228.     xor    bl,BYTE PTR [di]
  229. endif
  230.     inc    di
  231.     sub    bh,bh
  232. if Have_80x86
  233.     shl    bx,2
  234. else
  235.     shl    bx,1
  236.     shl    bx,1
  237. endif
  238.     mov    al,ah
  239.     mov    ah,dl
  240.     mov    dl,dh
  241.     sub    dh,dh
  242.     xor    ax,WORD PTR [bx][si]
  243.     xor    dx,WORD PTR [bx+2][si]
  244.     ENDM
  245. ;
  246. Do_2    MACRO
  247.     Do_CRC
  248.     Do_CRC
  249.     ENDM
  250. Do_4    MACRO
  251.     Do_2
  252.     Do_2
  253.     ENDM
  254. ;
  255.  
  256. IF @CodeSize
  257. CRC32_TEXT    SEGMENT
  258.     ASSUME    CS: CRC32_TEXT
  259. else
  260. _TEXT    SEGMENT
  261.     ASSUME    CS: _TEXT
  262. endif
  263. ; Line 37
  264.  
  265. ;
  266. ;ulg crc32(ulg crc,
  267. ;    uch *buf,
  268. ;    extend len)
  269. ;
  270.     PUBLIC    _crc32
  271. if @CodeSize
  272. _crc32    PROC FAR
  273. else
  274. _crc32    PROC NEAR
  275. endif
  276. if Have_80x86
  277.     enter    WORD PTR 0,0
  278. else
  279.     push    bp
  280.     mov    bp,sp
  281. endif
  282.     push    di
  283.     push    si
  284. if @DataSize
  285. ;    crc = 4+LCOD_OFS    DWORD (unsigned long)
  286. ;    buf = 8+LCOD_OFS    DWORD PTR BYTE (uch *)
  287. ;    len = 12+LCOD_OFS    WORD (unsigned int)
  288. else
  289. ;    crc = 4+LCOD_OFS    DWORD (unsigned long)
  290. ;    buf = 8+LCOD_OFS    WORD PTR BYTE (uch *)
  291. ;    len = 10+LCOD_OFS    WORD (unsigned int)
  292. endif
  293. ;
  294. if @DataSize
  295.     mov    ax,WORD PTR [bp+8+LCOD_OFS]    ;buf
  296.     or    ax,WORD PTR [bp+10+LCOD_OFS]
  297. else
  298.     cmp    WORD PTR [bp+8+LCOD_OFS],0    ;buf
  299. endif
  300.     jne    crc_update
  301.     sub    ax,ax                ; crc = 0
  302.     cwd
  303. ifndef NO_UNROLLED_LOOPS
  304.     jmp    fine
  305. else
  306.     jmp    SHORT fine
  307. endif
  308. ;
  309. crc_update:
  310.     call    _get_crc_table
  311. ;  When used with compilers that conform to the Microsoft/Borland standard
  312. ;  C calling convention, model-dependent handling is not needed, because
  313. ;   _get_crc_table returns NEAR pointer.
  314. ;  But Watcom C is different and does not allow one to assume DS pointing to
  315. ;  DGROUP. So, we load DS with DGROUP, to be safe.
  316. ;if @DataSize
  317. ;    push    ds
  318. ;    mov    ds,dx
  319. ;    ASSUME    DS: nothing
  320. ;endif
  321.     mov    si,ax                ;crc_table
  322. if @DataSize
  323.     push    ds
  324.     mov    ax,SEG DGROUP
  325.     mov    ds,ax
  326.     ASSUME    DS: DGROUP
  327. endif
  328. ;
  329.     mov    ax,WORD PTR [bp+4+LCOD_OFS]    ;crc
  330.     mov    dx,WORD PTR [bp+6+LCOD_OFS]
  331.     not    ax
  332.     not    dx
  333. if @DataSize
  334.     les    di,DWORD PTR [bp+8+LCOD_OFS]    ;s
  335.     mov    cx,WORD PTR [bp+12+LCOD_OFS]    ;n
  336. else
  337.     mov    di,WORD PTR [bp+8+LCOD_OFS]    ;s
  338.     mov    cx,WORD PTR [bp+10+LCOD_OFS]    ;n
  339. endif
  340. ;
  341. ifndef NO_UNROLLED_LOOPS
  342. if Have_80x86
  343.     shr    cx,2
  344. else
  345.     shr    cx,1
  346.     shr    cx,1
  347. endif
  348.     jcxz    No_Fours
  349. ;
  350.     align    Align_Size        ; align destination of branch
  351. Next_Four:
  352.     Do_4
  353.     loop    Next_Four
  354. ;
  355. No_Fours:
  356. if @DataSize
  357.     mov    cx,WORD PTR [bp+12+LCOD_OFS]    ;n
  358. else
  359.     mov    cx,WORD PTR [bp+10+LCOD_OFS]    ;n
  360. endif
  361.     and    cx,00003H
  362. endif ; NO_UNROLLED_LOOPS
  363.     jcxz    done
  364. ;
  365.         align   Align_Size              ; align destination of branch
  366. Next_Byte:
  367.     Do_CRC
  368.     loop    Next_Byte
  369. ;
  370. done:
  371. if @DataSize
  372.     pop    ds
  373. ;    ASSUME    DS: DGROUP
  374.     ASSUME    DS: nothing
  375. endif
  376.     not    ax
  377.     not    dx
  378. ;
  379. fine:
  380.     pop    si
  381.     pop    di
  382. if Have_80x86
  383.     leave
  384. else
  385.     mov    sp,bp
  386.     pop    bp
  387. endif
  388.     ret
  389.  
  390. _crc32    ENDP
  391.  
  392. if @CodeSize
  393. CRC32_TEXT    ENDS
  394. else
  395. _TEXT    ENDS
  396. endif
  397. ;
  398. endif ;!USE_ZLIB
  399. ;
  400. END
  401.