@wilbert: Your version is more accurate than mine because my procedure returns the number of intended char replacements, while yours returns the actual number of chars replaced.
I find that it's very inexpensive timewise to add some safety to this procedure. Basically what I'm doing is not only checking for the insertstring terminating null, but also for the targetstring null. Execution is stopped if either is found and so you'll never write past the end of the target string. It isn't going to protect you from say, passing an offset that starts past the end of the target string, passing a negative offset, etc. but the error protection it does provide is the most useful one imho.
With the following protection adjustments, I find the speed penalty well less than 5%, which at the speed this is going, shouldn't faze anyone.
Code: Select all
Procedure.l UpdateString(*target, *insert, pos.l)
EnableASM
MOV edx, *target
MOV eax, pos
CompilerIf #PB_Compiler_Unicode
!lea edx, [edx + eax * 2 - 2]
mov eax, *insert
!jmp us_unic_entry
!us_unic_loop:
!mov [edx], cx
!add eax, 2
!add edx, 2
!us_unic_entry:
!mov cx, [eax]
!and cx, cx
!mov bx, [edx] ; <--- write-past-end protection
!and bx, cx ; <--- " " " "
!jnz us_unic_loop
sub eax, *insert
!shr eax, 1
CompilerElse
!lea edx, [edx + eax - 1]
mov eax, *insert
!jmp us_ascii_entry
!us_ascii_loop:
!mov [edx], cl
!inc eax
!inc edx
!us_ascii_entry:
!mov cl, [eax]
!and cl, cl
!mov ch, [edx] ; <--- write-past-end protection
!and ch, cl ; <--- " " " "
!jnz us_ascii_loop
sub eax, *insert
CompilerEndIf
DisableASM
ProcedureReturn
EndProcedure
a$ = "Hello World!"
b$ = "Girls"
Debug UpdateString(@a$, @b$, 10)
Debug a$
Note that I'm not preserving ebx:
http://www.swansontec.com/sregisters.html wrote:
EBX - In 16-bit mode, the base register was useful as a pointer. Now it is completely free for extra storage space.
So, of all the general-purpose registers, EBX is the only register without an important dedicated purpose. It is a good place to store an extra pointer or calculation step, but not much more.
Having read this reference I concluded that it's probably ok not to preserve the ebx register. I use ebx in the unicode version of this procedure.