flat assembler
Message board for the users of flat assembler.

Index > DOS > [tasm] Displaying floating point numbers in 16-bit assembly?

Author
Thread Post new topic Reply to topic
galikk



Joined: 17 Jan 2023
Posts: 1
galikk 17 Jan 2023, 22:47
For studies, I have to write a program in TASM x86, which will calculate tangens of x. I wrote this using stack. I've never dealt with ASM before and we were given little time for the project. The program compiles, but i have trouble with displaying a value. Program displays a random signs (I'am guessing, maybe ASCII code). Lecturer gave us a hint that we have to change number into string, but I have no idea how to do it.

Does anybody have any idea, how to do this with any possible way?

Code:
.model small
.stack 100h

.data

   result dq 0.0

    x dq 0.5
    two dq 2.0
    three dq 3.0
    fifteen dq 15.0
    seventeen dq 17.0
    three_hundred_fifteen dq 315.0

.code    
    
tan proc    
   ;x^3/3
   fld x
   fld x
   fmulp 
   fld x
   fmulp 
   fld three
   fdivp
   
   ;2x^5/15    
   fld x
   fld x
   fmulp 
   fld x
   fmulp 
   fld x
   fmulp
   fld x
   fmulp ;x^5
   fld two
   fmulp ;2x^5
   fld fifteen
   fdivp

   ;x^3/3 + 2x^5/15
   faddp
   
   ;17x^7/315
   fld x
   fld x
   fmulp 
   fld x
   fmulp 
   fld x
   fmulp
   fld x
   fmulp 
   fld x
   fmulp
   fld x
   fmulp ;x^7    
   fld seventeen    
   fmulp ; 17x^7    
   fld three_hundred_fifteen
   fdivp
   
   ;x^3/3 + 2x^5/15 + 17x^7/315
   faddp       
   ;x
   fld x
   
   ;x + x^3/3 + 2x^5/15 + 17x^7/315    
   faddp       
   fstp result       
   ret       

   tan endp    

start:
    call tan

    mov ah, 9
    mov dx, offset result
    int 21h
    
end start
    
[/code]
Post 17 Jan 2023, 22:47
View user's profile Send private message Reply with quote
al_Fazline



Joined: 24 Oct 2018
Posts: 54
al_Fazline 18 Jan 2023, 07:40
You need to convert binary integer to decimal by dividing it by 0Ah and putting remainders into the stack, until you get zero, then you unwind them into a variable (which you need to reserve some memory for), adding '0' (30h) every time, then you add decimal point and continue, this time you need to multiply the fractional part by 0Ah and append integer part of the result + '0' to the variable, until you got enough decimal digits. Then once you are done, append a $ and call int 21h with 9 in ah as you do here. 9th function requires $ as line terminator. Most other things use 0h to terminate strings but apparently not DOS.

Also why not to use fasm instead of tasm? It's kinda easier. But anyway, either will do.
Post 18 Jan 2023, 07:40
View user's profile Send private message Reply with quote
DimonSoft



Joined: 03 Mar 2010
Posts: 1228
Location: Belarus
DimonSoft 19 Jan 2023, 15:16
The question is about floating-point values though. But the principle is nearly the same, just with more corner cases if a universally usable implementation is the goal.

P.S. I guess, I’ll never stop being thankful to Tomasz for the clean and lean FASM syntax. (TASM/MASM’s one makes me feel bad each time I see their offset and ptr junk.)
Post 19 Jan 2023, 15:16
View user's profile Send private message Visit poster's website Reply with quote
al_Fazline



Joined: 24 Oct 2018
Posts: 54
al_Fazline 19 Jan 2023, 17:59
DimonSoft, yeah, I know. You can take the integer part first, convert it, and then go with the fractional part.

Or yeah, you can first take an integer part of decimal logarithm of the number, then put 0Ah to that power+1, and divide the number by it, so it's guaranteed you'll get something below 1, then you can multiply it by 0Ah and keep track of the decimal point position to print it when appropriate and continue.

Or, you can multiply the number by 0Ah in power of desired number of decimal digits, then take integer part and convert it to string, keeping in mind that you'll also need to count the digit and put decimal point in certain position.
Post 19 Jan 2023, 17:59
View user's profile Send private message Reply with quote
macomics



Joined: 26 Jan 2021
Posts: 1043
Location: Russia
macomics 19 Jan 2023, 20:55
DimonSoft wrote:
P.S. I guess, I’ll never stop being thankful to Tomasz for the clean and lean FASM syntax.

fasm also knows about ptr and can apply it.
Code:
; fasm1 ver. 1.73.30

format MZ

stack 128
heap 0

segment @data
string db 'Hello from fasm!$'

segment @text
entry @text:$
    mov ax, @data
    mov ds, ax
    mov es, ax

    lea dx, byte ptr string
    mov ah, 9
    int 33

    mov ax, $4C00
    int 33    


to galikk: In addition to the methods described above, you can also take the format of a real number and translate it into a string using only integer commands. But it will be long and difficult, although it is possible.

Format of a real 64-bit number:
Code:
; bitmap (63 <-> 0)
sqqqqqqqqqqqqmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
s - sign bit (1)
q - characteristic (12)
m - mantissa of a number (51)

p = q - 2048 ; The q value takes 12 bits. Thus, numbers from 0 to 4095 are placed in it. 
p - power (10=2) ; If you subtract 2048 from this value, then the p value will become signed and will be in the range from -2048 to 2047.

sign
v
-0.314159e1 <- power
  \    /
mantissa of a number    
A mantissa is a normalized exponential number in binary representation. A normalized number is called when it has only one (not zero) digit of the digit in the integer part (for the binary number, this means 1 bit). That is, the highest bit in the mantissa is always 1 and is not written in this number, which means the dimension of the mantissa is not 51, but 52 bits (it still needs to be supplemented with the highest 1).

But the position of the point is already determined by the value of the power (p). Using the value of p and dividing the bits of m into an integer and a real part, you can start translating them into a string. How to do this was written to you in the 2nd answer.
Post 19 Jan 2023, 20:55
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20454
Location: In your JS exploiting you and your system
revolution 20 Jan 2023, 03:31
In theory the tan function can return numbers in the range -inf to +inf so the conversion to decimal representation needs to account for all possible values.

But in practice using qword floats I can't find a value that exceeds 10^16
Code:
input: 1.5707963267948963
tan: 3530114321217157.5

input: 1.5707963267948966
tan: 1.633123935319537e+16

input: 1.5707963267948968
tan: -6218431163823738.0    
However going the other direction into tiny numbers we have this as the smallest value (aside from zero of course):
Code:
input: 5e-324
tan: 5e-324    
Post 20 Jan 2023, 03:31
View user's profile Send private message Visit poster's website Reply with quote
DimonSoft



Joined: 03 Mar 2010
Posts: 1228
Location: Belarus
DimonSoft 22 Jan 2023, 20:48
macomics wrote:
fasm also knows about ptr and can apply it.

I’m well aware of that and the MASM.INC macros and I’m extremely thankful to Tomasz for making the stupid nonsense optional in FASM. Thankful both as a programmer and as a university teacher.
Post 22 Jan 2023, 20:48
View user's profile Send private message Visit poster's website Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 805
Location: Russian Federation, Sochi
ProMiNick 22 Jan 2023, 22:42
may be it will help to think
demo
https://disk.yandex.ru/d/wDAXIae2DGcQSA
https://t.me/ChatAssembler/177696
source
https://t.me/ChatAssembler/177704
screenshot
https://t.me/ChatAssembler/177695
I made it for myself as newton apple to call ideas, but they still not come (for start - on what value I should myltiply any float (calculated from float) to atleast extract first decimal digit.
[post edited, dropbox link added]
https://www.dropbox.com/s/7mlkb38i25yudhn/PJ3.zip?dl=0


Last edited by ProMiNick on 23 Jan 2023, 07:07; edited 1 time in total
Post 22 Jan 2023, 22:42
View user's profile Send private message Send e-mail Reply with quote
al_Fazline



Joined: 24 Oct 2018
Posts: 54
al_Fazline 23 Jan 2023, 06:16
ProMiNick, that's a bad link, it does not work without registration in Telegram.
Post 23 Jan 2023, 06:16
View user's profile Send private message Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 805
Location: Russian Federation, Sochi
ProMiNick 23 Jan 2023, 23:11
thoughts
Code:
exp  mantissa           value                           realexp     mantissa
3FEB 80000000 00000000  +0.00000095367431640625(1/1M)   ?(3FEB)     80000000 00000000
3FEB 8637BD05 AF6C69B6  +0.000001                       ?(3FEB)     8637BD05 AF6C69B6
3FF5 80000000 00000000  +0.0009765625(1/1K)             ?(3FF5)     80000000 00000000
3FF5 83126E97 8D4FDF3B  +0.001                          ?(3FF5)     83126E97 8D4FDF3B
3FFA CCCCCCCC CCCCCCCD  +0.05                           ?(3FFA)     CCCCCCCC CCCCCCCD
3FFB CCCCCCCC CCCCCCCD  +0.1                            ?(3FFB)     CCCCCCCC CCCCCCCD
3FFC CCCCCCCC CCCCCCCD  +0.2                            ?(3FFC)     CCCCCCCC CCCCCCCD
3FFD AAAAAAAA AAAAAAAA  +0.33333333333333333333         ?(3FFD)     AAAAAAAA AAAAAAAA
3FFD CCCCCCCC CCCCCCCD  +0.4                            ?(3FFD)     CCCCCCCC CCCCCCCD
3FFE 80000000 00000000  +0.5                            ?(3FFE)     80000000 00000000
3FFE 99999999 9999999A  +0.6                            ?(3FFE)     99999999 9999999A
3FFE A0000000 00000000  +0.625                          ?(3FFE)     A0000000 00000000
3FFE AAAAAAAA AAAAAAAA  +0.66666666666666666666         ?(3FFE)     AAAAAAAA AAAAAAAA
3FFE AAAAAAAA AAAAAAAB  +0.66666666666666666667         ?(3FFE)     AAAAAAAA AAAAAAAB
3FFE CCCCCCCC CCCCCCCD  +0.8                            0(403E)     CCCCCCCC CCCCCCCD
3FFF 80000000 00000000  +1.0                            0(403E)     00000000 00000001
4000 80000000 00000000  +2.0                            0(403E)     00000000 00000002
4000 ADF85458 A2BB4A99  +2.718281828459045235           ?(4000)     ADF85458 A2BB4A99
4000 C0000000 00000000  +3.0                            0(403E)     00000000 00000003
4000 C90FDAA2 2168C233  +3.141592653589793238           ?(4000)     C90FDAA2 2168C234
4001 80000000 00000000  +4.0                            0(403E)     00000000 00000004
4001 A0000000 00000000  +5.0                            0(403E)     00000000 00000005
4002 80000000 00000000  +8.0                            0(403E)     00000000 00000008
4002 A0000000 00000000  +10.0                           0(403E)     00000000 0000000A
4008 C8000000 00000000  +100.0                          0(403E)     00000000 00000064
4008 FA000000 00000000  +1000.0                         0(403E)     00000000 000003E8
4009 80000000 00000000  +1024.0                         0(403E)     00000000 00000400
400B 9C400000 00000000  +5000.0                         0(403E)     00000000 00001388
4012 F4240000 00000000  +1000000.0                      0(403E)     00000000 00F42400
4012 F4240000 00000000  +1000000.0                      0(403E)     00000000 00F42400
401C EE6B2800 00000000  +1000000000.0                   0(403E)     00000000 3B9ACA00
4026 E8D4A510 00000000  +1000000000000.0                0(403E)     000000E8 D4A51000
4030 E35FA931 A0000000  +1000000000000000.0             0(403E)     00038D7E A4C68000
403A DE0B6B3A 76400000  +1000000000000000000.0          0(403E)     0DE0B6B3 A7640000
403C 96E51BAF 02CD85CC  +2718281828459045235.0          0(403E)     25B946EB C0B36173
403C AE64B77E 88C92758  +3141592653589793238.0          0(403E)     2B992DDF A23249D6
403E 8AC72304 89E80000  +10000000000000000000.0         0(403E)     8AC72304 89E80000
403E AAAAAAAA AAAAAAAA  +12297829382473034410.0         0(403E)     AAAAAAAA AAAAAAAA
403E CCCCCCCC CCCCCCCD  +14757395258967641293.0         0(403E)     CCCCCCCC CCCCCCCD
403E FFFFFFFF FFFFFFFF  +18446744073709551615.0         0(403E)     FFFFFFFF FFFFFFFF    


Code:
        xor     ecx, ecx
        jmp     simplest_case

   simplest_case.zero_low_part:
        add     [exponent], 32
        xor     eax, eax
        xchg    eax, [hidwordmantissa]
        mov     [lodwordmantissa], eax
   simplest_case:
        bsf     ecx, [lodwordmantissa]
        jz      .zero_low_part ; no infinite loop, completely zero mantissa must be handled previously
        jecxz   .state_done
        mov     eax, [hidwordmantissa]
        shrd    [lodwordmantissa], eax, cl
        shr     [hidwordmantissa], cl
        add     [exponent], ecx
   .state_done:
        sub     [exponent],$403E ; in IEEE zero is $3FFF, but we consider $3FFF+63 as zero exponent
        jnz     .noluck
        ;here qword at [lodwordmantissa] can be transformed as usual integer qword to string
    .noluck
        ;multiply or divide mantissa on value from table for exponent ((2 shl 10) shl n ): +$10 +$20 +$40 +$80 and so on  
        test    [exponent], $1F ; is real exponent misaligned and required extramantissa?
        jz      .no_extramantissa
 ;for rest - [lodwordmantissa],[hidwordmantissa],[extramantissa] hold mantissa    


could I found values for table on what multiply/divide?
could this be solved the way I think?
of course I don`t touch denormalized but they too fit 63 bits, could be multiplyed some value (maybe left couple bits for extramantissa) and again translation would be integer qword to string.
Code:
; 7654321076543210                 7654321076543210
;$CCCCCCCCCCCCCCCD*10 shl 0      =$8000000000000000.2 (.2 - no matter, rounded)
; ||||||||||||||||
;  repeat period
; [---][---][---][
;$A3D70A3D70A3D70A*100 shl 1     =$7FFFFFFFFFFFFFFF.D0 (.D - rounded up to 80...)
;                   repeat period
; [-----------------------][-----------------------]
;$83126E978D4FDF3B645A1CAC083126E978D4FDF3B645A1CAC0*1000 shl 2 (shr 2 - no matter)
;$83126E978D4FDF3B*1000 shl 2    =$7FFFFFFFFFFFFFFF.9E0 (.D - rounded up to 80...)

;$8637BD05AF6C69B6*1000000 shl 5 =$8000000000000000.5598 (bad .5 is rouded up)

;$8CBCCC096F5088CC*10^12 shl 11  =$8000000000000000.062408C (.0 - no matter, rounded)

;$9ABE14CD44753B53*10^24 shl 23  =$8000000000000000.312861A5CA2633 (.3 - no matter, rounded)

;same as upper
_0.5            =$8000000000000000

_0.1            =$CCCCCCCCCCCCCCCD ;_0.1                *5              =_0.5
_0.01           =$A3D70A3D70A3D70A ;_0.01               *25 shl 1       =_0.5
_0.001          =$83126E978D4FDF3B ;_0.001              *125 shl 2      =_0.5
_0.000001       =$8637BD05AF6C69B6 ;_0.000001           *15625 shl 5    =_0.5
_0.000000000001 =$8CBCCC096F5088CC ;_0.000000000001     *15625 shl 11    =_0.5

macro mantissa [flt] {
        virtual
                dt flt
                load mantissa qword from $$
        end virtual
        dq mantissa }
; we could hold full twords, but every hi word of tword will be wasting of space
;mantissa +1E-1,+1E-2,+1E-3,+1E-6,+1E-12 same as dq _0.1,_0.01,_0.001,_0.000001,_0.000000000001 but we dont needed to explore bicycle and assembler calculate them for us
mantissa +1E-1,+1E-2,+1E-3,+1E-6,+1E-12,+1E-24,+1E-48,+1E-96,+1E-192; ... multiplier table (64bit is enought precision for single, double & double extended)
mantissa +1E+1,+1E+2,+1E+3,+1E+6,+1E+12,+1E+24,+1E+48,+1E+96,+1E+192; ... multiplier table    
Post 23 Jan 2023, 23:11
View user's profile Send private message Send e-mail Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.