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

Obsah / Utility / TEXT / TextAddFormat

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


TextAddFormat - Přidání formátovaného textu na konec textu

Funkce TextAddFormat přidá formátovaný text na konec textu.


; -----------------------------------------------------------------------------
;                       Add formated text to end of text
; -----------------------------------------------------------------------------
; INPUT:	EAX = pointer to source TEXT variable
;		EBX = pointer to destination TEXT variable
;		ECX = number of DWORDs in array of arguments (max. 256)
;		EDX = pointer to array of arguments
;		ESI = pointer to nationality descriptor NATIONAL (NULL=default)
; OUTPUT:	CY = memory error or invalid argument index (text not changed)
; -----------------------------------------------------------------------------
; Local variables (ebp+N are read-only variables):
;
;  ECX = local variables in stack

%define		TFRMSrc		ecx+24	; (4) source TEXT
%define		TFRMDst		ecx+20	; (4) destination TEXT
%define		TFRMArgN	ecx+16	; (4) number of arguments
%define		TFRMArg		ecx+12	; (4) pointer to arguments
%define		TFRMNat		ecx+8	; (4) pointer to nationality

Na vstupu funkce obsahuje registr EAX ukazatel na textovou proměnnou obsahující formátovací řetězec. Registr EBX obsahuje ukazatel na cílovou proměnnou, do které se zformátovaný text uloží. Registr ECX obsahuje velikost pole argumentů v násobcích dvojslov DWORD, registr EDX je ukazatel na pole argumentů. Registr ESI obsahuje ukazatel na popisovač národnostních informací NATIONAL. Je-li ukazatel nulový (tj. obsahuje NULL), použije se implicitní popisovač národnostních informací. V případě chyby paměti, nebo pokud je ve formátovacím řetězci použit neplatný index argumentu, je navrácen chybový příznak CY a obsah cílové textové proměnné se nezmění.

Funkce používá tyto lokální proměnné: TFRMSrc ukazatel na textovou proměnnou s formátovacím řetězcem, TFRMDst ukazatel na cílovou textovou proměnnou, TFRMArgN velikost pole argumentů, TFRMArg ukazatel na pole argumentl a TFRMNat ukazatel na popisovač národnostních informací. Stejné lokální proměnné využívá i funkce zpětného volání TextAddFormCB (viz dále).


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

TextAddFormat:	push	eax		; push EAX (source TEXT)
		push	ebx		; push EBX (destination TEXT)
		push	ecx		; push ECX (number of arguments)
		push	edx		; push EDX (pointer to arguments)
		push	esi		; push ESI (pointer to nationality)
		push	edi		; push EDI
		push	ebp		; push EBP
		mov	ecx,esp		; ECX <- local variables

; ------------- Get text length (-> ESI)

		mov	edx,[eax]	; EDX <- source text data
		mov	ebx,[edx+TEXT_Length] ; EBX <- size of source text
		add	edx,TEXT_Text	; EDX <- start of source text
		mov	ebp,TextAddFormCB ; EBP <- callback function
		xchg	eax,ecx		; EAX <- callback value,local variables
		call	FormToTextBufN	; get text length
		xchg	eax,ecx		; ECX <- local variables
		jc	TextAddFormat9	; invalid argument index

Po úschově registrů do zásobníku se zjistí potřebná velikost cílového bufferu voláním funkce FormToTextBufN, registr EBP přitom obsahuje adresu funkce zpětného volání TextAddFormCB (viz dále) a registr EAX hodnotu pro zpětnou funkci, což je ukazatel na zásobník s lokálními proměnnými. V případě chybného indexu argumentu se funkce ihned ukončí s chybou.


; ------------- Copy text on write

		mov	ebx,[TFRMDst]	; EBX <- destination text
		call	TextCopyWrite	; copy text on write
		jc	TextAddFormat9	; memory error

Cílová textová proměnná se připraví pro zápis kopií textu před zápisem pomocí funkce TextCopyWrite. V případě chyby paměti se funkce ihned ukončí s příznakem chyby.


; ------------- Resize buffer

		mov	eax,[ebx]	; EAX <- destination data buffer
		mov	eax,[eax+TEXT_Length] ; EAX <- length of data buffer
		add	eax,esi		; EAX <- new text length
		call	TextResize	; resize data buffer
		jc	TextAddFormat9	; memory error

Velikost cílového bufferu se změní podle zjištěné požadované délky pomocí funkce TextResize. V případě chyby paměti se funkce ihned ukončí s příznakem chyby.


; ------------- Format text

		sub	eax,esi		; EAX <- old length of text
		add	eax,[ebx]	; EAX <- data buffer
		add	eax,TEXT_Text	; EAX <- start of new text
		xchg	eax,edi		; EDI <- start of new text
		mov	edx,[TFRMSrc]	; EDX <- pointer to source variable
		mov	edx,[edx]	; EDX <- source text data
		mov	ebx,[edx+TEXT_Length] ; EBX <- size of source text
		add	edx,TEXT_Text	; EDX <- start of source text
		mov	ebp,TextAddFormCB ; EBP <- callback function
		mov	eax,[TFRMNat]	; EAX <- pointer to nationality
		or	eax,eax		; default nationality?
		jnz	TextAddFormat6	; nationality is valid
		DEFAULT_NAT eax		; EAX <- get default nationality
TextAddFormat6:	xchg	eax,ecx		; EAX <- callback value,local variables
		call	FormToTextBuf	; format text into buffer

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

TextAddFormat9:	pop	ebp		; pop EBP
		pop	edi		; pop EDI
		pop	esi		; pop ESI
		pop	edx		; pop EDX
		pop	ecx		; pop ECX
		pop	ebx		; pop EBX
		pop	eax		; pop EAX
		ret

Text se zformátuje pomocí funkce FormToTextBuf, registr EBP přitom obsahuje adresu funkce zpětného volání TextAddFormCB (viz dále), registr EAX hodnotu pro zpětnou funkci, což je ukazatel na zásobník s lokálními proměnnými a registr ECX ukazatel na popisovač národnostních informací. Pokud nebyl popisovač národnostních informací zadán, použije se implicitní popisovač (makro DEFAULT_NAT).

TextAddFormCB - Funkce zpětného volání pro formátování textu

Funkce TextAddFormCB je funkce zpětného volání. Tato funkce je volána zpětně z funkce TextAddFormat a slouží k načtení argumentu ze seznamu argumentů.


; -----------------------------------------------------------------------------
;          Local function - Add formated text to end of text, callback
; -----------------------------------------------------------------------------
; INPUT:	EAX = callback value
;		EBX = formatting parameters with argument type
;		EDX = DWORD index in argument stack (0 to 255)
; OUTPUT:	CY=error, invalid argument index (no valid value returned)
;		EAX = width or precision parameter
;		EDX:EAX integer
;		EAX character UNICODE
;		ST0 floating point (only if NC)
;		EAX pointer to text UTF-8, EDX length of text
; DESTROYS:	EBX, ECX, EDX:EAX (if not returning a value)
; NOTES:	64-bit integer or double float takes 2 DWORDs, extended double
;		takes 3 DWORDs and other numbers take 1 DWORD. Argument index
;		refers to index of DWORD argument, not to real argument number.
; -----------------------------------------------------------------------------

Na vstupu funkce obsahuje registr EAX ukazatel na lokální proměnné v zásobníku funkce TextAddFormat, registr EBX obsahuje formátovací parametry a registr EDX index argumentu v seznamu argumentů. Index argumentu je offset v násobcích DWORD s rozsahem údaje 0 až 255 (tedy není to skutečný index argumentu, protože argumenty mohou mít různou velikost). Pokud byl zadán index argumentu mimo povolený rozsah, vrací funkce nastavený příznak CY a žádné platné údaje nejsou vráceny (tj. registry jsou neplatné a v zásobníku koprocesoru není vrácena žádná hodnota).

Není-li příznak chyby nastaven (tj. je navrácen příznak NC), obsahují registry EAX, EDX, ST0 návratové hodnoty, v závislosti podle typu argumentu. Parametr šířky nebo přesnosti je navrácen v registru EAX, celé číslo v registrovém páru EDX:EAX, znak UNICODE v registru EAX, desetinné číslo v registru ST0, ukazatel na UTF-8 text v registru EAX a v registru EDX je délka textu.

Registry EAX, EBX, ECX a EDX jsou funkcí zničeny, pokud neslouží k navrácení hodnoty z funkce.

V seznamu argumentů zabírají 64.-bitové celočíselné argumenty a desetinná čísla 2 dvojslova, rozšířená desetinná čísla 3 dvojslova a ostatní argumenty 1 dvojslovo.


; ------------- Prepare pointer to local variables

TextAddFormCB:	xchg	eax,ecx		; ECX <- local variables

; ------------- Check argument index and size

		call	FormGetArgLen	; get argument length -> EAX
		add	eax,edx		; EAX <- end of arguments
		cmp	[TFRMArgN],eax	; check index and size of argument
		jb	TextAddFormCB9	; invalid argument index or size

Do registru ECX se uloží ukazatel na lokální proměnné v zásobníku z funkce TextAddFormat. Používá se stejný registr (ECX), takže je možné používat stejné názvy proměnných. Pomocí funkce FormGetArgLen se z formátovacích parametrů v registru EBX zjistí délka argumentu (ve dvojslovech). Přičtením indexu požadovaného argumentu v registru EDX se zjistí index konce argumentu a porovnáním s počtem argumentů se ověří platnost indexu požadovaného argumentu. V případě neplatného indexu se funkce ukončí s chybou.


; ------------- Prepare pointer to argument (-> EDX)

		shl	edx,2		; EDX <- argument index * 4
		add	edx,[TFRMArg]	; EDX <- argument address

Do registru EDX se připraví ukazatel na požadovaný argument (proměnná TFRMArg obsahuje ukazatel na pole argumentů).


; ------------- Prepare argument type (-> AL) and flags (-> AH)

		xchg	eax,ebx		; EAX <- formatting parameters
		shr	eax,FORMPAR_TypeF_b ; EAX <- type and flags
		and	al,FORMTYPE_Mask0 ; AL <- argument type

; ------------- Read width/precision parameter

		jnz	TextAddFormCB2	; not parameter
TextAddFormCB1:	mov	eax,[edx]	; EAX <- get parameter
		ret			; return with NC

; ------------- Read single character

TextAddFormCB2:	cmp	al,FORMTYPE_Char ; single character "c","C"?
		je	TextAddFormCB1	; single character

Do registru AL se připraví typ argumentu z registru EBX, který obsahuje formátovací parametry. Pokud měl typ argumentu hodnotu 0, jedná se o čtení parametru šířky nebo přesnosti, argument je přímo načten z ukazatele EDX a funkce je úspěšně ukončena (s vynulovaným příznakem CF). Stejně tak je argument načten jako 32-bitové číslo v případě, že argumentem je jeden znak v kódu UNICODE.


; ------------- Read string

		cmp	al,FORMTYPE_String ; string "s", "S"?
		jne	TextAddFormCB3
		mov	eax,[edx]	; EAX <- pointer to text variable
		mov	eax,[eax]	; EAX <- pointer to text data
		mov	edx,[eax+TEXT_Length] ; EDX <- length of text
		add	eax,TEXT_Text	; EAX <- start of text
		ret			; return with NC

Je-li argumentem textový řetězec, bude do registru EAX načten ukazatel na proměnnou textového řetězce TEXT a z ní je načten ukazatel na data textového řetězce TEXTDATA. Do proměnné EDX je uložena délka textu (v bajtech) a ukazatel dat v registru EAX je posunu na začátek dat textu. Funkce navrátí vynulovaný příznak chyby CF.


; ------------- Read integer

TextAddFormCB3:	cmp	al,FORMTYPE_ArgInt ; integer?
		ja	TextAddFormCB5	; not integer

; ------------- Integer 16-bit

		test	ah,FORMFLAG2_Shrt ; short argument?
		jz	TextAddFormCB43	; not short argument
		cmp	al,FORMTYPE_Int	; signed integer?
		jne	TextAddFormCB42	; not signed integer
		movsx	eax,word [edx]	; EAX <- signed short
TextAddFormCB41:cdq			; EDX:EAX <- signed integer
		ret			; return with NC

TextAddFormCB42:movzx	eax,word [edx]	; EAX <- unsigned short
		cdq			; EDX:EAX <- unsigned integer
		clc			; clear error flag
		ret			; return with NC

; ------------- Integer 32-bit

TextAddFormCB43:test	ah,FORMFLAG2_Long ; long argument?
		jnz	TextAddFormCB44	; long argument
		cmp	al,FORMTYPE_Int	; signed integer?
		mov	eax,[edx]	; EAX <- load integer
		je	TextAddFormCB41	; signed integer
		xor	edx,edx		; EDX:EAX <- unsigned integer
		ret			; return with NC

; ------------- Integer 64-bit

TextAddFormCB44:mov	eax,[edx]	; EAX <- integer LOW
		mov	edx,[edx+4]	; EDX <- integer HIGH
		ret			; return with NC

Následuje načtení celočíselného argumentu. Pro neceločíselné argumenty se obsluha přeskočí.

Testem příznaků v registru AH se rozliší velikost argumentu. Jedná-li se o krátký argument, bude číslo načítáno jako 16-bitové celé číslo - a to buď se znaménkem nebo bez znaménka. V obou případech bude číslo rozšířeno na 64-bitovou hodnotu (v registrovém páru EDX:EAX) a funkce navrácí vynulovaný příznak chyby CF.

Jedná-li se o dlouhý argument, bude číslo načteno jako 64-bitové do registrového páru EDX:EAX. Jinak bude načteno jako 32-bitové a výsledek bude opět rozšířen na 64-bitovou hodnotu (do registrového páru EDX:EAX) s rozlišením znaménkového a neznaménkového čísla.


; ------------- Single float

TextAddFormCB5:	test	ah,FORMFLAG2_Shrt ; short argument?
		jz	TextAddFormCB52	; not short argument
		fld	dword [edx]	; ST0 <- load single float
		ret			; return with NC

; ------------- Double float

TextAddFormCB52:test	ah,FORMFLAG2_Long ; long argument?
		jnz	TextAddFormCB54	; long argument
		fld	qword [edx]	; ST0 <- load double float
		ret			; return with NC

; ------------- Extended double float

TextAddFormCB54:fld	tword [edx]	; ST0 <- load extended double float
TextAddFormCB9:	ret			; return with NC

Nejedná-li se o celé číslo, bude argumentem desetinné číslo. Podle příznaků v registru AH se rozliší velikost argumentu - buď číslo s jednoduchou přesností (velikost 1 dvojslovo), nebo číslo s dvojnásobnou přesností (velikost 2 dvojslova) nebo číslo s rozšířenou přesností (velikost 10 bajtů, zarovnáno na 3 dvojslova). Funkce opět navrátí vynulovaný příznak chyby CF.


Obsah / Utility / TEXT / TextAddFormat