Tvůrce webu je i pro tebe! Postav třeba web. Bez grafika. Bez kodéra. Hned.
wz

Obsah / Utility / TEXT / TextFindWordFirst, TextFindWord

Zdrojový kód: INCLUDE\UTIL\TEXT.INC, UTIL\TEXT.ASM


TextFindWordFirst, TextFindWord - Vyhledání prvního/dalšího slova v textu

Funkce TextFindWordFirst vyhledá v textu první výskyt daného slova (2 bajtů). Funkce TextFindWord vyhledá první výskyt slova (2 bajtů) od dané pozice v textu (včetně).


; -----------------------------------------------------------------------------
;                  Find 2 bytes in text in forward direction
; -----------------------------------------------------------------------------
; INPUT:	AL = first byte of string to find
;		AH = second byte of string to find
;		EBX = pointer to TEXT
;		EDX = start offset (it can be out of range)
; OUTPUT:	EDX = offset of found bytes (or EDX = -1 if data not found)
;		CY = data not found (EDX = -1)
; NOTES:	Set EDX to 0 to find first occurrence of the bytes.
; -----------------------------------------------------------------------------

; ------------- Find first occurrence of 2 bytes

TextFindWordFirst:
		xor	edx,edx		; EDX <- 0, find first occurrence

Na vstupu funkce obsahuje registr AL hodnotu prvního bajtu a registr AH hodnotu druhého bajtu k vyhledání. Registr EBX obsahuje ukazatel na textovou proměnnou s textem k prohledání. Registr EDX obsahuje počáteční offset v textu, od kterého budou bajty vyhledávány. V případě funkce TextFindWordFirst je obsah registru EDX nejdříve vynulován, čímž se zajistí nastavení ukazatele na začátek textu.

Jsou-li bajty v textu nalezeny, je navrácena v registru EDX pozice (offset) bajtů v textu a příznak CF je vynulován. Nejsou-li bajty nalezeny, je v registru EDX navrácena hodnota -1 a je navrácen příznak chyby CY.


; ------------- Push registers

TextFindWord:	push	ecx		; push ECX
		push	edi		; push EDI

; ------------- Limit minimal offset to 0 (-> EDX)

		or	edx,edx		; is start offset negative?
		sets	cl		; CL <- 0 if EDX >= 0, 1 if EDX < 0
		movzx	ecx,cl		; ECX <- 0 if EDX >= 0, 1 if EDX < 0
		dec	ecx		; ECX <- -1 if EDX >= 0, 0 if EDX < 0
		and	edx,ecx		; EDX <- 0 if EDX < 0

Po úschově registrů bude omezen minimální počáteční offset v textu (aby neukazoval pod hodnotu 0). Pro zrychlení kódu se nepoužije instrukce skoku, ale využijí se operace s registry. Po testu obsahu registru EDX se nastaví obsah registru CL na hodnotu 0, pokud byl offset nezáporný, nebo 1, pokud byl offset záporný. Po rozšíření hodnoty do registru ECX a dekrementaci bude registr ECX obsahovat hodnotu -1 (tj. 0FFFFFFFFh) pokud byl offset nezáporný, nebo hodnotu 0, pokud byl offset záporný. Zamaskováním offsetu v registru EDX registrem ECX se zajistí vynulování obsahu registru EDX v případě, že offset byl záporný.


; ------------- Get text length (-> ECX) and text address (-> EDI)

		mov	edi,[ebx]	; EDI <- data buffer
		mov	ecx,[edi+TEXT_Length] ; ECX <- length of text
		dec	ecx		; ECX <- without last byte
		lea	edi,[edi+TEXT_Text+edx] ; EDI <- start pointer

Do registru ECX se připraví celková délka prohledávaného textu (v bajtech) snížená o 1 bajt (což je rezerva pro druhý hledaný bajt) a do registru EDI ukazatel na začátek prohledávaného textu (posunutý na počáteční pozici k prohledání).


; ------------- Find data

		sub	ecx,edx		; ECX <- remaining data
		jle	short TextFindWord6 ; data not found
TextFindWord2:	repne	scasb		; find data
		jne	short TextFindWord6 ; data not found
		cmp	ah,[edi]	; check second byte
		jne	TextFindWord2	; continue searching

Odečtením pozice počátku textu zůstane v registru ECX počet zbylých bajtů k prohledání - při podtečení se funkce ukončí s navrácením příznaku chyby CY a s hodnotou -1 v registru EDX. Je-li počet bajtů kladný, vyhledá se první bajt v textu. Nebyl-li nalezen (instrukce SCASB navrátí příznak NZ) funkce se opět ukončí s příznakem chyby CY a hodnotou -1 v registru EDX. Pokud byl první bajt nalezen, otestuje se druhý bajt. Jestliže druhý bajt nesouhlasí, pokračuje se vyhledáváním prvního bajtu od další pozice v textu.


; ------------- Get offset of data

		inc	ecx		; ECX <- return found data
		inc	ecx		; ECX <- return found data
		mov	edx,[ebx]	; EDX <- data buffer
		mov	edx,[edx+TEXT_Length] ; EDX <- text length
		sub	edx,ecx		; EDX <- data offset (it sets NC)

; ------------- OK: Pop registers (here is NC)

		pop	edi		; pop EDI
		pop	ecx		; pop ECX
		ret

Jsou-li oba bajty v textu nalezeny, obsahuje registr ECX počet zbylých bajtů. Dvojitou inkrementací a odečtením od celkové délky textu se obdrží v registru EDX offset nalezeného slova v textu. Funkce je ukončena s vynulovaným příznakem chyby NC.


; ------------- Data not found (here jumps from other functions, too)

TextFindWord5:	cld			; set direction up
TextFindWord6:	xor	edx,edx		; EDX <- 0
		dec	edx		; EDX <- -1, data not found
		stc			; set error flag
		
; ------------- ERROR: Pop registers

		pop	edi		; pop EDI
		pop	ecx		; pop ECX
		ret

Nejsou-li bajty v textu nalezeny, je do registru EDX nastavena hodnota -1 jako příznak neplatného offsetu a funkce je ukončena s nastaveným příznakem chyby CY. Tato část kódu je společná i pro další funkce (TextFindByte, TextFindByteRev atd.).


Obsah / Utility / TEXT / TextFindWordFirst, TextFindWord