面试的时候被要求写strncpy函数,其实之前看过这题目,不过本人水平太渣对c++的字符串很不了解,当时只是看了下好像说是什么内存重叠问题,就想着以后看到字符串再写,结果就是一下子懵了,最后颤抖着将只有两行代码的白纸交了上去。面试官好心地试图提示我考点,但是我根本反应不过来,最后直接跪了orz
所以说实力才是面试成功的保证啊
page ,132
title memcpy - Copy source memory bytes to destination
;***
;memcpy.asm - contains memcpy and memmove routines
;
; Copyright (c) Microsoft Corporation. All rights reserved.
;
;Purpose:
; memcpy() copies a source memory buffer to a destination buffer.
; Overlapping buffers are not treated specially, so propogation may occur.
; memmove() copies a source memory buffer to a destination buffer.
; Overlapping buffers are treated specially, to avoid propogation.
;
;*******************************************************************************
.xlist
include cruntime.inc
.list
M_EXIT macro
ret ; _cdecl return
endm ; M_EXIT
CODESEG
extrn _VEC_memcpy:near
extrn __sse2_available:dword
page
;***
;memcpy - Copy source buffer to destination buffer
;
;Purpose:
; memcpy() copies a source memory buffer to a destination memory buffer.
; This routine does NOT recognize overlapping buffers, and thus can lead
; to propogation.
; For cases where propogation must be avoided, memmove() must be used.
;
; Algorithm:
;
; Same as memmove. See Below
;
;
;memmove - Copy source buffer to destination buffer
;
;Purpose:
; memmove() copies a source memory buffer to a destination memory buffer.
; This routine recognize overlapping buffers to avoid propogation.
; For cases where propogation is not a problem, memcpy() can be used.
;
; Algorithm:
;
; void * memmove(void * dst, void * src, size_t count)
; {
; void * ret = dst;
;
; if (dst <= src || dst >= (src + count)) {
; /*
; * Non-Overlapping Buffers
; * copy from lower addresses to higher addresses
; */
; while (count--)
; *dst++ = *src++;
; }
; else {
; /*
; * Overlapping Buffers
; * copy from higher addresses to lower addresses
; */
; dst += count - 1;
; src += count - 1;
;
; while (count--)
; *dst-- = *src--;
; }
;
; return(ret);
; }
;
;
;Entry:
; void *dst = pointer to destination buffer
; const void *src = pointer to source buffer
; size_t count = number of bytes to copy
;
;Exit:
; Returns a pointer to the destination buffer in AX/DX:AX
;
;Uses:
; CX, DX
;
;Exceptions:
;*******************************************************************************
ifdef MEM_MOVE
_MEM_ equ <memmove>
else ; MEM_MOVE
_MEM_ equ <memcpy>
endif ; MEM_MOVE
% public _MEM_
_MEM_ proc \
dst:ptr byte, \
src:ptr byte, \
count:IWORD
; destination pointer
; source pointer
; number of bytes to copy
; push ebp ;U - save old frame pointer
; mov ebp, esp ;V - set new frame pointer
push edi ;U - save edi
push esi ;V - save esi
mov esi,[src] ;U - esi = source
mov ecx,[count] ;V - ecx = number of bytes to move
mov edi,[dst] ;U - edi = dest
;
; Check for overlapping buffers:
; If (dst <= src) Or (dst >= src + Count) Then
; Do normal (Upwards) Copy
; Else
; Do Downwards Copy to avoid propagation
;
mov eax,ecx ;V - eax = byte count...
mov edx,ecx ;U - edx = byte count...
add eax,esi ;V - eax = point past source end
cmp edi,esi ;U - dst <= src ?
jbe short CopyUp ;V - yes, copy toward higher addresses
cmp edi,eax ;U - dst < (src + count) ?
jb CopyDown ;V - yes, copy toward lower addresses
;
; Copy toward higher addresses.
;
CopyUp:
;
; First, see if we can use a "fast" copy SSE2 routine
; block size greater than min threshold?
cmp ecx,080h
jb Dword_align
; SSE2 supported?
cmp DWORD PTR __sse2_available,0
je Dword_align
; alignments equal?
push edi
push esi
and edi,15
and esi,15
cmp edi,esi
pop esi
pop edi
jne Dword_align
; do fast SSE2 copy, params already set
jmp _VEC_memcpy
; no return
;
; The algorithm for forward moves is to align the destination to a dword
; boundary and so we can move dwords with an aligned destination. This
; occurs in 3 steps.
;
; - move x = ((4 - Dest & 3) & 3) bytes
; - move y = ((L-x) >> 2) dwords
; - move (L - x - y*4) bytes
;
Dword_align:
test edi,11b ;U - destination dword aligned?
jnz short CopyLeadUp ;V - if we are not dword aligned already, align
shr ecx,2 ;U - shift down to dword count
and edx,11b ;V - trailing byte count
cmp ecx,8 ;U - test if small enough for unwind copy
jb short CopyUnwindUp ;V - if so, then jump
rep movsd ;N - move all of our dwords
jmp dword ptr TrailUpVec[edx*4] ;N - process trailing bytes
_________________________________________________________________
下面为strncpy和strcpy函数
#include <iostream>
#include <assert.h>
using namespace std;
char* strncpy(char *dst,char *src,size_t count)
{
assert(dst!=NULL);
assert(src!=NULL);
assert(count>=0);
char *ret=dst;
if(dst<=src||dst>=src+count)
{
while(count--)*dst++=*src++;
}
else
{
dst+=count-1;
src+=count-1;
while(count--)*dst--=*src--;
}
return ret;
}
//而且dst的空间不一定足以放下src字符串啊?考虑用strlen()、Cstring s=src s.GetLength();、memsize(const char*)查分配内存数量、_tcslen(str)
//但是网上找的各种答案里面都不考虑dst空间不足的问题,下面是最后的参考代码...
char* strcpy(char *dst,const char *src)
{
assert(dst!=NULL);
assert(src!=NULL);
char *ret=dst;
strncpy(dst,src,strlen(src)+1);
return ret;
}
int main()
{
try
{
char dest[6];
char *src="hello";
printf("%s\n",strcpy(dest,src));
cin.get();
}
catch(char *a){cout<<a<<endl;cin.get();}
}
;未完待续