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

Obsah / Utility / TEXTFORM / FloatInfNan

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

Související:

FltToTextBuf   Zformátování desetinného čísla do bufferu
ExpSToTextBuf   Zformátování čísla s exponentem do bufferu, malé "e"
ExpCToTextBuf   Zformátování čísla s exponentem do bufferu, velké "E"

FloatInfNan - Dekódování nekonečna a nečíselných konstant (interní funkce)

Funkce FloatInfNan je interní funkce používaná funkcemi dekódujícími desetinné číslo na text a konvertuje na text speciální konstanty koprocesoru jako je např. nekonečno.


; -----------------------------------------------------------------------------
;                     Internal - Store infinity or non-number text
; -----------------------------------------------------------------------------
; INPUT:	AH = sign flag (bit 7)
;		EBX = formatting parameters FORMPAR
;		ECX = pointer to nationality descriptor NATIONAL
;		EDX = pointer to extended double float number (in stack)
;		ESI = remaining free space in buffer (must be > 0)
;		EDI = destination buffer
; OUTPUT:	ZY = destination buffer is full (EAX is not valid)
;		EAX = text length (= 7, valid only if NZ)
;		ESI = next remaining free space in buffer
;		EDI = next destination buffer
; NOTES:	Infinity is +1.#INF or -1.#INF, non-number +1.#NAN or -1.#NAN.
;		It should continue with storing trailing spaces.
; -----------------------------------------------------------------------------

Na vstupu funkce obsahuje registr AH příznak záporného čísla (bit 7), registr EBX formátovací parametry FORMPAR, registr ECX ukazatel na popisovač národnostních informací NATIONAL, registr EDX ukazatel na desetinné číslo v rozšířeném formátu (velikost 10 bajtů). Registr ESI je čítač zbývajícího volného místa v cílovém bufferu a registr EDI je ukazatel do cílového bufferu. Na výstupu funkce indikuje příznak ZY, že výstupní buffer je plný, registr EAX je nastaven na délku uloženého textu (obsah platný jen není-li výstupní buffer plný, tj. je příznak NZ), registry ESI a EDI jsou posunuty na novou ukládací pozici.


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

FloatInfNan:	bt	ebx,FORMFLAG_Left_b ; left?
		jc	FloatInfNan4	; left-justify, no spaces
		cmp	bh,7		; check minimal width
		jbe	FloatInfNan4	; width is low
		push	ecx		; push ECX
		movzx	ecx,bh		; ECX <- minimal width
		sub	cl,7		; ECX <- remaining spaces
		bt	ebx,FORMFLAG_Cent_b ; center?
		jnc	FloatInfNan1	; no, right-justify
		cmp	cl,2		; check minimal width
		jb	FloatInfNan3	; width is low (it jumps with NZ)
		shr	ecx,1		; ECX <- spaces / 2, round down
FloatInfNan1:	mov	al," "		; AL <- space
FloatInfNan2:	dec	esi		; decrease space counter
		stosb			; store one space
		loopnz	FloatInfNan2	; next character
FloatInfNan3:	pop	ecx		; pop ECX
		jz	FloatInfNan8	; buffer is full

Funkce pro výpis speciálních konstant si sama zajišťuje dekódování úvodních mezer v případě, že text je zarovnaný doprava nebo na střed. Je-li text zarovnán doleva (je nastaven příznak FORMFLAG_Left_b), obsluha úvodních mezer se přeskočí, stejně jako je-li požadována šířka pole menší než 7 znaků (což je délka ukládaného textu).

Do registru ECX se připraví požadovaná šířka pole s číslem načtením z registru EBH, což je položka FORMPAR_Width formátovacích parametrů, a odečte se šířka ukládaného textu, tedy 7 znaků. Má-li být text centrován, je použit poloviční počet mezer. Kontrola minimálního počtu mezer je proveden tak, aby v případě malého počtu mezer byl navrácen příznak NZ.

Při ukládání úvodních mezer jsou znaky mezer ukládány do bufferu EDI, čítač znaků je ECX a dekrementací registru ESI se testuje zbývající volné místo v cílovém bufferu. Při překročení konce bufferu je funkce ukončena s příznakem ZY.


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

FloatInfNan4:	mov	al,"-"		; AL <- negative sign
		or	ah,ah		; negative number?
		js	FloatInfNan5	; negative number
		mov	al,"+"		; AL <- positive sign
FloatInfNan5:	dec	esi		; decrease space counter
		stosb			; store sign
		jz	FloatInfNan8	; buffer is full

Před vlastním textem konstanty bude uloženo znaménko. Podle obsahu registru AH se uloží buď znaménko "+" nebo "-" a dekrementací registru ESI je proveden test konce bufferu. Při překročení konce bufferu je funkce ukončena s příznakem ZY.


; ------------- Store "1" digit

		mov	al,"1"		; AL <- "1" digit
		dec	esi		; decrease space counter
		stosb			; store sign
		jz	FloatInfNan8	; buffer is full

; ------------- Store decimal separator

		mov	al,[ecx+NAT_DecimalSep] ; AL <- decimal separator
		dec	esi		; decrease space counter
		stosb			; store decimal separator
		jz	FloatInfNan8	; buffer is full

; ------------- Store "#" character

		mov	al,"#"		; AL <- "#" symbol
		dec	esi		; decrease space counter
		stosb			; store "#" symbol
		jz	FloatInfNan8	; buffer is full

Dále se uloží znaky, které jsou společné pro všechny konstanty. Nejdříve znak "1", poté oddělovač desetinných míst, který je načten z popisovače národnostních informací v registru ECX, a nakonec snak "#". U všech funkcí se současně dekrementací registru ESI ověřuje test konce bufferu. Při překročení konce bufferu je funkce ukončena s příznakem ZY.


; ------------- Prepare text

		mov	eax,[edx]	; EAX <- mantissa LOW
		or	eax,[edx+4]	; check if mantissa is zero
		mov	eax,"NAN"	; non-number value
		jnz	FloatInfNan6	; not zero, it is non-number
		mov	eax,"INF"	; infinity value

; ------------- Store first character

FloatInfNan6:	dec	esi		; decrease space counter
		stosb			; store fist character
		jz	FloatInfNan8	; buffer is full

; ------------- Store second character

		shr	eax,8		; AL <- second character
		dec	esi		; decrease space counter
		stosb			; store second character
		jz	FloatInfNan8	; buffer is full

; ------------- Store third character

		shr	eax,8		; AL <- third character
		dec	esi		; decrease space counter
		stosb			; store third character

; ------------- New text length (here is ZY = buffer is full)

FloatInfNan8:	mov	al,7		; EAX <- text length
		ret

Nyní budou uloženy 3 znaky specifikující konstantu. Není-li mantisa desetinného čísla nula (tj. první a druhé dvojslovo čísla v rozšířeném formátu není nula), jedná se o nedefinované číslo, použije se text "NAN". Je-li mantisa nula, jedná se o nekonečno a použije se text "INF".

Znaky textu jsou v registru EAX. Nejdříve se uloží první znak z registru AL, poté se registr EAX posune o 8 bitlů a uloží se druhý znak a nakonec podobně třetí znak. Při ukládání každého znaku se současně dekrementací registru ESI testuje konec bufferu. Při překročení konce bufferu je funkce ukončena s příznakem ZY.

Funkce je ukončena nastavením registru AL na 7. Je-li funkce ukončena s nastaveným příznakem ZY, došlo k přetečení bufferu a volající funkce by měla být ukončena. Není-li přetečení bufferu, jsou vyšší bajty registru EAX nulové (tj. registr EAX obsahuje délku textu) a volající funkce by měla pokračovat uložením koncových mezer za číslem.


Obsah / Utility / TEXTFORM / FloatInfNan