Leaked source code of windows server 2003
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.

413 lines
8.2 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. PMODE=1
  14. .xlist
  15. include cmacros.inc
  16. include windows.inc
  17. .list
  18. externA __WinFlags ; in KERNEL
  19. externA __AHINCR ; in KERNEL
  20. externA __AHSHIFT ; in KERNEL
  21. ; The following structure should be used to access high and low
  22. ; words of a DWORD. This means that "word ptr foo[2]" -> "foo.hi".
  23. LONG struc
  24. lo dw ?
  25. hi dw ?
  26. LONG ends
  27. FARPOINTER struc
  28. off dw ?
  29. sel dw ?
  30. FARPOINTER ends
  31. ; -------------------------------------------------------
  32. ; DATA SEGMENT DECLARATIONS
  33. ; -------------------------------------------------------
  34. ifndef SEGNAME
  35. SEGNAME equ <_TEXT>
  36. endif
  37. createSeg %SEGNAME, CodeSeg, word, public, CODE
  38. sBegin Data
  39. sEnd Data
  40. sBegin CodeSeg
  41. assumes cs,CodeSeg
  42. assumes ds,DATA
  43. ;---------------------------Public-Routine------------------------------;
  44. ; hmemcpy
  45. ;
  46. ; copy memory
  47. ;
  48. ; Entry:
  49. ; lpSrc HPSTR to copy from
  50. ; lpDst HPSTR to copy to
  51. ; cbMem DWORD count of bytes to move
  52. ;
  53. ; NOTE: overlapped copies will work iff lpSrc.sel == lpDst.sel
  54. ; [This is a lie. They will always work.]
  55. ;
  56. ; Returns:
  57. ; destination pointer
  58. ; Error Returns:
  59. ; None
  60. ; Registers Preserved:
  61. ; BP,DS,SI,DI
  62. ; Registers Destroyed:
  63. ; AX,BX,CX,DX,FLAGS
  64. ; Calls:
  65. ; nothing
  66. ; History:
  67. ;
  68. ; Wed 04-Jan-1990 13:45:58 -by- Todd Laney [ToddLa]
  69. ; Created.
  70. ; Tue 16-Oct-1990 16:41:00 -by- David Maymudes [DavidMay]
  71. ; Modified 286 case to work correctly with cbMem >= 64K.
  72. ; Changed name to hmemcpy.
  73. ; Changed 386 case to copy by longwords
  74. ;-----------------------------------------------------------------------;
  75. cProc MemCopy,<FAR,PASCAL,PUBLIC,NODATA>,<>
  76. ; ParmD lpDst
  77. ; ParmD lpSrc
  78. ; ParmD cbMem
  79. cBegin <nogen>
  80. mov ax,__WinFlags
  81. test ax,WF_CPU286
  82. jz fmemcpy386
  83. jmp FAR PTR fmemcpy286
  84. cEnd <nogen>
  85. cProc fmemcpy386,<FAR,PASCAL,PUBLIC,NODATA>,<ds>
  86. ParmD lpDst
  87. ParmD lpSrc
  88. ParmD cbMem
  89. cBegin
  90. .386
  91. push edi
  92. push esi
  93. cld
  94. mov ecx,cbMem
  95. jecxz mc386_exit
  96. movzx edi,di
  97. movzx esi,si
  98. lds si,lpSrc
  99. les di,lpDst
  100. ;
  101. ; calculate differance of pointers in "selector" space
  102. ;
  103. mov ax,si ; DX:AX = lpSrc
  104. mov dx,ds
  105. mov bx,es ; BX = selector of ptr B
  106. mov cx,__AHSHIFT ; number of selector bits per 64K 'segment'
  107. shr dx,cl ; linearize ptr A
  108. shr bx,cl ; linearize ptr B
  109. ;
  110. ; DX and BX contain normalized selectors
  111. ;
  112. mov ecx,cbMem
  113. sub ax,di
  114. sbb dx,bx ; do long subtraction.
  115. jnc mc_copy_forward
  116. add ax,cx
  117. adc dx,cbMem.hi
  118. jnc mc_copy_forward ; carry, so >0, thus they do hit.
  119. std
  120. add edi,ecx
  121. add esi,ecx
  122. sub edi,4
  123. sub esi,4
  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 ; Fix strange 386 bug
  128. add edi,3
  129. add esi,3
  130. pop ecx
  131. and ecx,3
  132. rep movs byte ptr es:[edi], byte ptr ds:[esi]
  133. db 67H ; Fix strange 386 bug
  134. jmp mc386_exit
  135. mc_copy_forward:
  136. push ecx
  137. shr ecx,2 ; get count in DWORDs
  138. rep movs dword ptr es:[edi], dword ptr ds:[esi]
  139. db 67H
  140. pop ecx
  141. and ecx,3
  142. rep movs byte ptr es:[edi], byte ptr ds:[esi]
  143. db 67H
  144. nop
  145. mc386_exit:
  146. cld
  147. pop esi
  148. pop edi
  149. mov dx,lpDst.sel ; return destination address
  150. mov ax,lpDst.off
  151. .286
  152. cEnd
  153. cProc fmemcpy286,<FAR,PASCAL,PUBLIC,NODATA>,<ds,si,di>
  154. ParmD lpDst
  155. ParmD lpSrc
  156. ParmD cbMem
  157. cBegin
  158. mov cx,cbMem.lo ; CX holds count
  159. or cx,cbMem.hi ; or with high word
  160. jnz @f
  161. jmp empty_copy
  162. @@:
  163. lds si,lpSrc ; DS:SI = src
  164. les di,lpDst ; ES:DI = dst
  165. ;
  166. ; calculate differance of pointers in "selector" space
  167. ;
  168. mov ax,si ; DX:AX = lpSrc
  169. mov dx,ds
  170. mov bx,es ; BX = selector of ptr B
  171. mov cx,__AHSHIFT ; number of selector bits per 64K 'segment'
  172. shr dx,cl ; linearize ptr A
  173. shr bx,cl ; linearize ptr B
  174. ;
  175. ; DX and BX contain normalized selectors
  176. ;
  177. mov cx,cbMem.lo
  178. sub ax,di
  179. sbb dx,bx ; do long subtraction.
  180. jnc forward_copy ; difference is positive, so copy forward
  181. ; see if the blocks intersect: is source + count > dest?
  182. ; equivalently, is source-dest + count > 0 ?
  183. ; sub ax,cx
  184. ; sbb dx,0
  185. ; jnc next ; This looks wrong. Recheck!
  186. add ax,cx
  187. adc dx,cbMem.hi
  188. jc reverse_copy ; carry, so >0, thus they do hit.
  189. forward_copy:
  190. jmp next
  191. reverse_copy:
  192. ; first, we have to set ds:si and es:di to the _ends_ of the blocks
  193. sub cx,1
  194. sbb cbMem.hi,0 ; subtract 2 from (long) count
  195. xor ax,ax
  196. add si,cx
  197. adc ax,cbMem.hi
  198. push cx
  199. mov cx,__AHSHIFT
  200. shl ax,cl
  201. pop cx
  202. mov bx,ds
  203. add ax,bx ; advance DS
  204. mov ds,ax
  205. xor ax,ax
  206. add di,cx
  207. adc ax,cbMem.hi
  208. push cx
  209. mov cx,__AHSHIFT
  210. shl ax,cl
  211. pop cx
  212. mov bx,es
  213. add ax,bx ; advance ES
  214. mov es,ax
  215. add cx,1
  216. adc cbMem.hi,0 ; restore count
  217. ;
  218. ; DS:SI += Count
  219. ; ES:DI += Count
  220. ; While Count != 0 Do
  221. ; Num = MIN(Count,SI+1,DI+1)
  222. ; Reverse Copy "Num" Bytes from DS:SI to ES:DI
  223. ; (SI -= Num, DI -= Num)
  224. ; Count -= Num
  225. ; If Count == 0 Then
  226. ; BREAK
  227. ; If SI == 0xFFFF Then
  228. ; DS -= __AHINCR
  229. ; If DI == 0xFFFF Then
  230. ; ES -= __AHINCR
  231. ;
  232. next_r:
  233. mov ax,si
  234. sub ax,di
  235. sbb bx,bx
  236. and ax,bx
  237. add ax,di ; AX = MIN(SI, DI)
  238. test cbMem.hi,-1 ; is high word not zero?
  239. jnz @f ; at least 64k to go
  240. dec cx
  241. sub ax,cx
  242. sbb bx,bx
  243. and ax,bx
  244. add ax,cx
  245. inc cx
  246. @@:
  247. xor bx,bx
  248. add ax,1 ; AX = Num = MIN(Count-1,SI,DI)+1
  249. adc bx,0 ; bx==1 if exactly 64k
  250. xchg ax,cx
  251. sub ax,cx ; Count -= Num
  252. sbb cbMem.hi,bx
  253. std
  254. shr bx,1
  255. rcr cx,1 ; if bx==1, then cx ends up 0x8000
  256. dec si
  257. dec di
  258. rep movsw
  259. inc si ; realign pointers
  260. inc di
  261. adc cl,cl
  262. rep movsb ; move last byte, if necessary
  263. cld
  264. mov cx,ax ; restore cx
  265. or ax,cbMem.hi
  266. jz done ; If Count == 0 Then BREAK
  267. cmp si,-1 ; if SI wraps, update DS
  268. jne @f
  269. mov ax,ds
  270. sub ax,__AHINCR
  271. mov ds,ax ; update DS if appropriate
  272. @@:
  273. cmp di,-1 ; if DI wraps, update ES
  274. jne next_r
  275. mov ax,es
  276. sub ax,__AHINCR
  277. mov es,ax ; update ES if appropriate
  278. jmp next_r
  279. ;
  280. ; While Count != 0 Do
  281. ; If (Count + SI > 65536) OR (Count + DI > 65536) Then
  282. ; Num = Min(65536-SI, 65536-DI)
  283. ; Else
  284. ; Num = Count
  285. ; Copy "Num" Bytes from DS:SI to ES:DI (SI += Num, DI += Num)
  286. ; Count -= Num
  287. ; If Count == 0 Then
  288. ; BREAK
  289. ; If SI == 0 Then
  290. ; DS += __AHINCR
  291. ; If DI == 0 Then
  292. ; ES += __AHINCR
  293. ;
  294. next:
  295. ;;;;;;;;mov ax,cx
  296. ;;;;;;;;dec ax
  297. mov ax,di
  298. not ax ; AX = 65535-DI
  299. mov dx,si
  300. not dx ; DX = 65535-SI
  301. sub ax,dx
  302. sbb bx,bx
  303. and ax,bx
  304. add ax,dx ; AX = MIN(AX,DX) = MIN(65535-SI,65535-DI)
  305. ; problem: ax might have wrapped to zero
  306. test cbMem.hi,-1
  307. jnz plentytogo ; at least 64k still to copy
  308. dec cx ; this is ok, since high word is zero
  309. sub ax,cx
  310. sbb bx,bx
  311. and ax,bx
  312. add ax,cx ; AX = MIN(AX,CX)
  313. inc cx
  314. plentytogo:
  315. xor bx,bx
  316. add ax,1 ; AX = Num = MIN(count,65536-SI,65536-DI)
  317. ; we must check the carry here!
  318. adc bx,0 ; BX could be 1 here, if CX==0 indicating
  319. ; exactly 64k to copy
  320. xchg ax,cx
  321. sub ax,cx ; Count -= Num
  322. sbb cbMem.hi,bx
  323. shr bx,1
  324. rcr cx,1 ; if bx==1, then cx ends up 0x8000
  325. rep movsw
  326. adc cl,cl
  327. rep movsb ; move last byte, if necessary
  328. mov cx,ax ; put low word of count back in cx
  329. or ax,cbMem.hi
  330. jz done ; If Count == 0 Then BREAK
  331. or si,si ; if SI wraps, update DS
  332. jnz @f
  333. mov ax,ds
  334. add ax,__AHINCR
  335. mov ds,ax ; update DS if appropriate
  336. @@:
  337. or di,di ; if DI wraps, update ES
  338. jnz next
  339. mov ax,es
  340. add ax,__AHINCR
  341. mov es,ax ; update ES if appropriate
  342. jmp next
  343. ;
  344. ; Restore registers and return
  345. ;
  346. done:
  347. empty_copy:
  348. mov dx,lpDst.sel ; return destination address
  349. mov ax,lpDst.off
  350. cEnd
  351. sEnd
  352. sEnd CodeSeg
  353. end