Obsah / Utility / TEXTFORM / FloatMantBCD
Zdrojový kód: INCLUDE\UTIL\TEXTFORM.INC, UTIL\TEXTFORM.ASM
Související:
FltToTextBuf | Zformátování desetinného čísla do bufferu | |
FltToTextBufN | Délka textu formátovaného desetinného čísla | |
ExpSToTextBuf | Zformátování čísla s exponentem do bufferu, malé "e" | |
ExpCToTextBuf | Zformátování čísla s exponentem do bufferu, velké "E" | |
ExpToTextBufN | Délka textu formátovaného čísla s exponentem |
FloatMantBCD - Zaokrouhlení, denormalizace a konverze mantisy na BCD
Funkce FloatMantBCD je interní funkce používaná funkcemi dekódujícími desetinné číslo na text. Zajistí zaokrouhlení mantisy čísla na požadovaný počet desetinných míst a konverzi mantisy na BCD číslice.
|
Na vstupu funkce obsahuje registr EAX požadovanou přesnost desetinné části čísla (tj. počet desetinných míst, bude omezeno na 18). EBX obsahuje dekadický exponent. V ECX je ukazatel na číslo v zásobníku s rozšířenou přesností (tj. 10 bajtů). V registru ST0 je normalizované kladné desetinné číslo v rozsahu 1 (včetně) až 10 (vyjma). Příznak CY zakazuje zaokrouhlení čísla, číslo se zaokrouhlí vždy na 19 číslic.
Na výstupu funkce obsahuje registr EBX nový dekadické exponent. V zásobníku, kam ukazuje registr ECX, jsou navrácený číslice mantisy v BCD formátu. Je navráceno 19 číslic a to tak, že významnější číslice jsou na nižších adresách a v nižších tetrádách. Například číslo 1,23456 bude dekódováno jako 21h 43h 65h 00h 00h ...
Funkce zničí obsah registrů EAX, ECX a EDX, použije jeden další registr koprocesoru a uvolní vstupní číslo z registru ST0.
|
Po úschově registrů a nastavení ukazatele cílového bufferu do EDI bude omezena požadovaná přesnost. Pokud byl nastaven příznak CY, nemá být číslo zaokrouhleno. Je-li požadovaná přesnost 18 a více, omezí se přesnost na 18 desetinných míst. Pro menší přesnost se do registru CH uloží skutečná požadovaná přesnost (jako počet požadovaných číslic) a do registru EAX omezená přesnost 18 číslic (pro další operace již vynásobeno 10x).
Má-li se číslo zaokrouhlovat, je při překročení hodnoty 18 omezen počet desetinných míst na 18. Požadovaná přesnost je uložena do registru CH.
|
Podle hodnoty požadované přesnosti je k číslu připočtena zaokrouhlovací konstanta z tabulky RoundTab. Konstanta je volena tak, aby tvořila hodnotu 0,5 za poslední dekódovanou číslicí. Například při zaokrouhlení čísla 5,6789 na 2 desetinná místa se přičte konstanta 0,005, vznikne číslo 5,6839. Po dekódování požadovaných 1+2 číslic bude výsledné číslo 5,68. Nemá-li být číslo zaokrouhlováno, je vždy přičtena zaokrouhlovací konstanta na nejnižší možné 18. pozici, aby se zaokrouhlily chyby výpočtu.
|
Po přičtení zaokrouhlovací korekce se může stát, že dojde k posunu řádu exponentu a k denormalizaci mantisy. Jedná se například o číslo 9,9999, které po zaokrouhlení na 2 desetinná místa přeteče na hodnotu 10,00. Proto je nutné mantisu opět normalizovat. Pokud mantisa dosáhla hodnotu 10, je vynásobena konstantou 0,1 a současně je inkrementací registru EBX opravena hodnota exponentu.
|
Po přípravě mantisy bude mantisa načtena do registrů. U čísla normalizovaného do rozsahu 1 až 10 bude binární exponent čísla v rozsahu 0 až 3. Mantisu je nutno denormalizovat tak, aby byl binární exponent čísla vynulován. V tom případě bude celočíselná část mantisy obsahovat první číslici čísla.
Mantisa je z registru ST0 uložena do zásobníku (na který ukazuje registr EDI). Do registru CL je načten nižší bajt binárního exponentu (vyšší bajt je 0). Přičtením 2 k CL se jednak provede korekce počátečního offsetu exponentu (binární exponent má hodnotu 3FFFh pro nulový dekadický exponent) a jednak se přednastaví počet rotací o 1 vyšší, aby se nejvyšší celočíselný bit dostal do nejvyššího registru.
Do registru ESI je načteno vyšší dvojslovo mantisy a současně je původní obsah v zásobníku vynulován. Stejně tak je načteno nižší dvojslovo mantisy a původní obsah i dalších částí v zásobníku je vynulován.
Mantisa je v registrech EAX:ESI:EBX (registr EAX je zatím nulový), rotací doleva o CL bitů pomocí instrukcí SHLD se mantisa denormalizuje tak, že registr EAX obsahuje nejvyšší číslici mantisy.
|
Dále již bude pokračovat konverze mantisy na BCD číslice. Do registru ECX se připraví požadovaný počet desetinných míst (0 až 18), zvýšením o 1 se připočítá první, celočíselná, číslice. První číslice je již připravená v registru EAX, proto může být již přímo uložena do bufferu jako nižší tetráda prvního bajtu.
Mantisa v registrech ESI:EBX je binární desetinné číslo. Vynásobením deseti přeteče do nejvyššího registru EAX další číslicem která se uloží do bufferu jako nižší tetráda bajtu. Čítáním registru ECX se sleduje počet požadovaných číslic.
|
Během dekódování číslic se střídavě dekódují číslice do nižší a do vyšší tetrády bufferu. Dekódování sudých číslic je prakticky stejné jako dekódování lichých číslic s tím rozdílem, že číslice se rotuje o 4 bity k vyšším bitům a uloží se do posledního bajtu bufferu operací OR.
Ke konverzi mantisy na BCD číslice by bylo možné alternativně použít funkci koprocesoru FBSTP, v tom případě by se mantisa nejdříve převedla na celé číslo vynásobením číslem 1e+18. Převod vlastní obsluhou pomocí registrů má však několik výhod - možnost řídit počet číslic (instrukce FBSTP dekóduje vždy 18 číslic), číslice jsou v obráceném pořadí, které více vyhovuje dalšímu zpracování a rychlost konverze je buď stejná nebo při menším počtu číslic i větší oproti FBSTP.
Obsah / Utility / TEXTFORM / FloatMantBCD