
c语言的memset到底是怎么实现的 是c标准库里面写的这样么 10
展开全部
memset在不同编译器里面实现方式是不一样的
不过 都要比你提供的几种要复杂 而且高效。
有些平台甚至是用汇编写的。
提供几种做参考:
void * __cdecl memset (
void *dst,
int val,
size_t count
)
{
void *start = dst;
#if defined (_M_IA64) || defined (_M_AMD64)
{
__declspec(dllimport)
void RtlFillMemory( void *, size_t count, char );
RtlFillMemory( dst, count, (char)val );
}
#else /* defined (_M_IA64) || defined (_M_AMD64) */
while (count--) {
*(char *)dst = (char)val;
dst = (char *)dst + 1;
}
#endif /* defined (_M_IA64) || defined (_M_AMD64) */
return(start);
}
#include <linux/types.h>
#include <asm/string.h>
#define OPSIZ (BITS_PER_LONG/8)
typedef unsigned long op_t;
void *
memset (void *dstpp, int sc, size_t len)
{
unsigned int c = sc;
long int dstp = (long int) dstpp;
if (len >= 8)
{
size_t xlen;
op_t cccc;
cccc = (unsigned char) c;
cccc |= cccc << 8;
cccc |= cccc << 16;
if (OPSIZ > 4)
/* Do the shift in two steps to avoid warning if long has 32 bits. */
cccc |= (cccc << 16) << 16;
/* There are at least some bytes to set.
No need to test for LEN == 0 in this alignment loop. */
while (dstp % OPSIZ != 0)
{
((unsigned char *) dstp)[0] = c;
dstp += 1;
len -= 1;
}
/* Write 8 `op_t' per iteration until less than 8 `op_t' remain. */
xlen = len / (OPSIZ * 8);
while (xlen > 0)
{
((op_t *) dstp)[0] = cccc;
((op_t *) dstp)[1] = cccc;
((op_t *) dstp)[2] = cccc;
((op_t *) dstp)[3] = cccc;
((op_t *) dstp)[4] = cccc;
((op_t *) dstp)[5] = cccc;
((op_t *) dstp)[6] = cccc;
((op_t *) dstp)[7] = cccc;
dstp += 8 * OPSIZ;
xlen -= 1;
}
len %= OPSIZ * 8;
/* Write 1 `op_t' per iteration until less than OPSIZ bytes remain. */
xlen = len / OPSIZ;
while (xlen > 0)
{
((op_t *) dstp)[0] = cccc;
dstp += OPSIZ;
xlen -= 1;
}
len %= OPSIZ;
}
/* Write the last few bytes. */
while (len > 0)
{
((unsigned char *) dstp)[0] = c;
dstp += 1;
len -= 1;
}
return dstpp;
}
CODESEG
extrn _VEC_memzero:near
extrn __sse2_available:dword
public memset
memset proc \
dst:ptr byte, \
value:byte, \
count:dword
OPTION PROLOGUE:NONE, EPILOGUE:NONE
.FPO ( 0, 3, 0, 0, 0, 0 )
mov edx,[esp + 0ch] ; edx = "count"
mov ecx,[esp + 4] ; ecx points to "dst"
test edx,edx ; 0?
jz short toend ; if so, nothing to do
xor eax,eax
mov al,[esp + 8] ; the byte "value" to be stored
; Special case large block zeroing using SSE2 support
test al,al ; memset using zero initializer?
jne dword_align
cmp edx,0100h ; block size exceeds size threshold?
jb dword_align
cmp DWORD PTR __sse2_available,0 ; SSE2 supported?
je dword_align
jmp _VEC_memzero ; use fast zero SSE2 implementation
; no return
; Align address on dword boundary
dword_align:
push edi ; preserve edi
mov edi,ecx ; edi = dest pointer
cmp edx,4 ; if it's less then 4 bytes
jb tail ; tail needs edi and edx to be initialized
neg ecx
and ecx,3 ; ecx = # bytes before dword boundary
jz short dwords ; jump if address already aligned
sub edx,ecx ; edx = adjusted count (for later)
adjust_loop:
mov [edi],al
add edi,1
sub ecx,1
jnz adjust_loop
dwords:
; set all 4 bytes of eax to [value]
mov ecx,eax ; ecx=0/0/0/value
shl eax,8 ; eax=0/0/value/0
add eax,ecx ; eax=0/0val/val
mov ecx,eax ; ecx=0/0/val/val
shl eax,10h ; eax=val/val/0/0
add eax,ecx ; eax = all 4 bytes = [value]
; Set dword-sized blocks
mov ecx,edx ; move original count to ecx
and edx,3 ; prepare in edx byte count (for tail loop)
shr ecx,2 ; adjust ecx to be dword count
jz tail ; jump if it was less then 4 bytes
rep stosd
main_loop_tail:
test edx,edx ; if there is no tail bytes,
jz finish ; we finish, and it's time to leave
; Set remaining bytes
tail:
mov [edi],al ; set remaining bytes
add edi,1
sub edx,1 ; if there is some more bytes
jnz tail ; continue to fill them
; Done
finish:
mov eax,[esp + 8] ; return dest pointer
pop edi ; restore edi
ret
toend:
mov eax,[esp + 4] ; return dest pointer
ret
memset endp
end
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询
广告 您可能关注的内容 |