String Operations

Description

PowerBASIC provides built-in string operations for concatenation, assignment, length retrieval, pointer access, and comparison. All strings are NUL-terminated (C-compatible) and stored in stack-local or heap-allocated buffers.

Syntax

Concatenation: result$ = a$ + b$ [+ c$ ...]
Assignment: dest$ = expr$
Length: LEN(string$)
String pointer: STRPTR(string$)
Variable pointer: VARPTR(variable)
Comparison: a$ = b$   a$ < b$   a$ > b$

Parameters

ParameterDescription
string$Any valid STRING expression or variable
variableAny variable (STRING or numeric); VARPTR returns its address
a$, b$, c$STRING operands to concatenate

String Concatenation (+)

Syntax: result$ = a$ + b$ [+ c$ ...]
Source: pb_cg_emit_string_concat_to_heap_temp (pb_codegen.c:3648)

Example

LOCAL a$, b$, c$ AS STRING
a$ = "Hello"
b$ = " World"
c$ = a$ + b$          ' c$ = "Hello World"

Phase 1 - Compute Total Length

xor    rax, rax
; For each part: get address -> RAX, length -> R10
mov    [rbp - ptr_offset_i], rax       ; save part pointer
mov    [rbp - len_offset_i], r10       ; save part length
add    [rbp - total_bytes], r10        ; total += len

Phase 2 - Allocate + Copy

mov    rcx, [rbp - total_bytes]
add    rcx, 8                          ; + padding for NUL
call   [__imp_malloc]                  ; allocate buffer
mov    [rbp - out_ptr], rax
; For each part:
mov    rcx, [rbp - out_ptr]
add    rcx, [rbp - write_pos]          ; dest = base + pos
mov    rdx, [rbp - ptr_offset_i]       ; src = part data
mov    r8, [rbp - len_offset_i]        ; count = part length
call   [__imp_memcpy]                  ; copy
add    [rbp - write_pos], r8           ; pos += len
; NUL-terminate:
mov    r11, [rbp - out_ptr]
add    r11, [rbp - total_bytes]
mov    byte [r11], 0

String Assignment (to local STRING)

Source: pb_cg_emit_string_expr_to_descriptor (pb_codegen.c:3910)

Example

LOCAL s AS STRING
s = "Hello World"       ' literal assignment
s = someFunction$()     ' expression result assignment
; String literal assignment: lstrcpynA
lea    rcx, [rbp - dest_offset]        ; dest buffer
mov    rdx, [rbp - print_ptr_offset]   ; source ptr
mov    r8, capacity                    ; max chars
call   [__imp_lstrcpynA]

; String expression assignment: malloc + memcpy + descriptor update

LEN()

Syntax: LEN(string$)
Source: pb_cg_emit_len_builtin (pb_codegen.c:4108)

Description

Returns the number of characters in string$ (excluding NUL terminator). For a string literal the length is a compile-time constant.

Example

LOCAL s, n AS STRING
s = "Hello"
n = LEN(s)              ' n = 5
; String literal: constant
mov    rax, <literal_length>

; Local STRING: load from descriptor
mov    rax, [rbp - length_offset]       ; length slot in frame

; STATIC/GLOBAL STRING: load from static data
mov    rax, [<label>_len]

STRPTR()

Syntax: STRPTR(string$)
Source: pb_cg_emit_strptr_builtin (pb_codegen.c:4130)

Description

Returns the memory address of the string data (a pointer to the first character). Useful when calling external DLL functions that expect a char*.

Example

LOCAL s AS STRING, p AS DWORD
s = "Hello"
p = STRPTR(s)           ' p = address of 'H'
; Local STRING: load data pointer from descriptor
mov    rax, [rbp - offset]              ; string data pointer

; BYREF STRING: dereference pointer
mov    r11, [rbp - offset]              ; get pointer-address
mov    rax, [r11]                       ; deref to data pointer

; Concatenation expression: scratch buffer address
lea    rax, [rbp - asciiz_scratch_offset]

VARPTR()

Syntax: VARPTR(variable)
Source: pb_cg_emit_varptr_builtin (pb_codegen.c:4140)

Description

Returns the memory address of any variable. For a STRING variable this returns the address of the string descriptor, not the string data (use STRPTR for that).

Example

LOCAL x AS LONG, p AS DWORD
x = 42
p = VARPTR(x)           ' p = stack address of x
; Stack local: LEA for address
lea    rax, [rbp - var_offset]

; BYREF parameter: already an address
mov    rax, [rbp - param_offset]

; STATIC/GLOBAL: LEA for static label
lea    rax, [static_label]

; Array element: compute element address
mov    rax, r11                         ; from pb_cg_emit_array_address

String Comparison

Source: pb_cg_emit_string_comparison_expr (pb_codegen.c:4930)

Description

String comparison is case-sensitive and lexicographic. It first compares the common prefix via memcmp, then falls back to length comparison if the prefix is identical. Supports all relational operators: =, <>, <, >, <=, >=.

Example

LOCAL a$, b$ AS STRING
a$ = "Apple"
b$ = "Banana"
IF a$ < b$ THEN PRINT "Apple comes first"   ' true
; Compare first min(lenL, lenR) bytes with memcmp
mov    rcx, [rbp - left_ptr]
mov    rdx, [rbp - right_ptr]
mov    r8, min_len
call   [__imp_memcmp]
movsxd rax, eax                        ; sign-extend 32-bit result
cmp    rax, 0
jne    __pb_str_cmp_ready_N            ; different -> use memcmp result
; Prefix equal, compare lengths:
mov    rax, [rbp - left_len]
cmp    rax, [rbp - right_len]
; 0 if equal, -1 if left shorter, 1 if left longer
; Then comparison jump: je/jne/jl/jg/jle/jge __pb_str_true_N