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

Obsah / Utility / TEXT / TextMid

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


TextMid - Střední část textu

Funkce TextMid navrátí střední část textu, tedy část textu od dané pozice a o dané délce.


; -----------------------------------------------------------------------------
;                          Get middle part of text
; -----------------------------------------------------------------------------
; INPUT:	EAX = pointer to source TEXT
;		EBX = pointer to destination TEXT
;		ECX = length of part of text (it may be out of range)
;		EDX = start position of part of text (it may be out of range)
; OUTPUT:	CY = memory error, destination TEXT becomes empty
; NOTES:	It limits length and position to a valid range.
;		Source and destination may be identical.
; -----------------------------------------------------------------------------

Na vstupu funkce obsahuje registr EAX ukazatel na zdrojovou textovou proměnnou, EBX ukazatel na cílovou textovou proměnnou, ECX délku části textu (v bajtech) a registr EDX pozici (offset) počátku části text. Délka i pozice textu mohou být mimo platný rozsah. V případě chyby paměti funkce navrátí příznak chyby CY a cílový text se nastaví jako prázdný. Zdrojová a cílová proměnná mohou být identické.


; ------------- Check if source and destination is identical

TextMid:	cmp	eax,ebx		; is source and destination identical?
		je	TextMid9	; source is identical with destination

...................

; ------------- Identical source and destination variable (here is EAX == EBX)

TextMid9:	push	eax		; create temporary variable in stack

		mov	ebx,esp		; EBX <- temporary variable
		push	eax		; push EAX (destination variable)
		mov	eax,[eax]	; EAX <- TEXTDATA buffer
		call	TextAttach	; attach text to temporary variable
		xchg	eax,ebx		; EAX <- temporary variable
		pop	ebx		; EBX <- destination variable

		call	TextMid1	; get middle part of text

		pushf			; push flags
		xchg	eax,ebx		; EBX <- temporary, EAX <- destination
		call	TextDetach	; detach temporary variable
		popf			; pop flags

		pop	ebx		; delete temporary variable
		mov	ebx,eax		; EBX <- destination variable
		ret

Na začátku funkce se porovnáním ukazatelů ověří, zda cílová a zdrojová textová proměnná nejsou identické. Pokud ano, provede se kopie textu zvláštní obsluhou a to tak, že se v zásobníku vytvoří přechodná textová proměnná, vstupní proměnná se k ní připojí, do cílové proměnné se z ní zkopíruj požadovaná střední část textu a přechodná proměnná se opět zruší.


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

TextMid1:	push	eax		; push EAX
		push	ecx		; push ECX
		push	edx		; push EDX
		push	esi		; push ESI
		push	edi		; push EDI

; ------------- Empty destination text variable

		call	TextEmpty	; empty text

Po úschově registrů je cílový text vyprázdněn pro případ návratu s chybou.


; ------------- Limit minimal start position

		or	edx,edx		; check minimal start position
		js	TextMid7	; limit minimal start position

...................

; ------------- Limit minimal start position

TextMid7:	add	ecx,edx		; ECX <- correct text length
		xor	edx,edx		; EDX <- 0, limit start position
		jmp	short TextMid2

Testem registru EDX se ověří minimální pozice části textu. Pokud leží pozice před začátkem textu, opraví se délka textu a pozice se omezí na nulu.


; ------------- Check minimal text length

TextMid2:	or	ecx,ecx		; check text length
		jle	TextMid6	; no text to copy (here is NC)

Pokud není délka textu kladné číslo, není žádný text ke kopírování a funkce se ukončí.


; ------------- Check maximal start position (rest of text -> EAX)

		mov	esi,[eax]	; EDI <- data buffer
		mov	eax,[esi+TEXT_Length] ; EAX <- text length
		sub	eax,edx		; EAX <- remaining characters
		jle	TextMid5	; no data to copy

Do registru ESI je připraven ukazatel na buffer zdrojového textu a do registru EAX délka zdrojového textu. Do registru EAX se připraví délka zbývající části textu od dané pozice. Pokud nezbyl žádný text, funkce se ukončí a bude navrácen prázdný text.


; ------------- Limit maximal text length

		cmp	eax,ecx		; EAX <- rest of text
		jl	TextMid8	; length is too big

...................

; ------------- Limit maximal text length

TextMid8:	xchg	eax,ecx		; ECX <- limit maximal text length
		jmp	short TextMid4

Délka zbylého textu v registru EAX se porovná s délkou požadovaného textu ECX a pokud je menší, omezí se dékla požadovaného textu na skutečnou zbývající délku textu.


; ------------- Create destination buffer (it need not be detached)

TextMid4:	jecxz	TextMid5	; text is empty
		mov	eax,ecx		; EAX <- text length
		call	TextNew		; create data buffer
		jc	TextMid6	; memory error

Registr ECX nyní obsahuje požadovanou délku textu. Je-li požadovaná délka nula, funkce se může ihned ukončit, cílový text je již vyprázdněný. Jinak se vytvoří pomocí funkce TextNew nový textový buffer pro požadovanou délku textu. Adresa bufferu se uloží do cílové proměnné EBX. Původní obsah proměnné EBX není potřeba odpojovat, protože se jednalo o prázdný konstantní text, který nevyžaduje manipulaci s čítačem referencí.


; ------------- Prepare buffer address

		lea	esi,[esi+TEXT_Text+edx] ; EDI <- start of text
		mov	edi,[ebx]	; EDI <- destination buffer
		add	edi,byte TEXT_Text ; EDI <- destination text

; ------------- Copy text

		shr	ecx,2		; ECX <- length of text in DWORDs
		rep	movsd		; shift text in DWORDs
		and	eax,byte 3	; EAX <- rest in last DWORD
		xchg	eax,ecx		; ECX <- rest in last DWORD
		rep	movsb		; copy rest of text

; ------------- Pop registers

TextMid5:	clc			; clear error flag
TextMid6:	pop	edi		; pop EDI
		pop	esi		; pop ESI
		pop	edx		; pop EDX
		pop	ecx		; pop ECX
		pop	eax		; pop EAX
		ret

Registr ESI se posune na začátek zdrojového textu. Do registru EDI se připraví začátek bufferu cílového textu. Text se zkopíruje ze zdrojového do cílového bufferu - nejdříve po celých dvojslovech a pak zbylá data v posledním dvojslovu.


Obsah / Utility / TEXT / TextMid