In this tutorial, we explore two fundamental data structures provided by FreshLib: Vectors (dynamic arrays) and HashTables (static Pearsons hash). These structures are essential for managing dynamic content and performing fast lookups in assembly applications.
Topics Covered
Dynamic Arrays (Vectors) - Using the TArray structure.
Array Lifecycle - Creation, allocation, and cleanup.
Element Management - Adding, inserting, and deleting items.
Static HashTables - Building and searching using PHashTable.
Pearson's Hash - Understanding the case-insensitive hash used in FreshLib.
Dynamic Arrays (TArray)
FreshLib's TArray is a dynamic array (vector) that grows as needed. It stores a count of elements, current capacity, and item size.
struct TArray
.count dd ? ; Count of elements in dynamic array
.capacity dd ? ; Capacity of the array allocated memory.
.itemsize dd ? ; Size of one element in dwords.
.lparam dd ? ; User defined value.
label .array dword ; Start of actual data
ends
Essential TArray Functions
Function
Purpose
CreateArray
Creates a new array with specified item size.
AddArrayItems
Adds one or more items to the end of the array.
InsertArrayItems
Inserts items at a specific index.
DeleteArrayItems
Removes items from the array.
GetArrayItem
Retrieves a pointer to an item at an index.
FreeMem
Used to free the array memory (as CreateArray uses heap).
TArray elements are always dword-aligned. The itemsize argument is in bytes, but internal storage is dword-based.
HashTables (PHashTable)
FreshLib uses a static Pearson's hash table for fast keyword lookups. This pattern is extensively used in AsmBB for API command routing and template tag processing.
The PHashTable Macro
The PHashTable macro builds a static table of 256 items. It requires a Pearson's hash function table (tpl_func) to operate.
Searching is typically performed by a helper function like SearchInHashTable. It computes the hash of a string and lookups the corresponding entry in the table.
stdcall SearchInHashTable, hCommand, tableAPICommands
; Returns proc address in ECX if found, CF=1
Demo Programs
Demo 20: Vector Basics
File: demo20_vector_basics.asm
Demonstrates creating a dynamic array of string handles, adding items, and iterating through them. This pattern is used in AsmBB for tracking open SQLite statements.
Demo 21: HashTable Basics
File: demo21_hashtable_basics.asm
Demonstrates building a static lookup table for commands and searching it using a Pearson's hash. This is the exact pattern used for AsmBB's FastCGI command routing.
Critical Implementation Notes
Register Preservation: FreshLib procedures do NOT preserve EAX, ECX, EDX, or ESI. Any pointer returned by a procedure (e.g., StrPtr, GetArrayItem) must be saved before calling another procedure.
Pattern: Preserving Pointers Across Calls
; ❌ WRONG - EAX is clobbered after FileWriteString
stdcall StrPtr, ebx
stdcall FileWriteString, 1, msg_dash
stdcall FileWriteString, 1, eax ; SEGFAULT! eax was destroyed
; ✅ CORRECT - Push/pop to preserve EAX
stdcall StrPtr, ebx
push eax ; Save pointer
stdcall FileWriteString, 1, msg_dash
pop eax ; Restore pointer
stdcall FileWriteString, 1, eax
Pattern: AddArrayItems Returns New Handle
When adding items, the array may be reallocated. Always update your handle from EDX:
stdcall StrDupMem, s_item1 ; EAX = string handle
push eax
stdcall AddArrayItems, ebx, 1
mov ebx, edx ; EDX = potentially new array handle
pop dword [eax] ; EAX = pointer to new element