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

Obsah / Utility / TEXTFORM / SDWToTextBufN

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

Související:

SDWToTextBuf   Konverze neformátovaného čísla DWORD se znaménkem na text
FormToTextBufN   Délka formátovaného textu

SDWToTextBufN - Délka textu neformátovaného čísla DWORD se znaménkem

Funkce SDWToTextBufN zjistí velikost bufferu potřebného k dekódování neformátovaného čísla DWORD se znaménkem do bufferu.


; -----------------------------------------------------------------------------
;     Convert unformatted signed DWORD into text buffer - get text length
; -----------------------------------------------------------------------------
; INPUT:	EAX = signed number
;		ECX = minimal text length (0...)
; OUTPUT:	EAX = text length (0...)
; -----------------------------------------------------------------------------

Na vstupu funkce obsahuje registr EAX číslo se znaménkem ke konverzi a registr ECX požadovanou minimální délku textu (včetně znaménka). Na výstupu navrací funkce v registru EAX délku textu v bajtech.


; ------------- Check if number is negative

SDWToTextBufN:	or	eax,eax		; is number negative?
		jns	short UDWToTextBufN ; number is not negative

Je-li konvertované číslo nezáporné, je obsluha převedena na funkci pro zjištění délky čísla bez znaménka UDWToTextBufN, jinak se pokračuje obsluhou záporných čísel.


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

		push	ebx		; push EBX

; ------------- Get number of bits in number (-> EBX, number is not 0)

		neg	eax		; EAX <- absolute value
		bsr	ebx,eax		; EBX <- highest bit in number
		inc	ebx		; EBX <- number of bits in number

Délka textu bude odvozena z dekadického logaritmu čísla, tedy z dekadického řádu nejvyšší číslice. Výchozím údajem bude binární logaritmus, tedy počet bitů v čísle, které je zjištěno instrukcí BSR (hledání bitu směrem zpět) a následnou inkrementací nalezené pozice nejvyššího bitu. Nula se v tomto místě nemůže vyskytnout.


; ------------- Get number of digits (ln 10/ln 2=3.3219, 10000h/3.3219=19729)

		imul	ebx,ebx,19729	; EBX <- approx. number of digits << 16
		shr	ebx,16		; EBX <- approx. number of digits
		cmp	[IntMul10+ebx*4],eax ; check number (0:0, 1:9, 2:99,..)
		xchg	eax,ebx		; EAX <- text length
		adc	al,1		; EAX <- number of digits + sign char

Zjištěný binární logaritmus bude převeden na dekadický logaritmus vydělením číslem ln 10 / ln 2 = 3,3219 (přibližně). Namísto dělení se použije rychlejší operace násobení převrácenou hodnotou, tj. číslem 10000h/3.3219 (zaokrouhleno nahoru). Po posunu o 16 bitů doprava se v registru EBX obdrží výsledný dekadický logaritmus (přesněji jeho celočíselná část).


; ------------- Table of multiple of 10 - 1 (1-1 to 1000000000-1)

		align	4, db 0
IntMul10:
		%assign	INTMUL10 1
		%rep	10
		dd	INTMUL10-1
		%assign	INTMUL10 INTMUL10*10
		%endrep

Přibližný počet číslic je již známý, ale údaj je potřeba ještě upřesnit, protože binární logaritmy mohou ležet přes hranici dekadických logaritmů. K tomu slouží tabulka IntMul10, která obsahuje násobky 10 snížené o 1, tedy čísla 0, 9, 99, 999 atd. Porovnáním původního čísla s hranicí podle vypočteného dekadického logaritmu čísla se upřesní, zda číslo leží nad hranicí nebo pod hranicí a pokud leží nad hranicí, počet číslic se zvýší o 1. Současně se přičte další 1, aby se započítalo záporné znaménko.


; ------------- Minimal text length

		cmp	eax,ecx		; check minimal text length
		ja	SDWToTextBufN4	; text length is OK
		mov	eax,ecx		; EAX <- limit minimal text length

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

SDWToTextBufN4:	pop	ebx		; pop EBX
		ret

Po zjištění skutečné délky čísla se vypočtený počet číslic porovná se zadanou minimální délkou textu a je-li menší, použije se namísto vypočtené délky zadaná minimální délka textu.


Obsah / Utility / TEXTFORM / SDWToTextBufN