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.

703 lines
22 KiB

  1. title "Memory functions"
  2. ;++
  3. ;
  4. ; Copyright (c) 2000 Microsoft Corporation
  5. ;
  6. ; Module Name:
  7. ;
  8. ; movemem.asm
  9. ;
  10. ; Abstract:
  11. ;
  12. ; This module implements functions to fill, copy , and compare blocks of
  13. ; memory.
  14. ;
  15. ; Author:
  16. ;
  17. ; David N. Cutler (davec) 6-Jul-2000
  18. ;
  19. ; Environment:
  20. ;
  21. ; Any mode.
  22. ;
  23. ;--
  24. include ksamd64.inc
  25. altentry RtlCopyMemoryAlternate
  26. subttl "Compare Memory"
  27. ;++
  28. ;
  29. ; SIZE_T
  30. ; RtlCompareMemory (
  31. ; IN PVOID Source1,
  32. ; IN PVOID Source2,
  33. ; IN SIZE_T Length
  34. ; )
  35. ;
  36. ; Routine Description:
  37. ;
  38. ; This function compares two unaligned blocks of memory and returns the
  39. ; number of bytes that compared equal.
  40. ;
  41. ; Arguments:
  42. ;
  43. ; Source1 (rcx) - Supplies a pointer to the first block of memory to
  44. ; compare.
  45. ;
  46. ; Source2 (rdx) - Supplies a pointer to the second block of memory to
  47. ; compare.
  48. ;
  49. ; Length (r8) - Supplies the Length, in bytes, of the memory to be
  50. ; compared.
  51. ;
  52. ; Return Value:
  53. ;
  54. ; The number of bytes that compared equal is returned as the function
  55. ; value. If all bytes compared equal, then the length of the orginal
  56. ; block of memory is returned.
  57. ;
  58. ;--
  59. CmFrame struct
  60. Fill dq ? ; fill to 8 mod 16
  61. SavedRsi dq ? ; saved nonvolatile registers
  62. SavedRdi dq ? ;
  63. CmFrame ends
  64. NESTED_ENTRY RtlCompareMemory, _TEXT$00
  65. push_reg rdi ; save nonvolatile registers
  66. push_reg rsi ;
  67. alloc_stack (sizeof CmFrame - (2 * 8)) ; allocate stack frame
  68. END_PROLOGUE
  69. mov rsi, rcx ; set address of first string
  70. mov rdi, rdx ; set address of second string
  71. xor edx, ecx ; check if compatible alignment
  72. and edx, 07h ;
  73. jnz short RlCM50 ; if nz, incompatible alignment
  74. cmp r8, 8 ; check if length to align
  75. jb short RlCM50 ; if b, insufficient alignment length
  76. ;
  77. ; Buffer alignment is compatible and there are enough bytes for alignment.
  78. ;
  79. mov r9, rdi ; copy destination address
  80. neg ecx ; compute alignment length
  81. and ecx, 07h ;
  82. jz short RlCM10 ; if z, buffers already aligned
  83. sub r8, rcx ; reduce count by align length
  84. repe cmpsb ; compare bytes to alignment
  85. jnz short RlCM30 ; if nz, not all bytes matched
  86. RlCM10: mov rcx, r8 ;
  87. and rcx, 0fffffff8h ; check if and quarwords to compare
  88. jz short RlCM20 ; if z, no quadwords to compare
  89. sub r8, rcx ; reduce length by compare count
  90. shr rcx, 3 ; compute number of quadwords
  91. repe cmpsq ; compare quadwords
  92. jz short RlCM20 ; if z, all quadwords compared
  93. inc rcx ; increment remaining count
  94. sub rsi, 8 ; back up source address
  95. sub rdi, 8 ; back up destination address
  96. shl rcx, 3 ; compute uncompared bytes
  97. RlCM20: add r8, rcx ; compute residual bytes to compare
  98. jz short RlCM40 ; if z, all bytes compared equal
  99. mov rcx, r8 ; set remaining bytes to compare
  100. repe cmpsb ; compare bytes
  101. jz short RlCM40 ; if z, all byte compared equal
  102. RlCM30: dec rdi ; back up destination address
  103. RlCM40: sub rdi, r9 ; compute number of bytes matched
  104. mov rax, rdi ;
  105. add rsp, sizeof CmFrame - (2 * 8) ; deallocate stack frame
  106. pop rsi ; restore nonvolatile register
  107. pop rdi ;
  108. ret ; return
  109. ;
  110. ; Buffer alignment is incompatible or there is less than 8 bytes to compare.
  111. ;
  112. RlCM50: test r8, r8 ; test if any bytes to compare
  113. jz short RlCM60 ; if z, no bytes to compare
  114. mov rcx, r8 ; set number of bytes to compare
  115. repe cmpsb ; compare bytes
  116. jz short RlCM60 ; if z, all bytes compared equal
  117. inc rcx ; increment remaining count
  118. sub r8, rcx ; compute number of bytes matched
  119. RlCM60: mov rax, r8 ;
  120. add rsp, sizeof CmFrame - (2 * 8) ; deallocate stack frame
  121. pop rsi ; restore nonvolatile register
  122. pop rdi ;
  123. ret ; return
  124. NESTED_END RtlCompareMemory, _TEXT$00
  125. subttl "Compare Memory 32-bits"
  126. ;++
  127. ;
  128. ; SIZE_T
  129. ; RtlCompareMemoryUlong (
  130. ; IN PVOID Source,
  131. ; IN SIZE_T Length,
  132. ; IN ULONG Pattern
  133. ; )
  134. ;
  135. ; Routine Description:
  136. ;
  137. ; This function compares a block of dword aligned memory with a specified
  138. ; pattern 32-bits at a time.
  139. ;
  140. ; N.B. The low two bits of the length are assumed to be zero and are
  141. ; ignored.
  142. ;
  143. ; Arguments:
  144. ;
  145. ; Source (rcx) - Supplies a pointer to the block of memory to compare.
  146. ;
  147. ; Length (rdx) - Supplies the length, in bytes, of the memory to compare. compare.
  148. ;
  149. ; Pattern (r8d) - Supplies the pattern to be compared against.
  150. ;
  151. ; Return Value:
  152. ;
  153. ; The number of bytes that compared equal is returned as the function
  154. ; value. If all bytes compared equal, then the length of the orginal
  155. ; block of memory is returned.
  156. ;
  157. ;--
  158. NESTED_ENTRY RtlCompareMemoryUlong, _TEXT$00
  159. push_reg rdi ; save nonvolatile register
  160. END_PROLOGUE
  161. mov rdi, rcx ; set destination address
  162. shr rdx, 2 ; compute number of dwords
  163. jz short RlCU10 ; if z, no dwords to compare
  164. mov rcx, rdx ; set length of compare in dwords
  165. mov eax, r8d ; set comparison pattern
  166. repe scasd ; compare memory with pattern
  167. jz short RlCU10 ; if z, all dwords compared
  168. inc rcx ; increment remaining count
  169. sub rdx, rcx ; compute number of bytes matched
  170. RlCU10: lea rax, [rdx*4] ; compute successful compare in bytes
  171. pop rdi ; restore nonvolatile register
  172. ret ; return
  173. NESTED_END RtlCompareMemoryUlong, _TEXT$00
  174. subttl "Copy Memory"
  175. ;++
  176. ;
  177. ; VOID
  178. ; RtlCopyMemory (
  179. ; OUT VOID UNALIGNED *Destination,
  180. ; IN CONST VOID UNALIGNED * Sources,
  181. ; IN SIZE_T Length
  182. ; )
  183. ;
  184. ; Routine Description:
  185. ;
  186. ; This function copies nonoverlapping from one unaligned buffer to another.
  187. ;
  188. ; Arguments:
  189. ;
  190. ; Destination (rcx) - Supplies a pointer to the destination buffer.
  191. ;
  192. ; Sources (rdx) - Supplies a pointer to the source buffer.
  193. ;
  194. ; Length (r8) - Supplies the length, in bytes, of the copy operation.
  195. ;
  196. ; Return Value:
  197. ;
  198. ; None.
  199. ;
  200. ;--
  201. CpFrame struct
  202. Fill dq ? ; fill to 8 mod 16
  203. SavedRsi dq ? ; saved nonvolatile registers
  204. SavedRdi dq ? ;
  205. CpFrame ends
  206. NESTED_ENTRY RtlCopyMemory, _TEXT$00
  207. push_reg rdi ; save nonvolatile registers
  208. push_reg rsi ;
  209. alloc_stack (sizeof CpFrame - (2 * 8)) ; allocate stack frame
  210. END_PROLOGUE
  211. ALTERNATE_ENTRY RtlCopyMemoryAlternate
  212. mov rdi, rcx ; set destination address
  213. mov rsi, rdx ; set source address
  214. xor edx, ecx ; check if compatible alignment
  215. and edx, 07h ;
  216. jnz short RlCP20 ; if nz, incompatible alignment
  217. cmp r8, 8 ; check if 8 bytes to move
  218. jb short RlCP20 ; if b, less than 8 bytes to move
  219. ;
  220. ; Buffer alignment is compatible and there are enough bytes for alignment.
  221. ;
  222. neg ecx ; compute alignment length
  223. and ecx, 07h ;
  224. jz short RlCP10 ; if z, buffers already aligned
  225. sub r8, rcx ; reduce count by align length
  226. rep movsb ; move bytes to alignment
  227. ;
  228. ; Move 8-byte blocks.
  229. ;
  230. RlCP10: mov rcx, r8 ; compute number of 8-byte blocks
  231. and rcx, 0fffffff8h ;
  232. jz short RlCP20 ; if z, no 8-byte blocks
  233. sub r8, rcx ; subtract 8-byte blocks from count
  234. shr rcx, 3 ; compute number of 8-byte blocks
  235. rep movsq ; move 8-byte blocks
  236. ;
  237. ; Move residual bytes.
  238. ;
  239. RlCP20: test r8, r8 ; test if any bytes to move
  240. jz short RlCP30 ; if z, no bytes to move
  241. mov rcx, r8 ; set remaining byte to move
  242. rep movsb ; move bytes to destination
  243. RlCP30: add rsp, sizeof CpFrame - (2 * 8) ; deallocate stack frame
  244. pop rsi ; restore nonvolatile registers
  245. pop rdi ;
  246. ret ; return
  247. NESTED_END RtlCopyMemory, _TEXT$00
  248. subttl "Copy Memory NonTemporal"
  249. ;++
  250. ;
  251. ; VOID
  252. ; RtlCopyMemoryNonTemporal (
  253. ; OUT VOID UNALIGNED *Destination,
  254. ; IN CONST VOID UNALIGNED * Sources,
  255. ; IN SIZE_T Length
  256. ; )
  257. ;
  258. ; Routine Description:
  259. ;
  260. ; This function copies nonoverlapping from one buffer to another using
  261. ; nontemporal moves that do not polute the cache.
  262. ;
  263. ; Arguments:
  264. ;
  265. ; Destination (rcx) - Supplies a pointer to the destination buffer.
  266. ;
  267. ; Sources (rdx) - Supplies a pointer to the source buffer.
  268. ;
  269. ; Length (r8) - Supplies the length, in bytes, of the copy operation.
  270. ;
  271. ; Return Value:
  272. ;
  273. ; None.
  274. ;
  275. ;--
  276. NtFrame struct
  277. Fill dq ? ; fill to 8 mod 16
  278. SavedRsi dq ? ; saved nonvolatile registers
  279. SavedRdi dq ? ;
  280. NtFrame ends
  281. NESTED_ENTRY RtlCopyMemoryNonTemporal, _TEXT$00
  282. push_reg rdi ; save nonvolatile registers
  283. push_reg rsi ;
  284. alloc_stack (sizeof NtFrame - (2 * 8)) ; allocate stack frame
  285. END_PROLOGUE
  286. mov rdi, rcx ; set destination address
  287. mov rsi, rdx ; set source address
  288. cmp r8, 16 ; check if 16 bytes to move
  289. jb RlNT50 ; if b, less than 16 bytes to move
  290. ;
  291. ; Align the destination to a 16-byte boundary.
  292. ;
  293. neg ecx ; compute alignment length
  294. and ecx, 0fh ;
  295. jz short RlNT10 ; if z, destination already aligned
  296. sub r8, rcx ; reduce count by align length
  297. rep movsb ; move bytes to alignment
  298. ;
  299. ; Move 64-byte blocks.
  300. ;
  301. RlNT10: mov rax, r8 ; compute number of 64-byte blocks
  302. and rax, 0ffffffc0h ;
  303. jz short RlNT30 ; if z, no 64-byte blocks to move
  304. sub r8, rax ; subtract 64-byte blocks from count
  305. RlNT20: prefetchnta 0[rsi] ; prefetch start of source block
  306. prefetchnta 63[rsi] ; prefetch end source block
  307. movdqu xmm0, [rsi] ; move 64-byte block
  308. movdqu xmm1, 16[rsi] ;
  309. movdqu xmm2, 32[rsi] ;
  310. movdqu xmm3, 48[rsi] ;
  311. movntq [rdi], xmm0 ;
  312. movntq 16[rdi], xmm1 ;
  313. movntq 32[rdi], xmm2 ;
  314. movntq 48[rdi], xmm3 ;
  315. add rdi, 64 ; advance destination address
  316. add rsi, 64 ; advance source address
  317. sub rax, 64 ; subtract number of bytes moved
  318. jnz short RlNT20 ; if nz, more 64-byte blocks to move
  319. ;
  320. ; Move 16-byte blocks.
  321. ;
  322. RlNT30: mov rax, r8 ; compute number of 16-byte blocks
  323. and rax, 0fffffff0h ;
  324. jz short RlNT50 ; if z, no 16-byte blocks
  325. sub r8, rax ; subract 16-byte blocks from count
  326. RlNT40: movdqu xmm0, [rsi] ; move 16-byte block
  327. movntq [rdi], xmm0 ;
  328. add rdi, 16 ; advance destination address
  329. add rsi, 16 ; advance source address
  330. sub rax, 16 ; subtract number of bytes moved
  331. jnz short RlNT40 ; if nz, more 16-byte blocks to move
  332. ;
  333. ; Move residual bytes.
  334. ;
  335. RlNT50: test r8, r8 ; test if any bytes to move
  336. jz short RlNT60 ; if z, no bytes to move
  337. mov rcx, r8 ; set residual bytes to move
  338. rep movsb ; move residual bytes
  339. RlNT60: sfence ; make sure all stores complete
  340. add rsp, sizeof NtFrame - (2 * 8) ; deallocate stack frame
  341. pop rsi ; restore nonvolatile registers
  342. pop rdi ;
  343. ret ; return
  344. NESTED_END RtlCopyMemoryNonTemporal, _TEXT$00
  345. subttl "Fill Memory"
  346. ;++
  347. ;
  348. ; VOID
  349. ; RtlFillMemory (
  350. ; IN VOID UNALIGNED *Destination,
  351. ; IN SIZE_T Length,
  352. ; IN UCHAR Fill
  353. ; )
  354. ;
  355. ; Routine Description:
  356. ;
  357. ; This function fills a block of unaligned memory with a specified pattern.
  358. ;
  359. ; Arguments:
  360. ;
  361. ; Destination (rcx) - Supplies a pointer to the memory to fill.
  362. ;
  363. ; Length (rdx) - Supplies the length, in bytes, of the memory to fill.
  364. ;
  365. ; Fill (r8d) - Supplies the value to fill memory with.
  366. ;
  367. ; Return Value:
  368. ;
  369. ; None.
  370. ;
  371. ;--
  372. NESTED_ENTRY RtlFillMemory, _TEXT$00
  373. push_reg rdi ; save nonvolatile register
  374. END_PROLOGUE
  375. mov rdi, rcx ; set destination address
  376. mov eax, r8d ; set fill pattern
  377. cmp rdx, 8 ; check if 8 bytes to fill
  378. jb short RlFM20 ; if b, less than 8 bytes to fill
  379. ;
  380. ; Fill alignment bytes.
  381. ;
  382. neg ecx ; compute alignment length
  383. and ecx, 07h ;
  384. jz short RlFM10 ; if z, buffers already aligned
  385. sub rdx, rcx ; reduce count by align length
  386. rep stosb ; fill bytes to alignment
  387. ;
  388. ; Fill 8-byte blocks.
  389. ;
  390. RlFM10: mov rcx, rdx ; compute number of 8-byte blocks
  391. and rcx, 0fffffff8h ;
  392. jz short RlFM20 ; if z, no 8-byte blocks
  393. sub rdx, rcx ; subtract 8-byte blocks from count
  394. shr rcx, 3 ; compute number of 8-byte blocks
  395. mov ah, al ; replicate pattern to dword
  396. shl eax, 16 ;
  397. mov al, r8b ;
  398. mov ah, al ;
  399. mov r9, rax ;
  400. shl rax, 32 ;
  401. or rax, r9 ;
  402. rep stosq ; fill 8-byte blocks
  403. ;
  404. ; Fill residual bytes.
  405. ;
  406. RlFM20: test rdx, rdx ; test if any bytes to fill
  407. jz short RlFM30 ; if z, no bytes to fill
  408. mov rcx, rdx ; set remaining byte to fill
  409. rep stosb ; fill residual bytes
  410. RlFM30: pop rdi ; restore nonvolatile register
  411. ret ; return
  412. NESTED_END RtlFillMemory, _TEXT$00
  413. subttl "Fill Memory 32-bits"
  414. ;++
  415. ;
  416. ; VOID
  417. ; RtlFillMemoryUlong (
  418. ; IN PVOID Destination,
  419. ; IN SIZE_T Length,
  420. ; IN ULONG Fill
  421. ; )
  422. ;
  423. ; Routine Description:
  424. ;
  425. ; This function fills a block of dword aligned memory with a specified
  426. ; pattern 32-bits at a time.
  427. ;
  428. ; N.B. The low two bits of the length are assumed to be zero and are
  429. ; ignored.
  430. ;
  431. ; Arguments:
  432. ;
  433. ; Destination (rcx) - Supplies a pointer to the memory to fill.
  434. ;
  435. ; Length (rdx) - Supplies the length, in bytes, of the memory to fill.
  436. ;
  437. ; Fill (r8d) - Supplies the value to fill memory with.
  438. ;
  439. ; Return Value:
  440. ;
  441. ; None.
  442. ;
  443. ;--
  444. NESTED_ENTRY RtlFillMemoryUlong, _TEXT$00
  445. push_reg rdi ; save nonvolatile register
  446. END_PROLOGUE
  447. mov rdi, rcx ; set destination address
  448. mov rcx, rdx ; set length of fill in bytes
  449. shr rcx, 2 ; compute number of dwords
  450. jz short RlFL10 ; if z, no dwords to fill
  451. mov eax, r8d ; set fill pattern
  452. rep stosd ; fill memory with pattern
  453. RlFl10: pop rdi ; restore nonvolatile register
  454. ret ; return
  455. NESTED_END RtlFillMemoryUlong, _TEXT$00
  456. subttl "Fill Memory 64-bits"
  457. ;++
  458. ;
  459. ; VOID
  460. ; RtlFillMemoryUlonglong (
  461. ; IN PVOID Destination,
  462. ; IN SIZE_T Length,
  463. ; IN ULONGLONG Fill
  464. ; )
  465. ;
  466. ; Routine Description:
  467. ;
  468. ; This function fills a block of qword aligned memory with a specified
  469. ; pattern 64-bits at a time.
  470. ;
  471. ; N.B. The low three bits of the length parameter are assumed to be zero
  472. ; and are ignored.
  473. ;
  474. ; Arguments:
  475. ;
  476. ; Destination (rcx) - Supplies a pointer to the memory to fill.
  477. ;
  478. ; Length (rdx) - Supplies the length, in bytes, of the memory to fill.
  479. ;
  480. ; Fill (r8) - Supplies the value to fill memory with.
  481. ;
  482. ; Return Value:
  483. ;
  484. ; None.
  485. ;
  486. ;--
  487. NESTED_ENTRY RtlFillMemoryUlonglong, _TEXT$00
  488. push_reg rdi ; save nonvolatile register
  489. END_PROLOGUE
  490. mov rdi, rcx ; set destination address
  491. mov rcx, rdx ; set length of fill in bytes
  492. shr rcx, 3 ; compute number of quadwords
  493. jz short RlFU10 ; if z, no quadwords to fill
  494. mov rax, r8 ; set fill pattern
  495. rep stosq ; fill memory with pattern
  496. RlFU10: pop rdi ; restore nonvolatile register
  497. ret ; return
  498. NESTED_END RtlFillMemoryUlonglong, _TEXT$00
  499. subttl "Move Memory"
  500. ;++
  501. ;
  502. ; VOID
  503. ; RtlMoveMemory (
  504. ; OUT VOID UNALIGNED *Destination,
  505. ; IN CONST VOID UNALIGNED * Sources,
  506. ; IN SIZE_T Length
  507. ; )
  508. ;
  509. ; Routine Description:
  510. ;
  511. ; This function copies from one unaligned buffer to another.
  512. ;
  513. ; Arguments:
  514. ;
  515. ; Destination (rcx) - Supplies a pointer to the destination buffer.
  516. ;
  517. ; Sources (rdx) - Supplies a pointer to the source buffer.
  518. ;
  519. ; Length (r8) - Supplies the length, in bytes, of the copy operation.
  520. ;
  521. ; Return Value:
  522. ;
  523. ; None.
  524. ;
  525. ;--
  526. MmFrame struct
  527. Fill dq ? ; fill to 8 mod 16
  528. SavedRsi dq ? ; saved nonvolatile registers
  529. SavedRdi dq ? ;
  530. MmFrame ends
  531. NESTED_ENTRY RtlMoveMemory, _TEXT$00
  532. push_reg rdi ; save nonvolatile registers
  533. push_reg rsi ;
  534. alloc_stack (sizeof MmFrame - (2 * 8)) ; allocate stack frame
  535. END_PROLOGUE
  536. cmp rcx, rdx ; check if possible buffer overlap
  537. jbe RtlCopyMemoryAlternate ; if be, no overlap possible
  538. mov rsi, rdx ; compute ending source address
  539. add rsi, r8 ;
  540. dec rsi ;
  541. cmp rcx, rsi ; check for buffer overlap
  542. jg RtlCopyMemoryAlternate ; if g, no overlap possible
  543. mov rdi, rcx ; compute ending destination address
  544. add rdi, r8 ;
  545. dec rdi ;
  546. mov rcx, r8 ; set count of bytes to move
  547. std ; set direction flag
  548. rep movsb ; move bytes backward to destination
  549. cld ; clear direction flag
  550. add rsp, sizeof MmFrame - (2 * 8) ; deallocate stack frame
  551. pop rsi ; restore nonvolatile registers
  552. pop rdi ;
  553. ret ; return
  554. NESTED_END RtlMoveMemory, _TEXT$00
  555. subttl "Prefetch Memory NonTemporal"
  556. ;++
  557. ;
  558. ; VOID
  559. ; RtlPrefetchMemoryNonTemporal (
  560. ; IN CONST PVOID Source,
  561. ; IN SIZE_T Length
  562. ; )
  563. ;
  564. ; Routine Description:
  565. ;
  566. ; This function prefetches memory at Source, for Length bytes into the
  567. ; closest cache to the processor.
  568. ;
  569. ; Arguments:
  570. ;
  571. ; Source (rcx) - Supplies a pointer to the memory to be prefetched.
  572. ;
  573. ; Length (rdx) - Supplies the length, in bytes, of the operation.
  574. ;
  575. ; Return Value:
  576. ;
  577. ; None.
  578. ;
  579. ;--
  580. LEAF_ENTRY RtlPrefetchMemoryNonTemporal, _TEXT$00
  581. RlPF10: prefetchnta 0[rcx] ; prefetch line
  582. add rcx, 64 ; increment address to prefetch
  583. sub rdx, 64 ; subtract number of bytes prefetched
  584. ja RlPF10 ; if above zero, more bytes to move
  585. ret ; return
  586. LEAF_END RtlPrefetchMemoryNonTemporal, _TEXT$00
  587. subttl "Zero Memory"
  588. ;++
  589. ;
  590. ; VOID
  591. ; RtlZeroMemory (
  592. ; IN VOID UNALIGNED *Destination,
  593. ; IN SIZE_T Length
  594. ; )
  595. ;
  596. ; Routine Description:
  597. ;
  598. ; This function fills a block of unaligned memory with zero.
  599. ;
  600. ; Arguments:
  601. ;
  602. ; Destination (rcx) - Supplies a pointer to the memory to fill.
  603. ;
  604. ; Length (rdx) - Supplies the length, in bytes, of the memory to fill.
  605. ;
  606. ; Return Value:
  607. ;
  608. ; None.
  609. ;
  610. ;--
  611. LEAF_ENTRY RtlZeroMemory, _TEXT$00
  612. xor r8, r8 ; set fill pattern
  613. jmp RtlFillMemory ; finish in common code
  614. LEAF_END RtlZeroMemory, _TEXT$00
  615. end