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

Obsah / Utility / TEXTFORM / UDWToTextBufN

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

Související:

UDWToTextBuf   Konverze neformátovaného čísla DWORD bez znaménka na text
FormToTextBufN   Délka formátovaného textu

UDWToTextBufN - Délka textu neformátovaného čísla DWORD bez znaménka

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


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

Na vstupu funkce obsahuje registr EAX číslo bez znaménka ke konverzi a registr ECX požadovaný minimální počet číslic. Na výstupu navrací funkce v registru EAX délku textu v bajtech.


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

UDWToTextBufN:	push	ebx		; push EBX

; ------------- Get number of bits in number (-> EBX)

		bsr	ebx,eax		; EBX <- highest bit in number
		jz	UDWToTextBufN2	; number is zero, no digit
		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. Je-li číslo nula, bude se pokračovat s počtem číslic 0.


; ------------- 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,0		; EAX <- number of digits

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.


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

UDWToTextBufN2:	cmp	eax,ecx		; check number of digits
		ja	UDWToTextBufN4	; number of digits is OK
		mov	eax,ecx		; EAX <- limit minimal number of digits

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

UDWToTextBufN4:	pop	ebx		; pop EBX
		ret

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


Obsah / Utility / TEXTFORM / UDWToTextBufN