Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

201 lines
7.7 KiB

  1. title "Compute Checksum"
  2. ;/*++
  3. ;
  4. ; Copyright (c) 2001 Microsoft Corporation
  5. ;
  6. ; Module Name:
  7. ;
  8. ; chksum.asm
  9. ;
  10. ; Abstract:
  11. ;
  12. ; This module implements a fucntion to compute the checksum of a buffer.
  13. ;
  14. ; Author:
  15. ;
  16. ; David N. Cutler (davec) 25-Jan-2001
  17. ;
  18. ; Environment:
  19. ;
  20. ; Any mode.
  21. ;
  22. ; Revision History:
  23. ;
  24. ;--*/
  25. include ksamd64.inc
  26. subttl "Checksum"
  27. ;++
  28. ;
  29. ; USHORT
  30. ; ChkSum(
  31. ; IN ULONG cksum,
  32. ; IN PUSHORT buf,
  33. ; IN ULONG len
  34. ; )
  35. ;
  36. ; Routine Description:
  37. ;
  38. ; This function computes the checksum of the specified buffer.
  39. ;
  40. ; Arguments:
  41. ;
  42. ; cksum (ecx) - Suppiles the initial checksum value.
  43. ;
  44. ; buf (rdx) - Supplies a pointer to the buffer that is checksumed.
  45. ;
  46. ; len (r8d) - Supplies the of the buffer in words.
  47. ;
  48. ; Return Value:
  49. ;
  50. ; The computed checksum is returned as the function value.
  51. ;
  52. ;--
  53. LEAF_ENTRY ChkSum, _TEXT$00
  54. mov eax, ecx ; set initial checksum value
  55. mov ecx, r8d ; set length of buffer in words
  56. shl ecx, 1 ; convert to length in bytes
  57. jz cks80 ; if z, no words to checksum
  58. ;
  59. ; Compute checksum in cascading order of block size until 128 byte blocks
  60. ; are all that is left, then loop on 128-byte blocks.
  61. ;
  62. test rdx, 02h ; check if source dword aligned
  63. jz short cks10 ; if z, source is dword aligned
  64. xor r8, r8 ; get initial word for alignment
  65. mov r8w, [rdx] ;
  66. add eax, r8d ; update partial checkcum
  67. adc eax, 0 ; add carry
  68. add rdx, 2 ; update source address
  69. sub ecx, 2 ; reduce length in bytes
  70. cks10: mov r8d, ecx ; isolate residual bytes
  71. and r8d, 07h ;
  72. sub ecx, r8d ; subtract residual bytes
  73. jz cks60 ; if z, no 8-byte blocks
  74. test ecx, 08h ; test if initial 8-byte block
  75. jz short cks20 ; if z, no initial 8-byte block
  76. add eax, [rdx] ; compute 8-byte checksum
  77. adc eax, 4[rdx] ;
  78. adc eax, 0 ; add carry
  79. add rdx, 8 ; update source address
  80. sub ecx, 8 ; reduce length of checksum
  81. jz cks60 ; if z, end of 8-byte blocks
  82. cks20: test ecx, 010h ; test if initial 16-byte block
  83. jz short cks30 ; if z, no initial 16-byte block
  84. add eax, [rdx] ; compute 16-byte checksum
  85. adc eax, 4[rdx] ;
  86. adc eax, 8[rdx] ;
  87. adc eax, 12[rdx] ;
  88. adc eax, 0 ; add carry
  89. add rdx, 16 ; update source address
  90. sub ecx, 16 ; reduce length of checksum
  91. jz cks60 ; if z, end of 8-byte blocks
  92. cks30: test ecx, 020h ; test if initial 32-byte block
  93. jz short cks40 ; if z set, no initial 32-byte block
  94. add eax, [rdx] ; compute 32-byte checksum
  95. adc eax, 4[rdx] ;
  96. adc eax, 8[rdx] ;
  97. adc eax, 12[rdx] ;
  98. adc eax, 16[rdx] ;
  99. adc eax, 20[rdx] ;
  100. adc eax, 24[rdx] ;
  101. adc eax, 28[rdx] ;
  102. adc eax, 0 ; add carry
  103. add rdx, 32 ; update source address
  104. sub ecx, 32 ; reduce length of checksum
  105. jz cks60 ; if z, end of 8-byte blocks
  106. cks40: test ecx, 040h ; test if initial 64-byte block
  107. jz cks50 ; if z, no initial 64-byte block
  108. add eax, [rdx] ; compute 64-byte checksum
  109. adc eax, 4[rdx] ;
  110. adc eax, 8[rdx] ;
  111. adc eax, 12[rdx] ;
  112. adc eax, 16[rdx] ;
  113. adc eax, 20[rdx] ;
  114. adc eax, 24[rdx] ;
  115. adc eax, 28[rdx] ;
  116. adc eax, 32[rdx] ;
  117. adc eax, 36[rdx] ;
  118. adc eax, 40[rdx] ;
  119. adc eax, 44[rdx] ;
  120. adc eax, 48[rdx] ;
  121. adc eax, 52[rdx] ;
  122. adc eax, 56[rdx] ;
  123. adc eax, 60[rdx] ;
  124. adc eax, 0 ; add carry
  125. add rdx, 64 ; update source address
  126. sub ecx, 64 ; reduce length of checksum
  127. jz cks60 ; if z, end of 8-byte blocks
  128. cks50: add eax, [rdx] ; compute 128-byte checksum
  129. adc eax, 4[rdx] ;
  130. adc eax, 8[rdx] ;
  131. adc eax, 12[rdx] ;
  132. adc eax, 16[rdx] ;
  133. adc eax, 20[rdx] ;
  134. adc eax, 24[rdx] ;
  135. adc eax, 28[rdx] ;
  136. adc eax, 32[rdx] ;
  137. adc eax, 36[rdx] ;
  138. adc eax, 40[rdx] ;
  139. adc eax, 44[rdx] ;
  140. adc eax, 48[rdx] ;
  141. adc eax, 52[rdx] ;
  142. adc eax, 56[rdx] ;
  143. adc eax, 60[rdx] ;
  144. adc eax, 64[rdx] ;
  145. adc eax, 68[rdx] ;
  146. adc eax, 72[rdx] ;
  147. adc eax, 76[rdx] ;
  148. adc eax, 80[rdx] ;
  149. adc eax, 84[rdx] ;
  150. adc eax, 88[rdx] ;
  151. adc eax, 92[rdx] ;
  152. adc eax, 96[rdx] ;
  153. adc eax, 100[rdx] ;
  154. adc eax, 104[rdx] ;
  155. adc eax, 108[rdx] ;
  156. adc eax, 112[rdx] ;
  157. adc eax, 116[rdx] ;
  158. adc eax, 120[rdx] ;
  159. adc eax, 124[rdx] ;
  160. adc eax, 0 ; add carry
  161. add rdx, 128 ; update source address
  162. sub ecx, 128 ; reduce length of checksum
  163. jnz short cks50 ; if nz, not end of 8-byte blocks
  164. ;
  165. ; Compute checksum on 2-byte blocks.
  166. ;
  167. cks60: test r8d, r8d ; check if any 2-byte blocks
  168. jz short cks80 ; if z, no 2-byte blocks
  169. xor ecx, ecx ; clear entire register
  170. cks70: mov cx, [rdx] ; load 2-byte block
  171. add eax, ecx ; compute 2-byte checksum
  172. adc eax, 0 ;
  173. add rdx, 2 ; update source address
  174. sub r8d, 2 ; reduce length of checksum
  175. jnz short cks70 ; if nz, more 2-bytes blocks
  176. ;
  177. ; Fold 32-but checksum into 16-bits
  178. ;
  179. cks80: mov edx, eax ; copy checksum value
  180. shr edx, 16 ; isolate high order bits
  181. and eax, 0ffffh ; isolate low order bits
  182. add eax, edx ; sum high and low order bits
  183. mov edx, eax ; isolate possible carry
  184. shr edx, 16 ;
  185. add eax, edx ; add carry
  186. and eax, 0ffffh ; clear possible carry bit
  187. ret ;
  188. LEAF_END ChkSum, _TEXT$00
  189. end