{From: Joel Lichtenwalner } PROGRAM TEST_CONCAT; { TESTS VARIOUS METHODS OF CONCATENATING STRINGS } USES CRT; CONST ADD_STR : STRING[22] = 'Test string 1234567890'; TICKS = 90; { LOOP FOR APPROX 5 SECONDS } VAR CLOCK_TICKS : WORD ABSOLUTE $40:$6C; { Updated every 58 ms by system } TIME_SAVE : WORD; { Variable used to keep track of time } LOOPS : LONGINT; { Loop control counter } TARG : STRING[255]; { Target string, to be added too } COMPUTE : EXTENDED; function strcont(s1,s2:string):string; assembler; asm push ds cld lds si,s1 {Load addresses of s1} les di,s2 {Load addresses of s2} xor ah,ah {Clear ah & bh} xor bh,bh { "" } mov al,ds:[si] {Get the length of first string, copy into al} mov bl,es:[di] {Get the length of second string, copy into bl} add ax,bx {Add length of s1 to length s2} cmp ax,255 {Compare} ja @toolarge {Jump to @toolarge if length(s1)+length(s2)>255} les di,@result {Copy location of @result into es:di} mov cl,1 {Make sure at least one byte of beginning string} xor ch,ch {is transferred to @result.} add cl,ds:[si] {Add length of string to cl.} rep movsb {Copy first string into @result} lds si,s2 {Get address of second string} mov cl,ds:[si] {Get length of second string, copy into cl} cmp cl,0 {If second string is blank, skip adding it.} je @end {Jump to end if length of second string is zero.} inc si {Move pointer (si) to start of second string} mov al,cl {Save length of second string in al} rep movsb {Copy second string into @result} lds si,@result {Get location of @result} add ds:[si],al {Add lengths together} jmp @end {Skip to end} @toolarge: {If added strings total larger than 255, this sub} les di,@result {is called.} xor al,al {Make sure al is a zero.} mov es:[di],al {Move a "0" into the beginning of @result, making it} @end: {a null string.} pop ds {Return DS to normal so Pascal doesn't screw up.} end; PROCEDURE ATTACH(VAR DEST,SOURCE:STRING); VAR DESTL : BYTE ABSOLUTE DEST; SOURCEL : BYTE ABSOLUTE SOURCE; BEGIN MOVE(SOURCE[1],DEST[SUCC(DESTL)],SOURCEL); INC(DESTL,SOURCEL); END; BEGIN CLRSCR; WRITELN('Test concatenation functions'); { -------- FIRST TEST -------- } WRITE('Testing Pascal''s "+" function'); LOOPS := 0; TIME_SAVE := CLOCK_TICKS; { WAIT UNTIL THE CLOCK TURNS OVER } REPEAT UNTIL CLOCK_TICKS <> TIME_SAVE; TIME_SAVE := CLOCK_TICKS + TICKS; { Set loop time } REPEAT TARG := ''; TARG := TARG + ADD_STR; { 22 } TARG := TARG + ADD_STR; { 44 } TARG := TARG + ADD_STR; { 66 } TARG := TARG + ADD_STR; { 88 } TARG := TARG + ADD_STR; { 110 } TARG := TARG + TARG; { 220 } TARG := TARG + ADD_STR; { 242 } INC(LOOPS); UNTIL CLOCK_TICKS = TIME_SAVE; COMPUTE := LOOPS; COMPUTE := COMPUTE / TICKS; WRITELN(' Performance = ',COMPUTE:0:6,' Loops per tick'); { -------- SECOND TEST -------- } WRITE('Testing STRCONT function'); LOOPS := 0; TIME_SAVE := CLOCK_TICKS; { WAIT UNTIL THE CLOCK TURNS OVER } REPEAT UNTIL CLOCK_TICKS <> TIME_SAVE; TIME_SAVE := CLOCK_TICKS + TICKS; { Set loop time } REPEAT TARG := ''; TARG := strcont(TARG,ADD_STR); { 22 } TARG := strcont(TARG,ADD_STR); { 44 } TARG := strcont(TARG,ADD_STR); { 66 } TARG := strcont(TARG,ADD_STR); { 88 } TARG := strcont(TARG,ADD_STR); { 110 } TARG := strcont(TARG,TARG); { 220 } TARG := strcont(TARG,ADD_STR); { 242 } INC(LOOPS); UNTIL CLOCK_TICKS = TIME_SAVE; COMPUTE := LOOPS; COMPUTE := COMPUTE / TICKS; WRITELN(' Performance = ',COMPUTE:0:6,' Loops per tick'); { -------- THIRD TEST -------- } WRITE('Testing ATTACH procedure '); LOOPS := 0; TIME_SAVE := CLOCK_TICKS; { WAIT UNTIL THE CLOCK TURNS OVER } REPEAT UNTIL CLOCK_TICKS <> TIME_SAVE; TIME_SAVE := CLOCK_TICKS + TICKS; { Set loop time } REPEAT TARG := ''; ATTACH(TARG,ADD_STR); { 22 } ATTACH(TARG,ADD_STR); { 44 } ATTACH(TARG,ADD_STR); { 66 } ATTACH(TARG,ADD_STR); { 88 } ATTACH(TARG,ADD_STR); { 110 } ATTACH(TARG,TARG); { 220 } ATTACH(TARG,ADD_STR); { 242 } INC(LOOPS); UNTIL CLOCK_TICKS = TIME_SAVE; COMPUTE := LOOPS; COMPUTE := COMPUTE / TICKS; WRITELN(' Performance = ',COMPUTE:0:6,' Loops per tick'); READLN; END.