diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/rtl/i386/movemem.asm | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/ntos/rtl/i386/movemem.asm')
-rw-r--r-- | private/ntos/rtl/i386/movemem.asm | 659 |
1 files changed, 659 insertions, 0 deletions
diff --git a/private/ntos/rtl/i386/movemem.asm b/private/ntos/rtl/i386/movemem.asm new file mode 100644 index 000000000..f5131312d --- /dev/null +++ b/private/ntos/rtl/i386/movemem.asm @@ -0,0 +1,659 @@ + title "User Mode Zero and Move Memory functions" +;++ +; +; Copyright (c) 1989 Microsoft Corporation +; +; Module Name: +; +; movemem.asm +; +; Abstract: +; +; This module implements functions to zero and copy blocks of memory +; +; +; Author: +; +; Steven R. Wood (stevewo) 25-May-1990 +; +; Environment: +; +; User mode only. +; +; Revision History: +; +;-- +.386p + .xlist +include ks386.inc +include callconv.inc ; calling convention macros + .list + +if DBG +_DATA SEGMENT DWORD PUBLIC 'DATA' + + public _RtlpZeroCount + public _RtlpZeroBytes + +_RtlpZeroCount dd 0 +_RtlpZeroBytes dd 0 + +ifndef BLDR_KERNEL_RUNTIME +_MsgUnalignedPtr db 'RTL: RtlCompare/FillMemoryUlong called with unaligned pointer (%x)\n',0 +endif + +_DATA ENDS + +ifndef BLDR_KERNEL_RUNTIME +ifdef NTOS_KERNEL_RUNTIME + extrn _KdDebuggerEnabled:BYTE +endif + EXTRNP _DbgBreakPoint,0 + extrn _DbgPrint:near +endif +endif + +; +; Alignment parameters for zeroing and moving memory. +; + +ZERO_MEMORY_ALIGNMENT = 4 +ZERO_MEMORY_ALIGNMENT_LOG2 = 2 +ZERO_MEMORY_ALIGNMENT_MASK = ZERO_MEMORY_ALIGNMENT - 1 + +MEMORY_ALIGNMENT = 4 +MEMORY_ALIGNMENT_LOG2 = 2 +MEMORY_ALIGNMENT_MASK = MEMORY_ALIGNMENT - 1 + + +; +; Alignment for functions in this module +; + +CODE_ALIGNMENT macro + align 16 +endm + + +_TEXT$00 SEGMENT PARA PUBLIC 'CODE' + ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING + + page , 132 + subttl "RtlCompareMemory" +;++ +; +; ULONG +; RtlCompareMemory ( +; IN PVOID Source1, +; IN PVOID Source2, +; IN ULONG Length +; ) +; +; Routine Description: +; +; This function compares two blocks of memory and returns the number +; of bytes that compared equal. +; +; Arguments: +; +; Source1 (esp+4) - Supplies a pointer to the first block of memory to +; compare. +; +; Source2 (esp+8) - Supplies a pointer to the second block of memory to +; compare. +; +; Length (esp+12) - Supplies the Length, in bytes, of the memory to be +; compared. +; +; Return Value: +; +; The number of bytes that compared equal is returned as the function +; value. If all bytes compared equal, then the length of the orginal +; block of memory is returned. +; +;-- + +RcmSource1 equ [esp+12] +RcmSource2 equ [esp+16] +RcmLength equ [esp+20] + +CODE_ALIGNMENT +cPublicProc _RtlCompareMemory,3 +cPublicFpo 3,0 + + push esi ; save registers + push edi ; + cld ; clear direction + mov esi,RcmSource1 ; (esi) -> first block to compare + mov edi,RcmSource2 ; (edi) -> second block to compare + +; +; Compare dwords, if any. +; + +rcm10: mov ecx,RcmLength ; (ecx) = length in bytes + shr ecx,2 ; (ecx) = length in dwords + jz rcm20 ; no dwords, try bytes + repe cmpsd ; compare dwords + jnz rcm40 ; mismatch, go find byte + +; +; Compare residual bytes, if any. +; + +rcm20: mov ecx,RcmLength ; (ecx) = length in bytes + and ecx,3 ; (ecx) = length mod 4 + jz rcm30 ; 0 odd bytes, go do dwords + repe cmpsb ; compare odd bytes + jnz rcm50 ; mismatch, go report how far we got + +; +; All bytes in the block match. +; + +rcm30: mov eax,RcmLength ; set number of matching bytes + pop edi ; restore registers + pop esi ; + stdRET _RtlCompareMemory + +; +; When we come to rcm40, esi (and edi) points to the dword after the +; one which caused the mismatch. Back up 1 dword and find the byte. +; Since we know the dword didn't match, we can assume one byte won't. +; + +rcm40: sub esi,4 ; back up + sub edi,4 ; back up + mov ecx,5 ; ensure that ecx doesn't count out + repe cmpsb ; find mismatch byte + +; +; When we come to rcm50, esi points to the byte after the one that +; did not match, which is TWO after the last byte that did match. +; + +rcm50: dec esi ; back up + sub esi,RcmSource1 ; compute bytes that matched + mov eax,esi ; + pop edi ; restore registers + pop esi ; + stdRET _RtlCompareMemory + +stdENDP _RtlCompareMemory + + + subttl "RtlCompareMemory" +EcmlSource equ [esp + 4 + 4] +EcmlLength equ [esp + 4 + 8] +EcmlPattern equ [esp + 4 + 12] + +; end of arguments + +CODE_ALIGNMENT +cPublicProc _RtlCompareMemoryUlong ,3 + +; +; Save the non-volatile registers that we will use, without the benefit of +; a frame pointer. No exception handling in this routine. +; + + push edi + +; +; Setup the registers for using REP STOS instruction to zero memory. +; +; edi -> memory to zero +; ecx = number of 32-bits words to zero +; edx = number of extra 8-bit bytes to zero at the end (0 - 3) +; eax = value to store in destination +; direction flag is clear for auto-increment +; + + mov edi,EcmlSource +if DBG +ifndef BLDR_KERNEL_RUNTIME + test edi,3 + jz @F + push edi + push offset FLAT:_MsgUnalignedPtr + call _DbgPrint + add esp, 2 * 4 +ifdef NTOS_KERNEL_RUNTIME + cmp _KdDebuggerEnabled,0 +else + mov eax,fs:[PcTeb] + mov eax,[eax].TebPeb + cmp byte ptr [eax].PebBeingDebugged,0 +endif + je @F + call _DbgBreakPoint@0 +@@: +endif +endif + mov ecx,EcmlLength + mov eax,EcmlPattern + shr ecx,ZERO_MEMORY_ALIGNMENT_LOG2 + + +; +; If number of 32-bit words to compare is non-zero, then do it. +; + + repe scasd + je @F + sub edi,4 +@@: + sub edi,EcmlSource + mov eax,edi + pop edi + stdRET _RtlCompareMemoryUlong + +stdENDP _RtlCompareMemoryUlong + + + subttl "RtlFillMemory" +;++ +; +; VOID +; RtlFillMemory ( +; IN PVOID Destination, +; IN ULONG Length, +; IN UCHAR Fill +; ) +; +; Routine Description: +; +; This function fills memory with a byte value. +; +; Arguments: +; +; Destination - Supplies a pointer to the memory to zero. +; +; Length - Supplies the Length, in bytes, of the memory to be zeroed. +; +; Fill - Supplies the byte value to fill memory with. +; +; Return Value: +; +; None. +; +;-- + +; definitions for arguments +; (TOS) = Return address + +EfmDestination equ [esp + 4 + 4] +EfmLength equ [esp + 4 + 8] +EfmFill equ byte ptr [esp + 4 + 12] + +; end of arguments + +CODE_ALIGNMENT +cPublicProc _RtlFillMemory ,3 +cPublicFpo 3,1 + +; +; Save the non-volatile registers that we will use, without the benefit of +; a frame pointer. No exception handling in this routine. +; + + push edi + +; +; Setup the registers for using REP STOS instruction to zero memory. +; +; edi -> memory to zero +; ecx = number of 32-bits words to zero +; edx = number of extra 8-bit bytes to zero at the end (0 - 3) +; eax = value to store in destination +; direction flag is clear for auto-increment +; + + mov edi,EfmDestination + mov ecx,EfmLength + mov al,EfmFill + mov ah,al + shl eax,16 + mov al,EfmFill + mov ah,al + cld + + mov edx,ecx + and edx,ZERO_MEMORY_ALIGNMENT_MASK + shr ecx,ZERO_MEMORY_ALIGNMENT_LOG2 + + +; +; If number of 32-bit words to zero is non-zero, then do it. +; + + rep stosd + +; +; If number of extra 8-bit bytes to zero is non-zero, then do it. In either +; case restore non-volatile registers and return. +; + + or ecx,edx + jnz @F + pop edi + stdRET _RtlFillMemory +@@: + rep stosb + pop edi + stdRET _RtlFillMemory + +stdENDP _RtlFillMemory + + subttl "RtlFillMemory" +;++ +; +; VOID +; RtlFillMemoryUlong ( +; IN PVOID Destination, +; IN ULONG Length, +; IN ULONG Fill +; ) +; +; Routine Description: +; +; This function fills memory with a 32-bit value. The Destination pointer +; must be aligned on a 4 byte boundary and the low order two bits of the +; Length parameter are ignored. +; +; Arguments: +; +; Destination - Supplies a pointer to the memory to zero. +; +; Length - Supplies the Length, in bytes, of the memory to be zeroed. +; +; Fill - Supplies the 32-bit value to fill memory with. +; +; Return Value: +; +; None. +; +;-- + +; definitions for arguments +; (TOS) = Return address + +EfmlDestination equ [esp + 4 + 4] +EfmlLength equ [esp + 4 + 8] +EfmlFill equ [esp + 4 + 12] + +; end of arguments + +CODE_ALIGNMENT +cPublicProc _RtlFillMemoryUlong ,3 +cPublicFpo 3,1 + +; +; Save the non-volatile registers that we will use, without the benefit of +; a frame pointer. No exception handling in this routine. +; + + push edi + +; +; Setup the registers for using REP STOS instruction to zero memory. +; +; edi -> memory to zero +; ecx = number of 32-bits words to zero +; edx = number of extra 8-bit bytes to zero at the end (0 - 3) +; eax = value to store in destination +; direction flag is clear for auto-increment +; + + mov edi,EfmlDestination +if DBG +ifndef BLDR_KERNEL_RUNTIME + test edi,3 + jz @F + push edi + push offset FLAT:_MsgUnalignedPtr + call _DbgPrint + add esp, 2 * 4 +ifdef NTOS_KERNEL_RUNTIME + cmp _KdDebuggerEnabled,0 +else + mov eax,fs:[PcTeb] + mov eax,[eax].TebPeb + cmp byte ptr [eax].PebBeingDebugged,0 +endif + je @F + call _DbgBreakPoint@0 +@@: +endif +endif + mov ecx,EfmlLength + mov eax,EfmlFill + shr ecx,ZERO_MEMORY_ALIGNMENT_LOG2 + + +; +; If number of 32-bit words to zero is non-zero, then do it. +; + + rep stosd + + pop edi + stdRET _RtlFillMemoryUlong + +stdENDP _RtlFillMemoryUlong + + subttl "RtlZeroMemory" +;++ +; +; VOID +; RtlZeroMemory ( +; IN PVOID Destination, +; IN ULONG Length +; ) +; +; Routine Description: +; +; This function zeros memory. +; +; Arguments: +; +; Destination - Supplies a pointer to the memory to zero. +; +; Length - Supplies the Length, in bytes, of the memory to be zeroed. +; +; Return Value: +; +; None. +; +;-- + +; definitions for arguments +; (TOS) = Return address + +EzmDestination equ [esp + 4 + 4] +EzmLength equ [esp + 4 + 8] + +; end of arguments + +CODE_ALIGNMENT +cPublicProc _RtlZeroMemory ,2 +cPublicFpo 2,1 + +; +; Save the non-volatile registers that we will use, without the benefit of +; a frame pointer. No exception handling in this routine. +; + + push edi + +; +; Setup the registers for using REP STOS instruction to zero memory. +; +; edi -> memory to zero +; ecx = number of 32-bits words to zero +; edx = number of extra 8-bit bytes to zero at the end (0 - 3) +; eax = zero (value to store in destination) +; direction flag is clear for auto-increment +; + + mov edi,EzmDestination + mov ecx,EzmLength + xor eax,eax + cld + + mov edx,ecx + and edx,ZERO_MEMORY_ALIGNMENT_MASK + shr ecx,ZERO_MEMORY_ALIGNMENT_LOG2 + + +; +; If number of 32-bit words to zero is non-zero, then do it. +; + + rep stosd + +; +; If number of extra 8-bit bytes to zero is non-zero, then do it. In either +; case restore non-volatile registers and return. +; + + or ecx,edx + jnz @F + pop edi + stdRET _RtlZeroMemory +@@: + rep stosb + pop edi + stdRET _RtlZeroMemory + +stdENDP _RtlZeroMemory + + page , 132 + subttl "RtlMoveMemory" +;++ +; +; VOID +; RtlMoveMemory ( +; IN PVOID Destination, +; IN PVOID Source OPTIONAL, +; IN ULONG Length +; ) +; +; Routine Description: +; +; This function moves memory either forward or backward, aligned or +; unaligned, in 4-byte blocks, followed by any remaining bytes. +; +; Arguments: +; +; Destination - Supplies a pointer to the destination of the move. +; +; Source - Supplies a pointer to the memory to move. +; +; Length - Supplies the Length, in bytes, of the memory to be moved. +; +; Return Value: +; +; None. +; +;-- + +; Definitions of arguments +; (TOS) = Return address + +EmmDestination equ [esp + 8 + 4] +EmmSource equ [esp + 8 + 8] +EmmLength equ [esp + 8 + 12] + +; End of arguments + +CODE_ALIGNMENT +cPublicProc _RtlMoveMemory ,3 +cPublicFpo 3,2 + +; +; Save the non-volatile registers that we will use, without the benefit of +; a frame pointer. No exception handling in this routine. +; + + push esi + push edi + +; +; Setup the registers for using REP MOVS instruction to move memory. +; +; esi -> memory to move (NULL implies the destination will be zeroed) +; edi -> destination of move +; ecx = number of 32-bits words to move +; edx = number of extra 8-bit bytes to move at the end (0 - 3) +; direction flag is clear for auto-increment +; + + mov esi,EmmSource + mov edi,EmmDestination + mov ecx,EmmLength +if DBG + inc _RtlpZeroCount + add _RtlpZeroBytes,ecx +endif + cld + + cmp esi,edi ; Special case if Source > Destination + jbe overlap + +nooverlap: + mov edx,ecx + and edx,MEMORY_ALIGNMENT_MASK + shr ecx,MEMORY_ALIGNMENT_LOG2 + +; +; If number of 32-bit words to move is non-zero, then do it. +; + + rep movsd + +; +; If number of extra 8-bit bytes to move is non-zero, then do it. In either +; case restore non-volatile registers and return. +; + + or ecx,edx + jnz @F + pop edi + pop esi + stdRET _RtlMoveMemory +@@: + rep movsb + +movedone: + pop edi + pop esi + stdRET _RtlMoveMemory + +; +; Here to handle special case when Source > Destination and therefore is a +; potential overlapping move. If Source == Destination, then nothing to do. +; Otherwise, increment the Source and Destination pointers by Length and do +; the move backwards, a byte at a time. +; + +overlap: + je movedone + mov eax,edi + sub eax,esi + cmp ecx,eax + jbe nooverlap + + std + add esi,ecx + add edi,ecx + dec esi + dec edi + rep movsb + cld + jmp short movedone + +stdENDP _RtlMoveMemory + +_TEXT$00 ends + end |