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.

605 lines
22 KiB

  1. page ,132
  2. title memcpy - Copy source memory bytes to destination
  3. ;***
  4. ;memcpy.asm - contains memcpy and memmove routines
  5. ;
  6. ; Copyright (c) 1986-2001, Microsoft Corporation. All rights reserved.
  7. ;
  8. ;Purpose:
  9. ; memcpy() copies a source memory buffer to a destination buffer.
  10. ; Overlapping buffers are not treated specially, so propogation may occur.
  11. ; memmove() copies a source memory buffer to a destination buffer.
  12. ; Overlapping buffers are treated specially, to avoid propogation.
  13. ;
  14. ;Revision History:
  15. ; 02-06-87 JCR Added memmove entry
  16. ; 04-08-87 JCR Conditionalized memmove/memcpy entries
  17. ; 06-30-87 SKS Rewritten for speed and size
  18. ; 08-21-87 SKS Fix return value for overlapping copies
  19. ; 05-17-88 SJM Add model-independent (large model) ifdef
  20. ; 08-04-88 SJM convert to cruntime/ add 32-bit support
  21. ; 08-19-88 JCR Minor 386 corrections/enhancements
  22. ; 10-25-88 JCR General cleanup for 386-only code
  23. ; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
  24. ; 05-10-91 GJF Back to _cdecl, sigh...
  25. ; 11-13-92 SRW Make it fast with unaligned arguments
  26. ; 09-26-96 RDK Total rewrite to optimize for Pentium execution.
  27. ; 06-12-01 PML inc->add 1, dec->sub 1 for Pentium 4 perf (vs7#267015)
  28. ;
  29. ;*******************************************************************************
  30. .xlist
  31. include cruntime.inc
  32. .list
  33. M_EXIT macro
  34. ifdef _STDCALL_
  35. ret 2*DPSIZE + ISIZE ; _stdcall return
  36. else
  37. ret ; _cdecl return
  38. endif
  39. endm ; M_EXIT
  40. CODESEG
  41. page
  42. ;***
  43. ;memcpy - Copy source buffer to destination buffer
  44. ;
  45. ;Purpose:
  46. ; memcpy() copies a source memory buffer to a destination memory buffer.
  47. ; This routine does NOT recognize overlapping buffers, and thus can lead
  48. ; to propogation.
  49. ; For cases where propogation must be avoided, memmove() must be used.
  50. ;
  51. ; Algorithm:
  52. ;
  53. ; void * memcpy(void * dst, void * src, size_t count)
  54. ; {
  55. ; void * ret = dst;
  56. ;
  57. ; /*
  58. ; * copy from lower addresses to higher addresses
  59. ; */
  60. ; while (count--)
  61. ; *dst++ = *src++;
  62. ;
  63. ; return(ret);
  64. ; }
  65. ;
  66. ;memmove - Copy source buffer to destination buffer
  67. ;
  68. ;Purpose:
  69. ; memmove() copies a source memory buffer to a destination memory buffer.
  70. ; This routine recognize overlapping buffers to avoid propogation.
  71. ; For cases where propogation is not a problem, memcpy() can be used.
  72. ;
  73. ; Algorithm:
  74. ;
  75. ; void * memmove(void * dst, void * src, size_t count)
  76. ; {
  77. ; void * ret = dst;
  78. ;
  79. ; if (dst <= src || dst >= (src + count)) {
  80. ; /*
  81. ; * Non-Overlapping Buffers
  82. ; * copy from lower addresses to higher addresses
  83. ; */
  84. ; while (count--)
  85. ; *dst++ = *src++;
  86. ; }
  87. ; else {
  88. ; /*
  89. ; * Overlapping Buffers
  90. ; * copy from higher addresses to lower addresses
  91. ; */
  92. ; dst += count - 1;
  93. ; src += count - 1;
  94. ;
  95. ; while (count--)
  96. ; *dst-- = *src--;
  97. ; }
  98. ;
  99. ; return(ret);
  100. ; }
  101. ;
  102. ;
  103. ;Entry:
  104. ; void *dst = pointer to destination buffer
  105. ; const void *src = pointer to source buffer
  106. ; size_t count = number of bytes to copy
  107. ;
  108. ;Exit:
  109. ; Returns a pointer to the destination buffer in AX/DX:AX
  110. ;
  111. ;Uses:
  112. ; CX, DX
  113. ;
  114. ;Exceptions:
  115. ;*******************************************************************************
  116. ifdef MEM_MOVE
  117. _MEM_ equ <memmove>
  118. else
  119. _MEM_ equ <memcpy>
  120. endif
  121. % public _MEM_
  122. _MEM_ proc \
  123. dst:ptr byte, \
  124. src:ptr byte, \
  125. count:IWORD
  126. ; destination pointer
  127. ; source pointer
  128. ; number of bytes to copy
  129. ; push ebp ;U - save old frame pointer
  130. ; mov ebp, esp ;V - set new frame pointer
  131. push edi ;U - save edi
  132. push esi ;V - save esi
  133. mov esi,[src] ;U - esi = source
  134. mov ecx,[count] ;V - ecx = number of bytes to move
  135. mov edi,[dst] ;U - edi = dest
  136. ;
  137. ; Check for overlapping buffers:
  138. ; If (dst <= src) Or (dst >= src + Count) Then
  139. ; Do normal (Upwards) Copy
  140. ; Else
  141. ; Do Downwards Copy to avoid propagation
  142. ;
  143. mov eax,ecx ;V - eax = byte count...
  144. mov edx,ecx ;U - edx = byte count...
  145. add eax,esi ;V - eax = point past source end
  146. cmp edi,esi ;U - dst <= src ?
  147. jbe short CopyUp ;V - yes, copy toward higher addresses
  148. cmp edi,eax ;U - dst < (src + count) ?
  149. jb CopyDown ;V - yes, copy toward lower addresses
  150. ;
  151. ; Copy toward higher addresses.
  152. ;
  153. ;
  154. ; The algorithm for forward moves is to align the destination to a dword
  155. ; boundary and so we can move dwords with an aligned destination. This
  156. ; occurs in 3 steps.
  157. ;
  158. ; - move x = ((4 - Dest & 3) & 3) bytes
  159. ; - move y = ((L-x) >> 2) dwords
  160. ; - move (L - x - y*4) bytes
  161. ;
  162. CopyUp:
  163. test edi,11b ;U - destination dword aligned?
  164. jnz short CopyLeadUp ;V - if we are not dword aligned already, align
  165. shr ecx,2 ;U - shift down to dword count
  166. and edx,11b ;V - trailing byte count
  167. cmp ecx,8 ;U - test if small enough for unwind copy
  168. jb short CopyUnwindUp ;V - if so, then jump
  169. rep movsd ;N - move all of our dwords
  170. jmp dword ptr TrailUpVec[edx*4] ;N - process trailing bytes
  171. ;
  172. ; Code to do optimal memory copies for non-dword-aligned destinations.
  173. ;
  174. ; The following length check is done for two reasons:
  175. ;
  176. ; 1. to ensure that the actual move length is greater than any possiale
  177. ; alignment move, and
  178. ;
  179. ; 2. to skip the multiple move logic for small moves where it would
  180. ; be faster to move the bytes with one instruction.
  181. ;
  182. align @WordSize
  183. CopyLeadUp:
  184. mov eax,edi ;U - get destination offset
  185. mov edx,11b ;V - prepare for mask
  186. sub ecx,4 ;U - check for really short string - sub for adjust
  187. jb short ByteCopyUp ;V - branch to just copy bytes
  188. and eax,11b ;U - get offset within first dword
  189. add ecx,eax ;V - update size after leading bytes copied
  190. jmp dword ptr LeadUpVec[eax*4-4] ;N - process leading bytes
  191. align @WordSize
  192. ByteCopyUp:
  193. jmp dword ptr TrailUpVec[ecx*4+16] ;N - process just bytes
  194. align @WordSize
  195. CopyUnwindUp:
  196. jmp dword ptr UnwindUpVec[ecx*4] ;N - unwind dword copy
  197. align @WordSize
  198. LeadUpVec dd LeadUp1, LeadUp2, LeadUp3
  199. align @WordSize
  200. LeadUp1:
  201. and edx,ecx ;U - trailing byte count
  202. mov al,[esi] ;V - get first byte from source
  203. mov [edi],al ;U - write second byte to destination
  204. mov al,[esi+1] ;V - get second byte from source
  205. mov [edi+1],al ;U - write second byte to destination
  206. mov al,[esi+2] ;V - get third byte from source
  207. shr ecx,2 ;U - shift down to dword count
  208. mov [edi+2],al ;V - write third byte to destination
  209. add esi,3 ;U - advance source pointer
  210. add edi,3 ;V - advance destination pointer
  211. cmp ecx,8 ;U - test if small enough for unwind copy
  212. jb short CopyUnwindUp ;V - if so, then jump
  213. rep movsd ;N - move all of our dwords
  214. jmp dword ptr TrailUpVec[edx*4] ;N - process trailing bytes
  215. align @WordSize
  216. LeadUp2:
  217. and edx,ecx ;U - trailing byte count
  218. mov al,[esi] ;V - get first byte from source
  219. mov [edi],al ;U - write second byte to destination
  220. mov al,[esi+1] ;V - get second byte from source
  221. shr ecx,2 ;U - shift down to dword count
  222. mov [edi+1],al ;V - write second byte to destination
  223. add esi,2 ;U - advance source pointer
  224. add edi,2 ;V - advance destination pointer
  225. cmp ecx,8 ;U - test if small enough for unwind copy
  226. jb short CopyUnwindUp ;V - if so, then jump
  227. rep movsd ;N - move all of our dwords
  228. jmp dword ptr TrailUpVec[edx*4] ;N - process trailing bytes
  229. align @WordSize
  230. LeadUp3:
  231. and edx,ecx ;U - trailing byte count
  232. mov al,[esi] ;V - get first byte from source
  233. mov [edi],al ;U - write second byte to destination
  234. add esi,1 ;V - advance source pointer
  235. shr ecx,2 ;U - shift down to dword count
  236. add edi,1 ;V - advance destination pointer
  237. cmp ecx,8 ;U - test if small enough for unwind copy
  238. jb short CopyUnwindUp ;V - if so, then jump
  239. rep movsd ;N - move all of our dwords
  240. jmp dword ptr TrailUpVec[edx*4] ;N - process trailing bytes
  241. align @WordSize
  242. UnwindUpVec dd UnwindUp0, UnwindUp1, UnwindUp2, UnwindUp3
  243. dd UnwindUp4, UnwindUp5, UnwindUp6, UnwindUp7
  244. UnwindUp7:
  245. mov eax,[esi+ecx*4-28] ;U - get dword from source
  246. ;V - spare
  247. mov [edi+ecx*4-28],eax ;U - put dword into destination
  248. UnwindUp6:
  249. mov eax,[esi+ecx*4-24] ;U(entry)/V(not) - get dword from source
  250. ;V(entry) - spare
  251. mov [edi+ecx*4-24],eax ;U - put dword into destination
  252. UnwindUp5:
  253. mov eax,[esi+ecx*4-20] ;U(entry)/V(not) - get dword from source
  254. ;V(entry) - spare
  255. mov [edi+ecx*4-20],eax ;U - put dword into destination
  256. UnwindUp4:
  257. mov eax,[esi+ecx*4-16] ;U(entry)/V(not) - get dword from source
  258. ;V(entry) - spare
  259. mov [edi+ecx*4-16],eax ;U - put dword into destination
  260. UnwindUp3:
  261. mov eax,[esi+ecx*4-12] ;U(entry)/V(not) - get dword from source
  262. ;V(entry) - spare
  263. mov [edi+ecx*4-12],eax ;U - put dword into destination
  264. UnwindUp2:
  265. mov eax,[esi+ecx*4-8] ;U(entry)/V(not) - get dword from source
  266. ;V(entry) - spare
  267. mov [edi+ecx*4-8],eax ;U - put dword into destination
  268. UnwindUp1:
  269. mov eax,[esi+ecx*4-4] ;U(entry)/V(not) - get dword from source
  270. ;V(entry) - spare
  271. mov [edi+ecx*4-4],eax ;U - put dword into destination
  272. lea eax,[ecx*4] ;V - compute update for pointer
  273. add esi,eax ;U - update source pointer
  274. add edi,eax ;V - update destination pointer
  275. UnwindUp0:
  276. jmp dword ptr TrailUpVec[edx*4] ;N - process trailing bytes
  277. ;-----------------------------------------------------------------------------
  278. align @WordSize
  279. TrailUpVec dd TrailUp0, TrailUp1, TrailUp2, TrailUp3
  280. align @WordSize
  281. TrailUp0:
  282. mov eax,[dst] ;U - return pointer to destination
  283. pop esi ;V - restore esi
  284. pop edi ;U - restore edi
  285. ;V - spare
  286. M_EXIT
  287. align @WordSize
  288. TrailUp1:
  289. mov al,[esi] ;U - get byte from source
  290. ;V - spare
  291. mov [edi],al ;U - put byte in destination
  292. mov eax,[dst] ;V - return pointer to destination
  293. pop esi ;U - restore esi
  294. pop edi ;V - restore edi
  295. M_EXIT
  296. align @WordSize
  297. TrailUp2:
  298. mov al,[esi] ;U - get first byte from source
  299. ;V - spare
  300. mov [edi],al ;U - put first byte into destination
  301. mov al,[esi+1] ;V - get second byte from source
  302. mov [edi+1],al ;U - put second byte into destination
  303. mov eax,[dst] ;V - return pointer to destination
  304. pop esi ;U - restore esi
  305. pop edi ;V - restore edi
  306. M_EXIT
  307. align @WordSize
  308. TrailUp3:
  309. mov al,[esi] ;U - get first byte from source
  310. ;V - spare
  311. mov [edi],al ;U - put first byte into destination
  312. mov al,[esi+1] ;V - get second byte from source
  313. mov [edi+1],al ;U - put second byte into destination
  314. mov al,[esi+2] ;V - get third byte from source
  315. mov [edi+2],al ;U - put third byte into destination
  316. mov eax,[dst] ;V - return pointer to destination
  317. pop esi ;U - restore esi
  318. pop edi ;V - restore edi
  319. M_EXIT
  320. ;-----------------------------------------------------------------------------
  321. ;-----------------------------------------------------------------------------
  322. ;-----------------------------------------------------------------------------
  323. ;
  324. ; Copy down to avoid propogation in overlapping buffers.
  325. ;
  326. align @WordSize
  327. CopyDown:
  328. lea esi,[esi+ecx-4] ;U - point to 4 bytes before src buffer end
  329. lea edi,[edi+ecx-4] ;V - point to 4 bytes before dest buffer end
  330. ;
  331. ; See if the destination start is dword aligned
  332. ;
  333. test edi,11b ;U - test if dword aligned
  334. jnz short CopyLeadDown ;V - if not, jump
  335. shr ecx,2 ;U - shift down to dword count
  336. and edx,11b ;V - trailing byte count
  337. cmp ecx,8 ;U - test if small enough for unwind copy
  338. jb short CopyUnwindDown ;V - if so, then jump
  339. std ;N - set direction flag
  340. rep movsd ;N - move all of our dwords
  341. cld ;N - clear direction flag back
  342. jmp dword ptr TrailDownVec[edx*4] ;N - process trailing bytes
  343. align @WordSize
  344. CopyUnwindDown:
  345. neg ecx ;U - negate dword count for table merging
  346. ;V - spare
  347. jmp dword ptr UnwindDownVec[ecx*4+28] ;N - unwind copy
  348. align @WordSize
  349. CopyLeadDown:
  350. mov eax,edi ;U - get destination offset
  351. mov edx,11b ;V - prepare for mask
  352. cmp ecx,4 ;U - check for really short string
  353. jb short ByteCopyDown ;V - branch to just copy bytes
  354. and eax,11b ;U - get offset within first dword
  355. sub ecx,eax ;U - to update size after lead copied
  356. jmp dword ptr LeadDownVec[eax*4-4] ;N - process leading bytes
  357. align @WordSize
  358. ByteCopyDown:
  359. jmp dword ptr TrailDownVec[ecx*4] ;N - process just bytes
  360. align @WordSize
  361. LeadDownVec dd LeadDown1, LeadDown2, LeadDown3
  362. align @WordSize
  363. LeadDown1:
  364. mov al,[esi+3] ;U - load first byte
  365. and edx,ecx ;V - trailing byte count
  366. mov [edi+3],al ;U - write out first byte
  367. sub esi,1 ;V - point to last src dword
  368. shr ecx,2 ;U - shift down to dword count
  369. sub edi,1 ;V - point to last dest dword
  370. cmp ecx,8 ;U - test if small enough for unwind copy
  371. jb short CopyUnwindDown ;V - if so, then jump
  372. std ;N - set direction flag
  373. rep movsd ;N - move all of our dwords
  374. cld ;N - clear direction flag
  375. jmp dword ptr TrailDownVec[edx*4] ;N - process trailing bytes
  376. align @WordSize
  377. LeadDown2:
  378. mov al,[esi+3] ;U - load first byte
  379. and edx,ecx ;V - trailing byte count
  380. mov [edi+3],al ;U - write out first byte
  381. mov al,[esi+2] ;V - get second byte from source
  382. shr ecx,2 ;U - shift down to dword count
  383. mov [edi+2],al ;V - write second byte to destination
  384. sub esi,2 ;U - point to last src dword
  385. sub edi,2 ;V - point to last dest dword
  386. cmp ecx,8 ;U - test if small enough for unwind copy
  387. jb short CopyUnwindDown ;V - if so, then jump
  388. std ;N - set direction flag
  389. rep movsd ;N - move all of our dwords
  390. cld ;N - clear direction flag
  391. jmp dword ptr TrailDownVec[edx*4] ;N - process trailing bytes
  392. align @WordSize
  393. LeadDown3:
  394. mov al,[esi+3] ;U - load first byte
  395. and edx,ecx ;V - trailing byte count
  396. mov [edi+3],al ;U - write out first byte
  397. mov al,[esi+2] ;V - get second byte from source
  398. mov [edi+2],al ;U - write second byte to destination
  399. mov al,[esi+1] ;V - get third byte from source
  400. shr ecx,2 ;U - shift down to dword count
  401. mov [edi+1],al ;V - write third byte to destination
  402. sub esi,3 ;U - point to last src dword
  403. sub edi,3 ;V - point to last dest dword
  404. cmp ecx,8 ;U - test if small enough for unwind copy
  405. jb CopyUnwindDown ;V - if so, then jump
  406. std ;N - set direction flag
  407. rep movsd ;N - move all of our dwords
  408. cld ;N - clear direction flag
  409. jmp dword ptr TrailDownVec[edx*4] ;N - process trailing bytes
  410. ;------------------------------------------------------------------
  411. align @WordSize
  412. UnwindDownVec dd UnwindDown7, UnwindDown6, UnwindDown5, UnwindDown4
  413. dd UnwindDown3, UnwindDown2, UnwindDown1, UnwindDown0
  414. UnwindDown7:
  415. mov eax,[esi+ecx*4+28] ;U - get dword from source
  416. ;V - spare
  417. mov [edi+ecx*4+28],eax ;U - put dword into destination
  418. UnwindDown6:
  419. mov eax,[esi+ecx*4+24] ;U(entry)/V(not) - get dword from source
  420. ;V(entry) - spare
  421. mov [edi+ecx*4+24],eax ;U - put dword into destination
  422. UnwindDown5:
  423. mov eax,[esi+ecx*4+20] ;U(entry)/V(not) - get dword from source
  424. ;V(entry) - spare
  425. mov [edi+ecx*4+20],eax ;U - put dword into destination
  426. UnwindDown4:
  427. mov eax,[esi+ecx*4+16] ;U(entry)/V(not) - get dword from source
  428. ;V(entry) - spare
  429. mov [edi+ecx*4+16],eax ;U - put dword into destination
  430. UnwindDown3:
  431. mov eax,[esi+ecx*4+12] ;U(entry)/V(not) - get dword from source
  432. ;V(entry) - spare
  433. mov [edi+ecx*4+12],eax ;U - put dword into destination
  434. UnwindDown2:
  435. mov eax,[esi+ecx*4+8] ;U(entry)/V(not) - get dword from source
  436. ;V(entry) - spare
  437. mov [edi+ecx*4+8],eax ;U - put dword into destination
  438. UnwindDown1:
  439. mov eax,[esi+ecx*4+4] ;U(entry)/V(not) - get dword from source
  440. ;V(entry) - spare
  441. mov [edi+ecx*4+4],eax ;U - put dword into destination
  442. lea eax,[ecx*4] ;V - compute update for pointer
  443. add esi,eax ;U - update source pointer
  444. add edi,eax ;V - update destination pointer
  445. UnwindDown0:
  446. jmp dword ptr TrailDownVec[edx*4] ;N - process trailing bytes
  447. ;-----------------------------------------------------------------------------
  448. align @WordSize
  449. TrailDownVec dd TrailDown0, TrailDown1, TrailDown2, TrailDown3
  450. align @WordSize
  451. TrailDown0:
  452. mov eax,[dst] ;U - return pointer to destination
  453. ;V - spare
  454. pop esi ;U - restore esi
  455. pop edi ;V - restore edi
  456. M_EXIT
  457. align @WordSize
  458. TrailDown1:
  459. mov al,[esi+3] ;U - get byte from source
  460. ;V - spare
  461. mov [edi+3],al ;U - put byte in destination
  462. mov eax,[dst] ;V - return pointer to destination
  463. pop esi ;U - restore esi
  464. pop edi ;V - restore edi
  465. M_EXIT
  466. align @WordSize
  467. TrailDown2:
  468. mov al,[esi+3] ;U - get first byte from source
  469. ;V - spare
  470. mov [edi+3],al ;U - put first byte into destination
  471. mov al,[esi+2] ;V - get second byte from source
  472. mov [edi+2],al ;U - put second byte into destination
  473. mov eax,[dst] ;V - return pointer to destination
  474. pop esi ;U - restore esi
  475. pop edi ;V - restore edi
  476. M_EXIT
  477. align @WordSize
  478. TrailDown3:
  479. mov al,[esi+3] ;U - get first byte from source
  480. ;V - spare
  481. mov [edi+3],al ;U - put first byte into destination
  482. mov al,[esi+2] ;V - get second byte from source
  483. mov [edi+2],al ;U - put second byte into destination
  484. mov al,[esi+1] ;V - get third byte from source
  485. mov [edi+1],al ;U - put third byte into destination
  486. mov eax,[dst] ;V - return pointer to destination
  487. pop esi ;U - restore esi
  488. pop edi ;V - restore edi
  489. M_EXIT
  490. _MEM_ endp
  491. end