singrdk/base/Kernel/Native/ix64/_memset.asm

133 lines
3.8 KiB
NASM
Raw Normal View History

2008-11-17 18:29:00 -05:00
;*******************************************************************************
;memset.asm - set a section of memory to all one byte
;
; Copyright (c) Microsoft Corporation. All rights reserved.
;
;Purpose:
; contains the memset() routine
;
;*******************************************************************************
.code
;***
;char *memset(dst, value, count) - sets "count" bytes at "dst" to "value"
;
;Purpose:
; Sets the first "count" bytes of the memory starting
; at "dst" to the character value "value".
;
; Algorithm:
; char *
; memset (dst, value, count)
; char *dst;
; char value;
; unsigned int count;
; {
; char *start = dst;
;
; while (count--)
; *dst++ = value;
; return(start);
; }
;
;Entry:
; char *dst - pointer to memory to fill with value
; char value - value to put in dst bytes
; int count - number of bytes of dst to fill
;
;Exit:
; returns dst, with filled bytes
;
;Uses:
;
;Exceptions:
;
;*******************************************************************************
public memset
memset proc
;
; On entry: rcx=dest, rdx=value, r8=count
;
test r8,r8 ; 0?
jz short toend ; if so, nothing to do
xor rax,rax
mov al,dl ; al = value
mov rdx,r8 ; rdx = "count"
mov r8,rcx ; scroll away dest for return
; Align address on qword boundary
push rdi ; preserve rdi
mov rdi,rcx ; rdi = dest pointer
cmp rdx,8 ; if it's less then 8 bytes
jb tail ; tail needs rdi and rdx to be initialized
neg rcx
and rcx,7 ; ecx = # bytes before dword boundary
jz short qwords ; jump if address already aligned
sub rdx,rcx ; edx = adjusted count (for later)
adjust_loop:
mov [rdi],al
add rdi,1
sub rcx,1
jnz adjust_loop
qwords:
; set all 8 bytes of eax to [value]
mov rcx,rax ; rcx=0/0/0/0/0/0/0/value
shl rax,8 ; rax=0/0/0/0/0/0/value/0
add rax,rcx ; rax=0/0/0/0/0/0/0/val/val
mov rcx,rax ; rcx=0/0/0/0/0/0/0/val/val
shl rax,10h ; rax=0/0/0/0/val/val/0/0
add rax,rcx ; rax = all 4 bytes = [value]
mov rcx,rax ; rcx = 0/0/0/0/val/val/val/val
shl rax,20h ; rax = val/val/val/val/0/0/0/0/
add rax,rcx ; rax = val/val/val/val/val/val/val/val
; Set qword-sized blocks
mov rcx,rdx ; move original count to ecx
and rdx,7 ; prepare in edx byte count (for tail loop)
shr rcx,3 ; adjust ecx to be dword count
jz tail ; jump if it was less then 4 bytes
rep stosq
main_loop_tail:
test rdx,rdx ; if there is no tail bytes,
jz finish ; we finish, and it's time to leave
; Set remaining bytes
tail:
mov [rdi],al ; set remaining bytes
add rdi,1
sub rdx,1 ; if there is some more bytes
jnz tail ; continue to fill them
; Done
finish:
mov rax,r8 ; return dest pointer
pop rdi ; restore edi
ret
toend:
mov rax,rcx ; return dest pointer
ret
memset endp
end