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

Obsah / Utility / TEXTFORM / ExpSToTextBuf, ExpCToTextBuf

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

Související:

ExpToTextBufN   Délka textu formátovaného čísla s exponentem
MixSToTextBuf   Zformátování smíšeného desetinného čísla do bufferu, malé "e"
MixCToTextBuf   Zformátování smíšeného desetinného čísla do bufferu, velké "E"
FormToTextBuf   Zformátování textu do bufferu

ExpSToTextBuf, ExpCToTextBuf - Zformátování čísla s exponentem do bufferu

Funkce ExpSToTextBuf a ExpCToTextBuf zkonvertují desetinné číslo na text ve formátovaném tvaru s exponentem. ExpSToTextBuf použije malé písmeno exponentu "e", ExpCToTextBuf velké písmeno "E". Velikost písmene exponentu přitom nemusí odpovídat formátovacímu příznaku FORMTYPE_Cap_b, který vypne zaokrouhlování poslední číslice.


; -----------------------------------------------------------------------------
;     Convert float number into text buffer in exponential form - small "e"
; -----------------------------------------------------------------------------
; INPUT:	ST0 = float number (it does not pop it from the FPU stack)
;		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:	It uses 2 more registers from FPU stack.
;		FPU should be in default state - 64 bits, round to nearest.
;		Exponent is 3 or 4 digits.
;		To destroy FPU register you can use "ffreep st0" instruction.
;		On AMD 1.6 GHz it takes approx. "10*decimal places+200" nsec.
; -----------------------------------------------------------------------------
; Local variables (ebp+N are read-only variables):
%define		EXPNat     ebp+8	; (4) pointer to nationality NATIONAL
%define		EXPForm    ebp-4	; (4) formatting parameters FORMPAR
%define		EXPLen     ebp-8	; (4) total length of text
%define		EXPChar    ebp-9	; (1) exponent character "E" or "e"
%define		EXPSign    ebp-10	; (1) stored flags, bit 7 = sign
					;	bit 6 = exponent sign
%define		EXPExp     ebp-12	; (2) float number, exponent
					;       (bit 0..14) and sign (bit 15)
%define		EXPMantH   ebp-16	; (4) float number, mantissa HIGH
%define		EXPMantL   ebp-20	; (4) float number, mantissa LOW
%define		EXPFloat   EXPMantL	; ...(10) float number

%define		EXPStack   20		; stack size

Na vstupu každé z funkcí obsahuje registr ST0 desetinné číslo 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žívá další 2 registry koprocesoru. Vstupní číslo v registru ST0 zůstává zachováno, neuvolňuje se ze zásobníku koprocesoru. K uvolnění čísla z registru ST0 lze použít instrukci "ffreep st0" volanou po ukončení funkce. Funkce předpokládá, že koprocesor je v implicitním nastavení - přesnost 64 bitů, zaokrouhlení k nejbližšímu.

Funkce používá lokální proměnné s bázovým registrem EBP. Proměnné s kladným offsetem (EXPNat) jsou použity jen pro čtení, jejich obsah není modifikován. EXPNat je ukazatel na národnostní informace NATIONAL (vstupní registr ECX). EXPForm jsou formátovací parametry FORMPAR (vstupní registr EBX). EXPLen je délka ukládaného textu. EXPChar je znak exponentu (malé "e" nebo velké "E"). EXPSign jsou příznaky - bit 7 označuje záporné znaménko čísla, bit 6 je záporné znaménko exponentu. EXPFloat je desetinné číslo v zásobníku a skládá se z částí EXPMantL - nižší dvojslovo mantisy, EXPMantH - vyšší dvojslovo mantisy a EXPExp - exponent. EXPStack je velikost lokálních proměnných v zásobníku.


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

ExpSToTextBuf:	or	esi,esi		; check remaining space
		jle	short ExpToTextBufN9 ; not enough free space

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

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

; ------------- Prepare exponent character

		mov	byte [EXPChar],"e" ; prepare exponent character
		jmp	short ExpToTextBuf1

Na začátku funkce ExpSToTextBuf 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é EXPChar se připraví znak exponentu malé "e".


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

ExpCToTextBuf:	or	esi,esi		; check remaining space
		jle	short ExpToTextBufN9 ; not enough free space

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

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

; ------------- Prepare exponent character

		mov	byte [EXPChar],"E" ; prepare exponent character

Začátek funkce ExpCToTextBuf je shodný se začátkem funkce ExpSToTextBuf s tím rozdílem, že do proměnné EXPChar se připraví znak exponentu velké "E". Dále již pokračují obě funkce společnou větví programu.


; ------------- Prepare precision (alternate: number of significant digits)

ExpToTextBuf1:	bt	ebx,FORMFLAG_Prec_b ; alternate precision?
		sbb	bl,0		; without first digit
		adc	bl,0		; minimal precision 0 if borrow

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

		mov	[EXPForm],ebx	; formatting parameters FORMPAR

Je-li požadována alternativní přesnost, má parametr FORMPAR_Prec formátovacích parametrů význam celkového počtu číslic namísto počtu číslic za desetinnou čárkou. Proto se v tom případě požadovaná přesnost opraví tak, že se sníží o 1. V případě podtečení se omezí na alespoň 1 číslici (není podporována přesnost 0 významných číslic). Formátovací parametry se uloží do lokální proměnní EXPForm.


; ------------- Store number into stack

		fld	st0		; duplicate number
		fstp	tword [EXPFloat] ; store number into stack

; ------------- Load exponent (-> EDX)

		fwait			; synchronize FPU
		movzx	edx,word [EXPExp] ; EDX <- exponent
		mov	ch,dh		; CH <- sign
		and	ch,B7		; left only sign flag
		mov	[EXPSign],ch	; push sign flag (bit 7)

Nyní se připraví exponent konvertovaného čísla. Číslo se uloží do bufferu v zásobníku EXPFloat (nejdříve se musí zduplikovat, protože není k dispozici instrukce pro uložení čísla v rozšířené přesnosti bez uvolnění čísla ze zásobníku koprocesoru).

Exponent čísla EXPExp se načte do registru EDX. Do proměnné EXPSign se uchová znaménko čísla, současně se vynulují ostatní bity EXPSign.


; ------------- Absolute value (it uses copy of register)

		fld	st0		; duplicate number
		fabs			; absolute value
		and	dx,7fffh	; mask exponent (15 bits)
		jnz	ExpToTextBuf2	; neither zero nor denormalized number

Konvertované číslo se zduplikuje (aby mohlo být modifikováno a přitom zůstalo vstupní číslo uchováno) a převede se na absolutní hodnotu. Vynulováním nejvyššího bitu v registru DX se vynuluje znaménkový bit. Je-li exponent v registru DX nulový, jedná se o speciální případ nuly nebo nenormalizovaného čísla.


; ------------- Zero or denormalized number

		mov	eax,[EXPMantL]	; EAX <- mantissa LOW
		or	eax,[EXPMantH]	; check if mantissa is zero
		jnz	ExpToTextBuf2	; not zero, it is denormalized number

; ------------- Zero

		ffreep	st0		; pop register from the FPU stack
		xor	ebx,ebx		; EBX <- zero decimal exponent
		test	byte [EXPForm+FORMPAR_Flags2],FORMFLAG2_Alt2 ; trunc.?
		jz	ExpToTextBuf6	; don't truncate
		mov	byte [EXPForm+FORMPAR_Prec],0 ; limit precision
		jmp	ExpToTextBuf6

V případě nulového exponentu se provede test mantisy na nulu. Není-li mantisa nulová, jedná se o nenormalizované číslo (s exponentem menším než přibližně 1e-4931), takové číslo se bude dále zpracovávat běžným způsobem.

Jsou-li exponent i mantisa nulové, jedná se o nulu. Číslo je uvolněno ze zásobníku koprocesoru, do registru EBX je připraven nulový dekadický exponent a přeskočí se část rozdělující číslo na exponent a mantisu. V případě požadavku ořezání koncových nul se omezí přesnost na 0 desetinných číslic.


; ------------- Infinity (+1.#INF, -1.#INF) or non-number (+1.#NAN, -1.#NAN)

ExpToTextBuf2:	cmp	dx,7fffh	; infinity or non-number?
		jne	ExpToTextBuf3	; neither infinity nor non-number
		ffreep	st0		; pop register from the FPU stack
		xchg	eax,ecx		; AH <- sign flag (bit 7)
		mov	ecx,[EXPNat]	; ECX <- pointer to nationality
		lea	edx,[EXPFloat]	; EDX <- pointer to float number
		call	FloatInfNan	; store text
		jz	ExpToTextBuf9	; buffer is full
		jmp	ExpToTextBuf86	; store trailing spaces

Má-li exponent v registru DX hodnotu 7FFFh, jedná se o další zvláštní případ - nekonečno nebo nedefinované číslo. Číslo se uvolní ze zásobníku koprocesoru, do registru AH (bit 7) se připraví příznak záporného znaménka, do registru ECX se připraví ukazatel na národnostní informace, do registru EDX se připraví ukazatel na buffer čísla v zásobníku a voláním funkce FloatInfNan se dekóduje text speciálního případu do výstupního bufferu. Je-li navrácen příznak ZY, došlo k přetečení výstupního bufferu a funkce se ihned ukončí. Jinak se pokračuje uložením koncových mezer (v registru EAX je navrácena délka textu).


; ============= Convert number to digits

; ------------- Split number to mantissa and exponent (here is EDX=bin. exp.)

ExpToTextBuf3:	lea	ecx,[EXPFloat]	; ECX <- pointer to float in stack
		call	FloatSplit	; split number to mantissa and exponent

Dále bude pokračovat obsluha rozložení čísla na číslice. Pomocí funkce FloatSplit je číslo rozloženo na mantisu a dekadický exponent. Na vstupu funkce je v registru EDX binární exponent čísla, registr ECX ukazuje na buffer čísla v zásobníku a v registru ST0 je absolutní hodnota konvertovaného čísla. Funkce navrací v registru EBX dekadický exponent a v registru ST0 mantisu čísla (normalizovanou do rozsahu 1 včetně až 10 vyjma).


;-------------- Round, denormalize and convert mantissa to BCD (EBX = exponent)

		movzx	eax,byte [EXPForm+FORMPAR_Prec] ; EAX <- precision
		lea	ecx,[EXPFloat]	; ECX <- pointer to float in stack
		bt	dword [EXPForm],FORMTYPE_Cap_b ; round always down?
		call	FloatMantBCD	; process mantissa

Číslo je pomocí funkce FloatMantBCD zaokrouhleno na poslední číslici a rozloženo na jednotlivé číslice. Před voláním funkce je do registru EAX připravena požadovaná přesnost, do registru ECX ukazatel na buffer čísla v zásobníku, registr EBX obsahuje dekadický exponent. Testem příznaku FORMTYPE_Cap_b je funkci předán příznak, zda se má vypnout zaokrouhlování poslední zobrazené číslice.


; ------------- Truncate trailing zeros

		test	byte [EXPForm+FORMPAR_Flags2],FORMFLAG2_Alt2 ; trunc.?
		jz	ExpToTextBuf6	; don't truncate
		lea	edx,[EXPFloat+9] ; EDX <- last digit
		call	FloatTrunc	; truncate trailing zeros
		cmp	cl,[EXPForm+FORMPAR_Prec] ; check precision
		jae	ExpToTextBuf6	; precision is OK
		mov	[EXPForm+FORMPAR_Prec],cl ; limit precision

Mají-li být ořezány nevýznamné koncové nuly, je funkcí FloatTrunc zjištěna skutečná přesnost čísla (tj. počet platných desetinných míst). Je-li skutečná přesnost nižší než požadovaná, opraví se parametr FORMPAR_Prec na skutečnou přesnost.


; ============= Get text length (here is EBX = decimal exponent)

; ------------- Add decimal point and first digit

ExpToTextBuf6:	movzx	eax,byte [EXPForm+FORMPAR_Prec]	; EAX <- num. of digits
		or	eax,eax		; zero digits after decimal point?
		jz	ExpToTextBuf66	; no digits after decimal point
		bts	dword [EXPForm],FORMFLAG_Alt_b ; set dec. point flag
ExpToTextBuf66:	bt	dword [EXPForm],FORMFLAG_Alt_b ; use decimal point?
		adc	eax,byte 1	; add decimal point and first digit

V další části bude zjištěna délka textu dekódovaného čísla. Do registru EAX se připraví požadovaná přesnost představující počet číslic za desetinnou tečkou. Není-li počet číslic za tečkou nulový, zapne se vynuceně příznak indikující, že se desetinná tečka použije. Pokud je požadována desetinná tečka, délka textu se zvýší o 1.


; ------------- Add sign

		mov	dl,[EXPSign]	; DL <- sign (bit 7)
		mov	dh,[EXPForm+FORMPAR_Flags1] ; DH <- flags 1
		and	dx,B7 + (FORMFLAG1_Sign + FORMFLAG1_Space)*256
		setnz	dl		; DL <- 1 if sign, else 0
		movzx	edx,dl		; EDX <- 1 if sign, else 0
		add	eax,edx		; EAX <- add sign

Je-li číslo záporné nebo je-li vynuceně znaménko (nebo náhradní mezera) vyžadováno vždy, je délka textu zvýšena o 1 znak znaménka.


; ------------- Absolute value of exponent (-> EBX)

		or	ebx,ebx		; is exponent negative?
		jns	ExpToTextBuf68	; exponent is not negative
		neg	ebx		; EBX <- absolute value of exponent
		or	byte [EXPSign],B6 ; set exponent sign flag

Připraví se absolutní hodnota dekadického exponentu a příznak v proměnné EXPSign (bit 6) indikující, že exponent je záporný.


; ------------- Add exponent

ExpToTextBuf68:	add	eax,byte 1+1+3	; add exp. character, sign and 3 digits
		cmp	bx,1000		; exponent 1000 or greater?
		cmc			; CY = exponent is 1000 or greater
		adc	eax,byte 0	; EAX <- exponent is 4 digits
		mov	[EXPLen],eax	; set length of text
		xchg	eax,edx		; EDX <- length of text

Přičte se délka exponentu. Exponent se skládá z 1 znaku oddělovače exponentu ("e" nebo "E"), 1 znaku znaménka a minimálně 3 číslic exponentu. Je-li exponent 1000 a více, bude mít exponent 4 číslice, délka textu se proto zvýší o 1. Výsledná délka textu se uloží do proměnné EXPLen a také do registru EDX.


; ============= Decode spaces and sign (here is EDX=text length, EBX=exponent)

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

	  test word [EXPForm+FORMPAR_TypeFlg],FORMFLAG1_Left+FORMFLAG2_Zero*256
		jnz	ExpToTextBuf72	; left-justify or add zeros, no spaces
		movzx	ecx,byte [EXPForm+FORMPAR_Width] ; ECX <- minimal width
		sub	ecx,edx		; ECX <- remaining spaces
		jle	ExpToTextBuf72	; no spaces left
		test	byte [EXPForm+FORMPAR_Flags2],FORMFLAG2_Cent ; center?
		jz	ExpToTextBuf7	; no, right-justify
		shr	ecx,1		; ECX <- spaces / 2, round down
		jz	ExpToTextBuf72	; no spaces left
ExpToTextBuf7:	mov	al," "		; AL <- space
ExpToTextBuf71:	dec	esi		; decrease space counter
		stosb			; store one space
		loopnz	ExpToTextBuf71	; next character
		jz	short ExpToTextBuf76 ; buffer is full

Všechny potřebné informace jsou nyní již k dispozici a proto může být zahájeno dekódování čísla do výstupního bufferu.

Není-li číslo zarovnáno doleva (příznak FORMFLAG1_Left) a nejsou-li ani požadovány nuly (příznak FORMFLAG2_Zero), je nutno před číslo doplnit úvodní mezery. Do registru ECX se připraví z parametru FORMPAR_Width požadovaná šířka pole. Odečtením délky textu z registru EDX se obdrží zbývající šířka pro okraje. 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čí.


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

ExpToTextBuf72:	mov	al,"-"		; AL <- negative sign
		test	byte [EXPSign],B7 ; negative number?
		jnz	ExpToTextBuf73	; negative number
		test	byte [EXPForm+FORMPAR_Flags1],FORMFLAG1_Sign ; sign?
		mov	al,"+"		; AL <- positive sign
		jnz	ExpToTextBuf73	; use positive sign
		test	byte [EXPForm+FORMPAR_Flags1],FORMFLAG1_Space ; space?
		jz	ExpToTextBuf74	; no space
		mov	al," "		; AL <- space
ExpToTextBuf73:	dec	esi		; decrease space counter
		stosb			; store sign
		jz	short ExpToTextBuf76 ; buffer is full

Před číslo se uloží znaménko. Je-li číslo záporné, uloží se znaménko mínus "-". Je-li znaménko vynucené (příznak FORMFLAG1_Sign), uloží se znaménko plus "+". Má-li být mezera místo kladného znaménka (příznak FORMFLAG1_Space), uloží se znak mezery " ". Jinak se žádný znak neuloží. Pokud čítač ESI volného místa v cílovém bufferu dosáhl nuly, funkce se ihned ukončí.


; ------------- Add leading zeros

ExpToTextBuf74:	test	byte [EXPForm+FORMPAR_Flags2],FORMFLAG2_Zero ; zeros?
		jz	ExpToTextBuf77	; no zeros
		movzx	ecx,byte [EXPForm+FORMPAR_Width] ; ECX <- minimal width
		sub	ecx,edx		; ECX <- remaining spaces
		jle	ExpToTextBuf77	; no spaces left
		mov	al,"0"		; AL <- zero
ExpToTextBuf75:	dec	esi		; decrease space counter
		stosb			; store zero
		loopnz	ExpToTextBuf75	; next character
ExpToTextBuf76:	jz	short ExpToTextBuf82 ; buffer is full

Má-li být číslo doplněno nulami namísto mezerami, uloží se před začátek čísla úvodní nuly. Do registru ECX se připraví požadovaná šířka pole, odečte se délka textu a uloží se nuly. Pokud během ukládání čítač ESI volného místa v cílovém bufferu dosáhne nuly, funkce se ihned ukončí.


; ============= Decode mantissa

ExpToTextBuf77:	lea	edx,[EXPFloat]	; EDX <- pointer to mantissa

; ------------- Store integer part

		mov	al,[edx]	; AL <- first digit
		and	al,0fh		; AL <- mask digit
		add	al,"0"		; AL <- convert to ASCII
		dec	esi		; decrease space counter
		stosb			; store one digit
		jz	short ExpToTextBuf82 ; buffer is full

Bude následovat dekódování jednotlivých číslic mantisy. Do registru EDX se připraví ukazatel na začátek mantisy v zásobníku. První číslice (z nižší tetrády prvního bajtu) se uloží vždy, jedná se o celočíselnou část mantisy. Pokud čítač ESI volného místa v cílovém bufferu dosáhl nuly, funkce se ihned ukončí.


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

		test	byte [EXPForm+FORMPAR_Flags2],FORMFLAG2_Alt ; dot?
		jz	ExpToTextBuf8	; no decimal point
		mov	eax,[EXPNat]	; EAX<-pointer to nationality NATIONAL
		mov	al,[eax+NAT_DecimalSep] ; AL <- decimal separator
		dec	esi		; decrease space counter
		stosb			; store decimal separator
		jz	short ExpToTextBuf82 ; buffer is full

Za první číslicí se uloží oddělovač desetinných míst, ale to jen v případě, že má být uložen. Příznak FORMFLAG2_Alt je již připraven tak, že není-li nastaven, nebudou následovat žádné desetinné číslice a další operace se mohou přeskočit. Pokud během ukládání oddělovače desetinných míst čítač ESI volného místa v cílovém bufferu dosáhne nuly, funkce se ihned ukončí.


; ------------- Prepare number of digits after decimal point (-> ECX)

		movzx	ecx,byte [EXPForm+FORMPAR_Prec]	; ECX <- num. of digits
		jecxz	ExpToTextBuf8	; no digit
		cmp	cl,18		; check maximal precision
		jb	ExpToTextBuf78	; precision is OK
		mov	cl,18		; CL <- 18, limit precision

; ------------- Decode mantissa - second digit

ExpToTextBuf78:	mov	al,[edx]	; AL <- 2 digits
		shr	al,4		; AL <- mask digit
		add	al,"0"		; AL <- convert to ASCII
		dec	esi		; decrease space counter
		stosb			; store one digit
		jz	short ExpToTextBuf82 ; buffer is full
		dec	ecx		; character counter
		jz	ExpToTextBuf79	; no next character

; ------------- Decode mantissa - first digit

		inc	edx		; EDX <- shift pointer
		mov	al,[edx]	; AL <- 2 digits
		and	al,0fh		; AL <- mask digit
		add	al,"0"		; AL <- convert to ASCII
		dec	esi		; decrease space counter
		stosb			; store one digit
		loopnz	ExpToTextBuf78	; next character
		jz	short ExpToTextBuf82 ; buffer is full

Do registru ECX se připraví počet desetinných číslic a omezí se na maximální počet 18 číslic.

Číslice mantisy jsou v zásobníku uloženy jako BCD číslice, tj. každý bajt mantisy obsahuje v nižší tetrádě první číslici a v druhé tetrádě druhou číslici. První číslice byla již dekódována před oddělovačem desetinných míst, proto cyklus začíná dekódováním druhé číslice (z vyšší tetrády) a pokračuje dekódováním první číslice z dalšího bajtu. Pokud během ukládání číslic čítač ESI volného místa v cílovém bufferu dosáhne nuly, funkce se ihned ukončí.


; ------------- Store trailing zeros

ExpToTextBuf79:	movzx	ecx,byte [EXPForm+FORMPAR_Prec]	; ECX <- num. of digits
		sub	cl,18		; ECX <- remaining zeros
		jle	ExpToTextBuf8	; no zeros left
		mov	al,"0"		; AL <- trailing zero
ExpToTextBuf7A:	dec	esi		; decrease space counter
		stosb			; store one digit
		loopnz	ExpToTextBuf7A	; next digit
		jz	short ExpToTextBuf82 ; buffer is full

Následuje uložení nevýznamných koncových nul. Nuly se uloží v případě, že je požadována vyšší přesnost než 18 číslic za oddělovačem desetinných míst, jinak byly nuly již zajištěny mantisou. Pokud během ukládání číslic čítač ESI volného místa v cílovém bufferu dosáhne nuly, funkce se ihned ukončí.


; ============= Exponent (here is EBX = decimal exponent)

; ------------- Exponent separator

ExpToTextBuf8:	mov	al,[EXPChar]	; AL <- exponent character
		dec	esi		; decrease space counter
		stosb			; store exponent separator
		jz	short ExpToTextBuf82 ; buffer is full

; ------------- Exponent sign

		mov	al,"-"		; AL <- minus sign
		test	byte [EXPSign],B6 ; negative exponent?
		jnz	ExpToTextBuf81	; negative exponent
		mov	al,"+"		; AL <- plus sign
ExpToTextBuf81:	dec	esi		; decrease space counter
		stosb			; store exponent separator
ExpToTextBuf82:	jz	short ExpToTextBuf9 ; buffer is full

Za mantisou bude uložen exponent. Absolutní hodnota dekadického exponentu je v registru EBX. Nejdříve se uloží oddělovací znak exponentu, který je v proměnné EXPChar (písmeno malé "e" nebo velké "E"). Za oddělovacím znakem exponentu se uloží znak znaménka "-" nebo "+" podle příznakového bitu v proměnné EXPSign (bit 6).


; ------------- Decode exponent

		imul	eax,ebx,268436	; EAX <- multiple with 1000'0000h/1000
		shr	eax,28		; AL <- thousands
		jz	ExpToTextBuf83	; no thousand digit
		add	al,"0"		; AL <- convert to ASCII character
		dec	esi		; decrease space counter
		stosb			; store digit
		jz	short ExpToTextBuf9 ; buffer is full
		sub	al,"0"		; AL <- return thousands
		imul	eax,eax,1000	; EAX <- thousands
		sub	ebx,eax		; EBX <- exponent without thousands

ExpToTextBuf83:	imul	eax,ebx,2684355	; EAX <- multiple with 1000'0000h/100
		shr	eax,28		; AL <- hundreds
		add	al,"0"		; AL <- convert to ASCII character
		dec	esi		; decrease space counter
		stosb			; store digit
		jz	short ExpToTextBuf9 ; buffer is full
		sub	al,"0"		; AL <- return hundreds
		imul	eax,eax,100	; EAX <- hundreds
		sub	ebx,eax		; EBX <- exponent without hundreds

ExpToTextBuf85:	xchg	eax,ebx		; EAX <- exponent 0 to 99
		aam			; AL <- units, AH <- tens
		xchg	al,ah		; AL <- tens, AH <- units
		add	al,"0"		; AL <- convert to ASCII character
		dec	esi		; decrease space counter
		stosb			; store digit
		jz	short ExpToTextBuf9 ; buffer is full
		mov	al,ah		; AL <- units
		add	al,"0"		; AL <- convert to ASCII character
		dec	esi		; decrease space counter
		stosb			; store digit
		jz	short ExpToTextBuf9 ; buffer is full

Exponent se bude dekódovat jako 3 nebo 4 číslice. Vydělením exponentu číslem 1000 se obdrží nejvyšší číslice exponentu (tisíce). Pro urychlení se namísto operace dělení použije vynásobení převrácenou hodnotou. Nejvyšší číslice exponentu se uloží jen v případě, že není nulová. Po uložení číslice tisíců se číslice odečte od dekadického exponentu.

Vydělením exponentu (nebo jeho zbytku bez tisíců) číslem 100 se obdrží číslice stovek. Pro urychlení se namísto operace dělení použije vynásobení převrácenou hodnotou. Číslice stovek se odečte od exponentu v registru EBX.

Nakonec se uloží číslice jednotek a desítek, k rozložení exponentu na jednotky a desítky se použije instrukce AAM. Pokud během ukládání číslic exponentu čítač ESI volného místa v cílovém bufferu dosáhne nuly, funkce se ihned ukončí.


; ------------- Store trailing spaces

		test	byte [EXPForm+FORMPAR_Flags2],FORMFLAG2_Zero ; zeros?
		jnz	short ExpToTextBuf9 ; zeros, no spaces
		mov	eax,[EXPLen]	; EAX <- text length
ExpToTextBuf86:	movzx	ecx,byte [EXPForm+FORMPAR_Width] ; ECX <- min. width
		sub	ecx,eax		; ECX <- remaining spaces
		jle	short ExpToTextBuf9 ; no spaces remain
		test	byte [EXPForm+FORMPAR_Flags1],FORMFLAG1_Left ; left?
		jnz	ExpToTextBuf87	; left-justify
		test	byte [EXPForm+FORMPAR_Flags2],FORMFLAG2_Cent ; center?
		jz	short ExpToTextBuf9 ; no center
		shr	ecx,1		; ECX <- spaces / 2
		adc	cl,ch		; ECX <- round up
		jz	short ExpToTextBuf9 ; no spaces
ExpToTextBuf87:	mov	al," "		; AL <- space
ExpToTextBuf88:	stosb			; store one space
		dec	esi		; decrease space counter
		loopnz	ExpToTextBuf88	; next character

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

ExpToTextBuf9:	mov	esp,ebp		; pop ESP
		pop	ebp		; pop EBP
		pop	edx		; pop EDX
		pop	ecx		; pop ECX
		pop	ebx		; pop EBX
		pop	eax		; pop EAX
		ret

Poslední operací je uložení mezer za koncem čísla. Je-li požadováno použití nul namísto mezer, není potřeba již ukládat žádnou mezeru a funkce se ukončí. Jinak se do registru EAX načte délka textu (bez mezer) a do registru ECX požadovaná šířka pole, odečtením zůstane v registru ECX počet zbývajících mezer. Pokud žádné mezery pro okraje nezbyly, funkce se ukončí.

Je-li nastaven příznakový bit FORMFLAG1_Left, je číslo zarovnáno doleva, ihned se přejde k ukládání mezer za číslo. Není-li tento příznak nastaven a není-li nastaven ani příznakový bit FORMFLAG2_Cent, bylo číslo zarovnáno doprava a mezery tedy již byly uloženy dříve, takže se funkce ukončí. Jinak platí, že číslo je centrováno. Do registru ECX se připraví poloviční počet mezer, ale tentokrát se zaokrouhlí nahoru (aby se zachytila případná lichá mezera).

Následuje ukládání mezer do bufferu. Počet mezer je dán čítačem v registru ECX. Současně se sleduje zbývající volné místo v cílovém bufferu čítáním registru ESI. Pokud dosáhne nuly, bylo dosaženo konce bufferu a smyčka se ukončí.


Obsah / Utility / TEXTFORM / ExpSToTextBuf, ExpCToTextBuf