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.

248 lines
4.8 KiB

  1. ; mem.asm:
  2. ;
  3. ; masm -Mx -Zi -DSEGNAME=????? asm.asm
  4. ;
  5. TITLE MEM.ASM
  6. ;****************************************************************
  7. ;* MEM.ASM - Assembly mem-copy routines *
  8. ;* for 80286 and 80386 *
  9. ;****************************************************************
  10. ;
  11. ?PLM=1 ; PASCAL Calling convention is DEFAULT
  12. ?WIN=0 ; Windows calling convention
  13. .xlist
  14. include cmacros.inc
  15. include windows.inc
  16. .list
  17. externA __WinFlags ; in KERNEL
  18. externA __AHINCR ; in KERNEL
  19. externA __AHSHIFT ; in KERNEL
  20. ; The following structure should be used to access high and low
  21. ; words of a DWORD. This means that "word ptr foo[2]" -> "foo.hi".
  22. LONG struc
  23. lo dw ?
  24. hi dw ?
  25. LONG ends
  26. FARPOINTER struc
  27. off dw ?
  28. sel dw ?
  29. FARPOINTER ends
  30. ; -------------------------------------------------------
  31. ; DATA SEGMENT DECLARATIONS
  32. ; -------------------------------------------------------
  33. ifndef SEGNAME
  34. SEGNAME equ <_TEXT>
  35. endif
  36. createSeg %SEGNAME, CodeSeg, word, public, CODE
  37. sBegin Data
  38. sEnd Data
  39. sBegin CodeSeg
  40. assumes cs,CodeSeg
  41. assumes ds,DATA
  42. cProc fstrrchr,<NEAR,PASCAL,PUBLIC,NODATA>,<di>
  43. ParmD lsz
  44. ParmB c
  45. cBegin
  46. les di, lsz
  47. xor al, al ; Search for terminating NULL
  48. mov cx, -1 ; Search forever
  49. cld ; Moving forward
  50. repne scasb ; Look for the NULL
  51. not cx ; Negative value minus 1 gives length
  52. dec cx ; CX is always incremented
  53. jcxz fstrrchr_fail ; Zero length string fails
  54. dec di ; DI is one past character found
  55. dec di ; Back up to last character in string
  56. mov al, c ; Get character to search for
  57. std ; Moving backwards
  58. repne scasb ; Look for the character
  59. cld ; Reset direction
  60. jne fstrrchr_fail ; Fail if not found
  61. inc di ; Back up to actual character found
  62. mov ax, di ; Return pointer to that character
  63. mov dx, es
  64. jmp fstrrchr_exit
  65. fstrrchr_fail:
  66. xor ax, ax ; Return NULL on failure
  67. cwd
  68. fstrrchr_exit:
  69. cEnd
  70. ;---------------------------Public-Routine------------------------------;
  71. ; MemCopy
  72. ;
  73. ; copy memory, dons *not* handle overlaped copies.
  74. ;
  75. ; Entry:
  76. ; lpSrc HPSTR to copy from
  77. ; lpDst HPSTR to copy to
  78. ; cbMem DWORD count of bytes to move
  79. ;
  80. ; Returns:
  81. ; destination pointer
  82. ; Error Returns:
  83. ; None
  84. ; Registers Preserved:
  85. ; BP,DS,SI,DI
  86. ; Registers Destroyed:
  87. ; AX,BX,CX,DX,FLAGS
  88. ; Calls:
  89. ; nothing
  90. ; History:
  91. ;
  92. ; Wed 04-Jan-1990 13:45:58 -by- Todd Laney [ToddLa]
  93. ; Created.
  94. ; Tue 16-Oct-1990 16:41:00 -by- David Maymudes [DavidMay]
  95. ; Modified 286 case to work correctly with cbMem >= 64K.
  96. ; Changed name to hmemcpy.
  97. ; Changed 386 case to copy by longwords
  98. ;-----------------------------------------------------------------------;
  99. cProc MemCopy,<NEAR,PASCAL,PUBLIC,NODATA>,<>
  100. ; ParmD lpDst
  101. ; ParmD lpSrc
  102. ; ParmD cbMem
  103. cBegin <nogen>
  104. mov ax,__WinFlags
  105. test ax,WF_CPU286
  106. jz MemCopy386
  107. jmp NEAR PTR MemCopy286
  108. cEnd <nogen>
  109. cProc MemCopy386,<NEAR,PASCAL,PUBLIC,NODATA>,<ds>
  110. ParmD lpDst
  111. ParmD lpSrc
  112. ParmD cbMem
  113. cBegin
  114. .386
  115. push edi
  116. push esi
  117. cld
  118. mov ecx,cbMem
  119. jecxz mc386_exit
  120. movzx edi,di
  121. movzx esi,si
  122. lds si,lpSrc
  123. les di,lpDst
  124. push ecx
  125. shr ecx,2 ; get count in DWORDs
  126. rep movs dword ptr es:[edi], dword ptr ds:[esi]
  127. db 67H
  128. pop ecx
  129. and ecx,3
  130. rep movs byte ptr es:[edi], byte ptr ds:[esi]
  131. db 67H
  132. nop
  133. mc386_exit:
  134. cld
  135. pop esi
  136. pop edi
  137. mov dx,lpDst.sel ; return destination address
  138. mov ax,lpDst.off
  139. .286
  140. cEnd
  141. cProc MemCopy286,<NEAR,PASCAL,PUBLIC,NODATA>,<ds,si,di>
  142. ParmD lpDst
  143. ParmD lpSrc
  144. ParmD cbMem
  145. cBegin
  146. mov cx,cbMem.lo ; CX holds count
  147. or cx,cbMem.hi ; or with high word
  148. jnz @f
  149. jmp empty_copy
  150. @@:
  151. lds si,lpSrc ; DS:SI = src
  152. les di,lpDst ; ES:DI = dst
  153. next:
  154. mov ax,cx
  155. dec ax
  156. mov ax,di
  157. not ax ; AX = 65535-DI
  158. mov dx,si
  159. not dx ; DX = 65535-SI
  160. sub ax,dx
  161. sbb bx,bx
  162. and ax,bx
  163. add ax,dx ; AX = MIN(AX,DX) = MIN(65535-SI,65535-DI)
  164. ; problem: ax might have wrapped to zero
  165. test cbMem.hi,-1
  166. jnz plentytogo ; at least 64k still to copy
  167. dec cx ; this is ok, since high word is zero
  168. sub ax,cx
  169. sbb bx,bx
  170. and ax,bx
  171. add ax,cx ; AX = MIN(AX,CX)
  172. inc cx
  173. plentytogo:
  174. xor bx,bx
  175. add ax,1 ; AX = Num = MIN(count,65536-SI,65536-DI)
  176. ; we must check the carry here!
  177. adc bx,0 ; BX could be 1 here, if CX==0 indicating
  178. ; exactly 64k to copy
  179. xchg ax,cx
  180. sub ax,cx ; Count -= Num
  181. sbb cbMem.hi,bx
  182. shr bx,1
  183. rcr cx,1 ; if bx==1, then cx ends up 0x8000
  184. rep movsw
  185. jnc @f
  186. movsb ; move last byte, if necessary
  187. @@:
  188. mov cx,ax ; put low word of count back in cx
  189. or ax,cbMem.hi
  190. jz done ; If Count == 0 Then BREAK
  191. or si,si ; if SI wraps, update DS
  192. jnz @f
  193. ;
  194. mov ax,ds
  195. add ax,__AHINCR
  196. mov ds,ax ; update DS if appropriate
  197. @@:
  198. or di,di ; if DI wraps, update ES
  199. jnz next
  200. ;
  201. mov ax,es
  202. add ax,__AHINCR
  203. mov es,ax ; update ES if appropriate
  204. jmp next
  205. ;
  206. ; Restore registers and return
  207. ;
  208. done:
  209. empty_copy:
  210. mov dx,lpDst.sel ; return destination address
  211. mov ax,lpDst.off
  212. cEnd
  213. sEnd
  214. sEnd CodeSeg
  215. end