summaryrefslogtreecommitdiff
path: root/reference/C/CONTRIB/SNIP/strecpy.asm
diff options
context:
space:
mode:
Diffstat (limited to 'reference/C/CONTRIB/SNIP/strecpy.asm')
-rwxr-xr-xreference/C/CONTRIB/SNIP/strecpy.asm92
1 files changed, 92 insertions, 0 deletions
diff --git a/reference/C/CONTRIB/SNIP/strecpy.asm b/reference/C/CONTRIB/SNIP/strecpy.asm
new file mode 100755
index 0000000..223dad4
--- /dev/null
+++ b/reference/C/CONTRIB/SNIP/strecpy.asm
@@ -0,0 +1,92 @@
+ page ,132
+ title STRECPY
+COMMENT $
+ Author: Leslie Satenstein
+ A form of strcpy() where the result returned is the
+ nul terminating character of the first argument. In many cases
+ this function is move efficient than the equivalent
+ strcpy, followed by strcat.
+
+ The assembler code does a strlen followed by a memcpy,
+ and makes use of the special string move instructions
+ intrinsic to the intel 8088, 80186, 80286, '386 and '486s.
+
+ Use as: strecpy(strecpy(target,"first part"),"Second part");
+ in place of
+ strcat(strcpy(target,"first part"),"Second part");
+
+ One of the ways the C code appears is:
+ char *strecpy(char *target,const char *src)
+ {
+ return target+strlen(strcpy(target,src));
+ }
+ Another way is to do your own looping:
+
+ char *strecpy(char *target,const char *src)
+ {
+ char *cpt,*cps; /* many compilers optimise better
+ * when local pointers are declared
+ * (locals can be assigned registers)
+ */
+ cpt=target-1;
+ cps=src-1;
+ do
+ {
+ *++cpt = *++src; /* copy first, ask questions later */
+ } while(*cpt!='\0');
+ return cpt;
+ }
+
+ $
+
+; Requires MASM 5.1 or later or equivalent
+;
+; Assemble with: MASM /Mx /z ...
+; TASM /jMASM /mx /z ...
+
+% .MODEL memodel,C ;Add model support via command
+ ;line macros, e.g.
+ ;MASM /Dmemodel=LARGE,
+ ;MASM /Dmemodel=SMALL, etc.
+ PUBLIC STRECPY
+
+ .DATA
+ .CODE
+if @DataSize
+strecpy proc uses si di ds,target:FAR ptr byte,src:FAR ptr byte
+ les di,src ; load es:di with src
+ mov si,di ; put copy to bx:si
+ mov bx,es
+else
+strecpy proc uses si di,target:NEAR ptr byte,src:NEAR ptr byte
+ mov di,ds ; make es same as ds
+ mov es,di
+ mov di,src
+ mov si,di ; put copy to es:si
+endif
+ xor ax,ax ; scan for the nul at end of string
+ mov cx,-1
+ repne scasb
+ not cx ; cx = strlen(src)+1 ;
+if @Datasize
+ les di,target ; this is where copy is to begin
+ mov dx,es ; dx has segment, di has offset to target
+ mov ds,bx ; ds:si have pointer to src
+else
+ mov di,target ; this is where copy is to begin
+endif
+ test di,1 ; if we are on odd address, do one byte move
+ jz on_even
+ movsb ; now, prepare to move words at a
+ dec cx ;time to target
+on_even:
+ shr cx,1 ; carry flag has remainder after divide by 2
+ rep movsw ; move this many words
+ jnc fini ; if no carry, we are finished
+ movsb
+fini:
+ xchg di,ax ; set up return value, dx has seg value
+ dec ax ; backup to the nul character
+ ret
+strecpy endp
+ end