2025-04-27 07:49:33 -04:00

128 lines
3.1 KiB
NASM

page ,132
title memset - set sections of memory all to one byte
;***
;memset.asm - set a section of memory to all one byte
;
; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
;
;Purpose:
; contains the memset() routine
;
;Revision History:
; 05-07-84 RN initial version
; 06-30-87 SKS faster algorithm
; 05-17-88 SJM Add model-independent (large model) ifdef
; 08-04-88 SJM convert to cruntime/ add 32-bit support
; 08-19-88 JCR Enable word alignment code for all models/CPUs,
; Some code improvement
; 10-25-88 JCR General cleanup for 386-only code
; 10-27-88 JCR More optimization (dword alignment, no ebx usage, etc)
; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
; 05-10-91 GJF Back to _cdecl, sigh...
;
;*******************************************************************************
.xlist
include cruntime.inc
.list
page
;***
;char *memset(dst, val, count) - sets "count" bytes at "dst" to "val"
;
;Purpose:
; Sets the first "count" bytes of the memory starting
; at "dst" to the character value "val".
;
; Algorithm:
; char *
; memset (dst, val, count)
; char *dst;
; char val;
; unsigned int count;
; {
; char *start = dst;
;
; while (count--)
; *dst++ = val;
; return(start);
; }
;
;Entry:
; char *dst - pointer to memory to fill with val
; char val - value to put in dst bytes
; int count - number of bytes of dst to fill
;
;Exit:
; returns dst, with filled bytes
;
;Uses:
;
;Exceptions:
;
;*******************************************************************************
CODESEG
public memset
memset proc \
uses edi, \
dst:ptr byte, \
value:byte, \
count:IWORD
mov ecx,[count] ; cx = count
jecxz short toend ; if no work to do
; set all 4 bytes of eax to [value]
mov al,[value] ; the byte value to be stored
mov ah,al ; store it as a word
mov edx,eax ; lo 16 bits dx=ax=val/val
ror eax,16 ; move val/val to hi 16-bits
mov ax,dx ; eax = all 4 bytes = [value]
; Align address on dword boundary
mov edi,[dst] ; di = dest pointer
mov edx,edi ; dx = di = *dst
neg edx
and edx,(ISIZE-1) ; dx = # bytes before dword boundary
jz short dwords ; jump if address already aligned
cmp ecx,edx ; count >= # leading bytes??
jb short tail ; nope, just move ecx bytes
sub ecx,edx ; cx = adjusted count (for later)
xchg ecx,edx ; cx = leading byte count / dx = adjusted count
rep stosb ; store leading bytes
mov ecx,edx ; cx = count of remaining bytes
;jecxz short toend ; jump out if nothing left to do
; Move dword-sized blocks
dwords:
mov edx,ecx ; save original count
shr ecx,ISHIFT ; cx = dword count
rep stos IWORD ptr [edi] ; fill 'em up
mov ecx,edx ; retrieve original byte count
; Move remaining bytes
tail: ; store remaining 1,2, or 3 bytes
and ecx,(ISIZE-1) ; get byte count
rep stosb ; store remaining bytes, if necessary
; Done
toend:
mov eax,[dst] ; return dest pointer
ifdef _STDCALL_
ret DPSIZE + 2*ISIZE ; _stdcall return
else
ret ; _cdecl return
endif
memset endp
end