With the new syntax for PB compilers I can write code in MASM and port it directly to PB as long as it is low level mnemonic code with no change apart from things like masm's anonymous labels and hex notation.
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
' -------------------
' build with PBWIN 10
' -------------------
FUNCTION PBmain as LONG
LOCAL rval as DWORD
LOCAL wszStr as WSTRINGZ * 64
wszStr = "1234567890"
! lea eax, wszStr
! push eax
! call uc_len
! mov rval, eax
msgbox format$(rval)
wszStr = "1234567890"
! push 6
! lea eax, wszStr
! push eax
! call uc_left
msgbox wszStr
wszStr = "1234567890"
! push 6
! lea eax, wszStr
! push eax
! call uc_right
msgbox wszStr
wszStr = "1234567890"
! lea eax, wszStr
! push eax
! call uc_reverse
msgbox wszStr
wszStr = " 1234567890"
! lea eax, wszStr
! push eax
! call uc_ltrim
msgbox wszStr
wszStr = "1234567890 "
! lea eax, wszStr
! push eax
! call uc_rtrim
msgbox wszStr
wszStr = " 1234567890 "
! lea eax, wszStr
! push eax
! call uc_trim
msgbox wszStr
LOCAL txt1 as WSTRINGZ * 32
LOCAL txt2 as WSTRINGZ * 32
LOCAL txt3 as WSTRINGZ * 32
LOCAL trv as DWORD
txt1 = "text one"
txt2 = "text two"
! lea eax, txt2
! push eax
! lea eax, txt1
! push eax
! call uc_cmp
! mov trv, eax
msgbox format$(trv)
! lea eax, txt1
! push eax
! lea eax, txt1
! push eax
! call uc_cmp
! mov trv, eax
msgbox format$(trv)
wszStr = "Original String"
txt1 = " Next String "
txt2 = " Last String"
! lea eax, txt1
! push eax
! lea eax, wszStr
! push eax
! call uc_cat
msgbox wszStr
! lea eax, txt2
! push eax
! lea eax, wszStr
! push eax
! call uc_cat
msgbox wszStr
LOCAL esp_ as DWORD
wszStr = ""
txt1 = "Original String"
txt2 = " Next String"
txt3 = " Last String"
! lea eax, txt3
! push eax
! lea eax, txt2
! push eax
! lea eax, txt1
! push eax
! lea eax, wszStr
! push eax
! push 3
! call uc_multicat
! add esp, 20
msgbox wszStr
End FUNCTION
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FASTPROC uc_len
PREFIX "! "
mov eax, [esp+4] ; load the string address
sub eax, 2 ; set up the address for loop entry
lbl0:
add eax, 2 ; increment up to the next WORD sized character
cmp WORD PTR [eax], 0 ; test if UNICODE character is terminator
jne lbl0 ; loop back if not
sub eax, [esp+4] ; sub the start address from EAX
shr eax, 1 ; half the result for UNICODE length
ret 4 ; return while balancing the stack
END PREFIX
END FASTPROC
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FASTPROC uc_left
PREFIX "! "
mov eax, [esp+4] ; string address
mov ecx, [esp+8] ; char count
sub eax, 2 ; set up the address for loop entry
lbl0:
add eax, 2
cmp WORD PTR [eax], 0 ; exit if zero is found before required length
je lblout
sub ecx, 1
jns lbl0
mov WORD PTR [eax], 0 ; else truncate the string
lblout:
ret 8
END PREFIX
END FASTPROC
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FASTPROC uc_right
PREFIX "! "
mov eax, [esp+4] ; load address into EAX
push eax ; push it onto the stack
call uc_len ; get the string length
cmp eax, [esp+8] ; compare it against required length
ja lbl0 ; if its greater that required, proceed.
ret 8 ; else exit with no change
lbl0:
sub eax, [esp+8] ; calculate the OFFSET for the 1st required character
add eax, eax ; double it for 2 byte UNICODE character
mov ecx, [esp+4] ; load the string address in both source and destination registers
mov edx, [esp+4]
add ecx, eax ; add the 1st character OFFSET to the source register
lbl1:
movzx eax, WORD PTR [ecx] ; load each UNICODE character into EBX
mov WORD PTR [edx], ax ; copy it to the destination register
add ecx, 2 ; add 2 for next UNICODE character location
add edx, 2
test eax, eax ; test if last written character is zero.
jnz lbl1 ; loop back if not
ret 8 ; balance the stack and return
END PREFIX
END FASTPROC
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FASTPROC uc_reverse
PREFIX "! "
push ebx
push esi
mov eax, [esp+12] ; load src address into EAX ([esp+4] plus 8 {2 pushes})
push eax
call uc_len
mov esi, eax ; write char count to ESI
shr esi, 1 ; int divide it by 2
add eax, eax ; double UNICODE length to get offset of end
mov ecx, [esp+12]
mov edx, [esp+12]
add edx, eax ; add the OFFSET to get end character
sub edx, 2
; read 1st and last chars then swap them then read
; next inner pair until middle of string is reached
lbl0:
movzx eax, WORD PTR [ecx]
movzx ebx, WORD PTR [edx]
mov [ecx], bx
mov [edx], ax
add ecx, 2
sub edx, 2
sub esi, 1
jnz lbl0
pop esi
pop ebx
ret 4 ; balance the stack and return
END PREFIX
END FASTPROC
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FASTPROC uc_ltrim
PREFIX "! "
mov eax, [esp+4] ; load the stack variable into EAX
mov ecx, [esp+4] ; load the stack variable into ECX
sub eax, 2
lbl0:
add eax, 2
cmp WORD PTR [eax], 32 ; strip space
je lbl0
cmp WORD PTR [eax], 9 ; strip tab
je lbl0
; ------------------------------------------
; copy the rest back to string start address
; ------------------------------------------
lbl1:
movzx edx, WORD PTR [eax] ; zero extend WORD into EDX
mov WORD PTR [ecx], dx ; write it back to same buffer
add eax, 2
add ecx, 2
test edx, edx ; test for zero after it is written
jnz lbl1 ; loop back if not zero
ret 4 ; balance the stack and return
END PREFIX
END FASTPROC
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FASTPROC uc_rtrim
PREFIX "! "
mov ecx, [esp+4] ; load string address in ECX
xor edx, edx ; zero EDX
sub ecx, 2
lbl0:
add ecx, 2
cmp WORD PTR [ecx], 0 ; exit loop on zero
je lbl2
cmp WORD PTR [ecx], 32 ; loop back on space
je lbl0
cmp WORD PTR [ecx], 9 ; loop back on tab
je lbl0
lbl1:
mov edx, ecx ; else write last char address to EDX
jmp lbl0
lbl2:
test edx, edx ; test if EDX has been modified
jz lbl3
mov WORD PTR [edx+2], 0 ; if it has, write terminator 1 char after
lbl3: ' last non space/tab char
ret 4 ; balance the stack and return
END PREFIX
END FASTPROC
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FASTPROC uc_trim
PREFIX "! "
mov eax, [esp+4]
push eax
call uc_ltrim
mov eax, [esp+4]
push eax
call uc_rtrim
ret 4 ; balance the stack and return
END PREFIX
END FASTPROC
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FASTPROC uc_cmp
PREFIX "! "
push edi
mov edx, [esp+8]
mov edi, [esp+12]
mov eax, -2
xor ecx, ecx
lbl0:
add eax, 2
movzx ecx, WORD PTR [edx+eax] ; load each char
cmp cx, [edi+eax] ; compare it to char in other string
jne mismatch
test ecx, ecx
jnz lbl0
shr eax, 1 ; half for character count on match
jmp match
mismatch:
xor eax, eax ; zero for mismatch
match:
pop edi
ret 8 ; balance the stack and return
END PREFIX
END FASTPROC
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FASTPROC uc_cat
PREFIX "! "
mov edx, [esp+4]
sub edx, 2
mov ecx, [esp+8]
xor eax, eax
lbl0:
add edx, 2
cmp WORD PTR [edx], 0 ; find the end
jne lbl0
lbl1:
mov ax, [ecx] ; append 2nd string
mov [edx], ax
add ecx, 2
add edx, 2
test ax, ax
jnz lbl1
ret 8
END PREFIX
END FASTPROC
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
' ucMultiCat proc C pcount:DWORD,lpBuffer:DWORD,args:VARARG
FASTPROC uc_multicat
PREFIX "! "
push esi
push edi
xor eax, eax ; clear EAX for following partial reads and writes
mov edi, [esp+8][8] ; lpBuffer
xor ecx, ecx ; clear arg counter
lea edx, [esp+12][8] ; args
sub edi, 2
lbl0:
add edi, 2
mov ax, [edi]
test ax, ax
jne lbl0
newstr:
sub edi, 2
mov esi, [edx+ecx*4]
lbl1:
add edi, 2
mov ax, [esi]
mov [edi], ax
add esi, 2
test ax, ax
jne lbl1
add ecx, 1
cmp ecx, [esp+4][8] ; pcount
jne newstr
mov eax, [esp+8][8] ; lpBuffer
pop edi
pop esi
ret ; stack must be corrected by caller
END PREFIX
END FASTPROC
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤