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

Obsah / Utility / TEXTFORM / IntToTextBuf

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

Související:

IntToTextBufN   Délka textu formátovaného čísla INT se znaménkem
FormToTextBuf   Zformátování textu do bufferu

IntToTextBuf - Zformátování dekadického čísla se znaménkem do bufferu

Funkce IntToTextBuf zkonvertuje 64-bitové celé číslo se znaménkem na text ve formátovaném dekadickém (desítkovém) tvaru.


; -----------------------------------------------------------------------------
;                  Convert signed INT number into text buffer
; -----------------------------------------------------------------------------
; INPUT:	EDX:EAX = number
;		EBX = formatting parameters FORMPAR
;		ECX = pointer to nationality descriptor NATIONAL
;		ESI = remaining free space in buffer
;		EDI = destination buffer
; OUTPUT:	ESI = next remaining free space in buffer
;		EDI = next destination buffer
; NOTES:	On AMD 1.6 GHz it takes approx. "10*digits+40" nanosecs for
;		0 to 10	digits, "50*digits-360" nanosecs for 10 to 20 digits.
; -----------------------------------------------------------------------------
; Local variables - see UIntToTextBuf

Na vstupu funkce obsahuje registrový pár EDX:EAX číslo se znaménkem ke konverzi, registr EBX obsahuje formátovací parametry FORMPAR (ne ukazatel), registr ECX ukazatel na popisovač národnostních informací NATIONAL, registr ESI čítač zbylého místa v cílovém bufferu a registr EDI ukazatel do cílového bufferu. Na výstupu z funkce jsou registry ESI a EDI posunuty na novou ukládací pozici.

Funkce používají lokální proměnné s bázovým registrem EBP. Názvy a význam lokálních proměnných jsou stejné jako u funkce UIntToTextBuf.


; ------------- Check remaining free space in buffer

IntToTextBuf:	or	esi,esi		; check remaining space
		jle	short IntToTextBufN9 ; not enough free space

; ------------- Push registers (it must agree with UIntToTextBuf)

		push	eax		; push EAX number LOW
		push	ebx		; push EBX
		push	ecx		; push ECX pointer to nationality
		push	edx		; push EDX number HIGH
		push	ebp		; push EBP
		mov	ebp,esp		; EBP <- push ESP
		sub	esp,UINTStack	; ESP <- create local variables

; ------------- Prepare local variables

		mov	[UINTForm],ebx	; formatting parameters FORMPAR

Na začátku funkce IntToTextBuf je nejdříve proveden test volného místa v cílovém bufferu. Není-li v cílovém bufferu volné místo, funkce se ihned ukončí.

Po úschově registrů se vytvoří v zásobníku místo pro lokální proměnné.Do proměnné UINTForm se uschovají formátovací parametry z registru EBX.


; ------------- Get text length without spaces (-> EDX)

		call	Int0ToTextBufN	; get text length without spaces
		mov	[UINTLen],eax	; store text length
		xchg	eax,edx		; EDX <- push text length

Ke zformátování čísla v bufferu je potřeba nejdříve znát délku čísla. Délka čísla se zjistí funkcí Int0ToTextBufN, která na rozdíl od funkce IntToTextBufN ignoruje parametr minimální šířky pole s údajem. Délka čísla se uchová do proměnné UINTLen a do registru EDX.


; ------------- Store leading spaces

		bt	ebx,FORMFLAG_Left_b ; left-justify?
		jc	IntToTextBuf3	; left-justify, no leading spaces
		movzx	ecx,bh		; ECX <- minimal width of field
		sub	ecx,edx		; ECX <- remaining spaces
		jle	IntToTextBuf3	; no spaces left
		bt	ebx,FORMFLAG_Cent_b ; center?
		jnc	IntToTextBuf2	; no, right-justify
		shr	ecx,1		; ECX <- spaces / 2, round down
		jz	IntToTextBuf3	; no spaces left
IntToTextBuf2:	mov	al," "		; AL <- space
IntToTextBuf21:	dec	esi		; decrease space counter
		stosb			; store one space
IntToTextBuf22:	jz	UIntToTextBuf9	; buffer is full
		loop	IntToTextBuf21	; next character

Není-li číslo zarovnáno doleva (příznakový bit FORMFLAG_Left_b), je nutno před číslo doplnit úvodní mezery. Do registru ECX se připraví z registru BH (což je parametr FORMPAR_Width z popisovače formátovacích parametrů) požadovaná šířka pole. Odečtením délky textu z registru EDX se obdrží zbývající šířka pro okraje. Je-li to kladné číslo, bude se pokračovat dále. Má-li být text centrován, použije se pouze polovina mezer se zaokrouhlením dolů.

V cyklu se ukládají znaky mezer do cílového bufferu. Počet mezer je v registru ECX. Dekrementací registru ESI se ověřuje, zda bude v bufferu místo pro další znak. Pokud čítač ESI dosáhne nuly, dosáhlo se konce cílového bufferu a funkce se ukončí.


; ------------- Prepare registers to convert number

IntToTextBuf3:	mov	ecx,edx		; ECX <- length in characters
		mov	ebx,[UINTNumL]	; EBX <- number LOW
		mov	eax,[UINTNumH] 	; EAX <- number HIGH

; ------------- Number is negative

		or	eax,eax		; is number negative?
		jns	IntToTextBuf34	; number is not negative

; ------------- Negative value

		neg	ebx		; EBX <- negative value LOW
		adc	eax,0		; EAX <- carry
		neg	eax		; EAX <- negative value HIGH
		mov	[UINTNumH],eax	; store number HIGH

; ------------- Store negative sign

		mov	al,"-"		; AL <- negative sign
		dec	esi		; decrease space counter
		stosb			; store sign
		jz	short IntToTextBuf22 ; buffer is full
		dec	ecx		; ECX <- without sign character
		jmp	UIntToTextBuf32

; ------------- Store positive sign or space

IntToTextBuf34:	test	byte [UINTForm+FORMPAR_Flags1],FORMFLAG1_Sign ; sign?
		mov	al,"+"		; AL <- positive sign
		jnz	IntToTextBuf35	; use positive sign
		test	byte [UINTForm+FORMPAR_Flags1],FORMFLAG1_Space ; space?
		jz	UIntToTextBuf32	; no space
		mov	al," "		; AL <- space
IntToTextBuf35:	dec	esi		; decrease space counter
		stosb			; store sign
		jz	short IntToTextBuf22 ; buffer is full
		dec	ecx		; ECX <- without sign character
		jmp	UIntToTextBuf32

Při přípravě registrů ke konverzi se do dvojregistru EAX:EBX načte konvertované číslo a do registru ECX délka textu čísla. Kladná a záporná čísla mají zvláštní obsluhy.

Je-li číslo negativní, převede se na absolutní hodnotu (negace LOW části, přenos do HIGH části a negace HIGH části). Vyšší dvojslovo výsledku se uloží do proměnné UINTNumH, nižší dvojslovo se ponechá v registru EBX.

Do výstupního bufferu se uloží záporné znaménko. Pokud došlo k přetečení bufferu. funkce se ukončí. Jinak se sníží čítač požadovaných číslic o záporné znaménko a dále se pokračuje částí společnou s obsluhou čísel bez znaménka.

Není-li číslo záporné, může se uložit alternativní znak před číslo a to v případě, že je znaménko povinné (je nastaven příznak FORMFLAG1_Sign) nebo je požadována mezera namísto čísla (je nastaven příznak FORMFLAG1_Space). Po uložení znaku nzaménka, ošetření konce bufferu a snížení délky textu se pokračuje částí společnou s obsluhou čísel bez znaménka.


Obsah / Utility / TEXTFORM / IntToTextBuf