flat assembler
Message board for the users of flat assembler.

flat assembler > DOS > Floating point numbers

Author
Thread Post new topic Reply to topic
A$M



Joined: 29 Feb 2012
Posts: 94
Hello all!

I would know how to use floating point numbers in Assembly. I do not understand almost nothing about it. So if anyone has some spare time, please teach me how to use them or where to learn about them (I could not understand the FASM documentation).
Post 25 Feb 2013, 21:05
View user's profile Send private message Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1389
Location: Toronto, Canada
I learned here:
http://www.website.masmforum.com/tutorials/fptute/
Great article about float point processing!

So, what kind of problem you're trying to solve?
Most of the difficulty are conversions to/from text:

TEXT -> FLOAT POINT REGISTER
FLOAT POINT REGISTER -> TEXT

The rest is just watching over the FPU stack so it would not overflow.
Please ask your questions -- I'll try to help.
Post 25 Feb 2013, 22:02
View user's profile Send private message Send e-mail Reply with quote
A$M



Joined: 29 Feb 2012
Posts: 94
AsmGuru62 wrote:
I learned here:
http://www.website.masmforum.com/tutorials/fptute/
Great article about float point processing!

So, what kind of problem you're trying to solve?
Most of the difficulty are conversions to/from text:

TEXT -> FLOAT POINT REGISTER
FLOAT POINT REGISTER -> TEXT

The rest is just watching over the FPU stack so it would not overflow.
Please ask your questions -- I'll try to help.


Thank you! Thank you! Thank you! Thank you! Thank you! Thank you! Thank you! Thank you! Thank you! Thank you! Thank you! Thank you! Thank you! Thank you! Thank you! Thank you! Thank you! Thank you! Thank you! Thank you! Thank you! Thank you!!! It's too easy...

A little program:
Code:
org 100h
use16

finit
fld [num3]
fld [num1]
fld [num2]
fmul ST0, ST1
fcom ST2
fstsw ax
fwait
sahf
jpe error
jne no
mov al, "Y"
jmp @f
no:
mov al, "N"
@@:
mov ah, 0Eh
int 10h

exit:
xor ax, ax
int 16h

ret

error:
mov ah, 0Eh
mov al, "E"
int 10h
jmp exit

num1 dt 1.01
num2 dt 5.5
num3 dt 5.555
    


It returns Y if "1.01*5.5=5.555", else returns N.
Post 26 Feb 2013, 21:05
View user's profile Send private message Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1389
Location: Toronto, Canada
So, it works?!
Post 26 Feb 2013, 22:24
View user's profile Send private message Send e-mail Reply with quote
A$M



Joined: 29 Feb 2012
Posts: 94
AsmGuru62 wrote:
So, it works?!


Works. Now, another program more complicated, but simple, which makes a circle. Please compile it and tell your opinion. I'm 13 years old and had to search for things I did not understand. That is, if there are any errors, please tell me. Anyone can copy, modify, print or do anything else.

Code:
    org 100h
    use16

    mov ax, 13h
    int 10h

    finit

    mov ax, 0A000h
    mov es, ax

next:
    call calculate
    mov cx, [x]
    mov dx, [y]
    call drawPixel
    inc [degrees]
    cmp [degrees], 360;ยบ
    jne next
    mov ax, 0
    int 16h

    ret

drawPixel: ; CX and DX = X and Y
    add cx, 70
    add dx, 70
    mov ax, dx
    shl dx, 6
    shl ax, 8
    add dx, ax
    mov bx, cx
    add bx, dx
    mov byte[es:bx], 15
    ret

calculate:
    ffree st7
    ffree st6
    ffree st5
    ffree st4
    ffree st3
    fild [radius]
    fild [halfcircle]
    fild [degrees]
    fldpi
    fmul st0, st1
    fdiv st0, st2
    fsincos
    fmul st0, st4
    fistp [x]
    fmul st0, st3
    fist [y]
    ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;                     Formulas                    ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Degrees (x) -> Radians = x pi/180               ;;
;; Degrees (x) Radius (r) -> X location = r cos(x) ;;
;; Degrees (x) Radius (r) -> Y location = r sin(x) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

radius     dw 25
degrees    dw 0
halfcircle dw 180
x          dw ?
y          dw ?
    


EDIT: It is dotted circles if the radius is large. No big issue. The solution would be to draw lines between the points, but it is unnecessary.
Post 27 Feb 2013, 19:43
View user's profile Send private message Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1389
Location: Toronto, Canada
Nice code.
I see just few things:

1. The way you return to DOS is most likely incorrect.
I think is the way you do it:
Code:
mov ax,0
int 16h
ret
    

That RET opcode may not work if you will run your program from standard DOS command line.
The proper way to stop the COM program is INT 20h:
Code:
mov ax,0
int 16h
int 20h
    

2. You can make it faster by only computing the pixels for 1/4 of a circle, because
the other 3/4 are a symmetrically positioned pixels just with oppisite sign for X and Y.
This way you need to perform only 25% of the pixels calculation.

3. You can even speed up more by not using degrees, but radians.
The circle takes up 2*PI in radians, meaning that you need a 1/360th part of it to be a 1 degree.
Create a variable and set it to (2*PI)/360 and use it as a step to increment your radian value going from 0 to 90, so you avoid the conversion on every step.
Post 27 Feb 2013, 20:11
View user's profile Send private message Send e-mail Reply with quote
freecrac



Joined: 19 Oct 2011
Posts: 117
Location: Germany Hamburg
AsmGuru62 wrote:
Nice code.
I see just few things:

1. The way you return to DOS is most likely incorrect.
I think is the way you do it:
Code:
mov ax,0
int 16h
ret
    

That RET opcode may not work if you will run your program from standard DOS command line.
The proper way to stop the COM program is INT 20h:
[code]
mov ax,0
int 16h
int 20h

But if we start a *.com-file under pure DOS and from the standard DOS command line, then DOS fill the PSP with an int 20h instruction and additional the stack starts with a word of 0000.
So if we terminate our application only with a ret-instruction, then our programmcounter will be set to this int 20h instruction inside of the PSP.
(adopted unix like ret-methode in MSDOS 2 and above?)

I can not see a big differce between using only a ret-instruction for to execute the int 20h instruction inside of the PSP, or to execute an int 20h instruction that was placed as the last instruction in our codesegment.
And i never read it before that there is a problem using only a ret instruction or that it is not a proper way for to stop a COM program.
The only normaly conditions are that we do not have to pop the last word from the stack and we do not have to corrupt the PSP structure and additional CS normaly pointed to our codesegment.

I need more information and a clarification about the difference and the statement that it is not a propper way. What does it means exactly?

Dirk
Post 28 Feb 2013, 07:41
View user's profile Send private message Send e-mail Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1389
Location: Toronto, Canada
Cool! I did not know (or just forgot) that about the PSP having INT 20h opcode.
I guess both RET and INT 20h would be fine to end a COM program.
Post 28 Feb 2013, 15:20
View user's profile Send private message Send e-mail Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
AsmGuru62 wrote:
I guess both RET and INT 20h would be fine to end a COM program.
Unless you're fiddling with cs. Those ret, int20 and int21/00 methods are highly dependent on it, they're remnants of CP/M legacy (call/jmp 0 for program termination, call 5 for BDOS services, and CCP pushes 0 on stack). Once TSRs were introduced, DOS should know which process to terminate (guess why we do need int21/50 "set current PID/PSP").
Post 28 Feb 2013, 18:41
View user's profile Send private message Reply with quote
freecrac



Joined: 19 Oct 2011
Posts: 117
Location: Germany Hamburg
Good morning and many thanks for posting an answer.

I think our last instruction in the codesegment of a COM-executacle is also highly dependent on CS, no matter if it is a ret-instruction or an int 20h-instruction, because all together have to be in one 64 KB segment with the PSP.
So if we fiddiing with CS before, then we become a problem with both instructions.

But if we lost the address, then we can get back the address of the currrent PSP:
RBIL->inter61b.zip->INTERRUP.H
Code:
--------D-2162-------------------------------
INT 21 - DOS 3.0+ - GET CURRENT PSP ADDRESS
        AH = 62h
Return: BX = segment of PSP for current process
Notes:  this function does not use any of the DOS-internal stacks and may
          thus be called at any time, even during another INT 21h call
        the current PSP is not necessarily the caller's PSP
        identical to the undocumented AH=51h
    

Dirk
Post 01 Mar 2013, 08:12
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-2018, Tomasz Grysztar.

Powered by rwasa.