Jump to content
  • 0

Floating Point Library example?


Dacobi
 Share

Question

13 answers to this question

Recommended Posts

  • 0

What are you trying to accomplish? Isn’t it possible with fixed point math perhaps?

In any case, prog8 for instance  uses those kernal floating point routines for its float calculations.  If you’re not familiar with assembly programming it will be a large hurdle to grasp how it works. But essentially it revolves around loading FAC1 and possibly FAC2 with aa value, calling one of the float math functions, and converting FAC1 (which will usually contain the result) back to a number or string somewhere. FAC1 and FAC2 are internal floating point variables stored somewhere in ram.  It’s quite tedious to write this code by hand especially for complex calculations...

i can add a tiny example that adds 2 numbers later if you really want to pursue this

 

Edited by desertfish
Link to comment
Share on other sites

  • 0
On 1/2/2022 at 9:30 PM, desertfish said:

What are you trying to accomplish? Isn’t it possible with fixed point math perhaps?

i can add a tiny example that adds 2 numbers later if you really want to pursue this

I would like to get cc65-floatlib to work on x16.

I'd very much like an example.

Currently I've tried to piece together an example to FMUL a float and print it:

.org $080D
.segment "STARTUP"
.segment "INIT"
.segment "ONCE"
.segment "CODE"

 jmp start

;Kernal
GETIN             = $FFE4

;Float
FAC1              = $61
FACEXP1       = $61
FACHO1         = $62 ; -$65        
FACSGN1       = $66            
SGNFLG1       = $67            
BIT1                = $68            

FMULT            = $FE27 ;FAC *= mem(.Y:.A)
FOUT               = $FE7B  ;Convert FAC to ASCIIZ string at fbuffr
GIVAYF2         = $FE03 ;FAC = (s16).A:.Y

CHAR_Q          = $51

mstring:           .res 32

; global data

start:
   lda #04
   sta $9f61 ; ROM BANK 4

;load floating point number into FAC1
    LDA <L1
    LDY >L1
    JSR GIVAYF2

    JMP L2
L1:
    .byte "$87 $48 $00 $00 $00",0
L2:
   
   LDY <L1
   LDA >L1

   jsr FMULT

   LDA <mstring
   LDY >mstring
   ;jsr FOUT

    LDY #$00
L3:
    LDA mstring,Y
    CMP #0
    BEQ L4
    JSR $FFD2
    INY
    JMP L3
L4:
   ;jsr $FFD2
@main_loop:
   wai
   jsr GETIN
   cmp #CHAR_Q
   bne @main_loop
   rts

But whenever I uncomment FOUT the program crashes

 

Link to comment
Share on other sites

  • 0

You'll have to make sure you're using the correct addresses of those kernal routines for the given emulator/rom revision you are using. They have changed from r38 to r39. It seems that you are using the r39 addresses on a r38 target?

The documentation in the master branch of the github repo shows the r39 state of affairs.

Here is the r38 one https://github.com/commanderx16/x16-rom/blob/r38/fplib/fplib.inc

Link to comment
Share on other sites

  • 0
On 1/2/2022 at 10:53 PM, desertfish said:

You'll have to make sure you're using the correct addresses of those kernal routines for the given emulator/rom revision you are using. They have changed from r38 to r39. It seems that you are using the r39 addresses on a r38 target?

The documentation in the master branch of the github repo shows the r39 state of affairs.

Here is the r38 one https://github.com/commanderx16/x16-rom/blob/r38/fplib/fplib.inc

As far as I can tell the only address that was different was FOUT.

After changing it, my program no longer crashes, but still it doesn't print any characters.

The documentation says: fout = $fe81 ; Convert FAC to ASCIIZ string at fbuffr
What is "fbuffr"?

I know it's a big task. My expertise is in C/C++

But I hope that by gaining a basic understanding of the Float Lib in asm, I might get floatlib to work with x16. Currently I can compile floatlib code, but if I try to actually do something with floats, the program crashes. 

Link to comment
Share on other sites

  • 0

for FOUT, 'fbuffr' is probably the name of the internal basic string buffer it uses.  Don't try to access it directly, instead, use the fact that FOUT returns the address of it in the A and Y registers. Store that somewhere and read the characters using that pointer.

Link to comment
Share on other sites

  • 0
On 1/2/2022 at 11:27 PM, desertfish said:

for FOUT, 'fbuffr' is probably the name of the internal basic string buffer it uses.  Don't try to access it directly, instead, use the fact that FOUT returns the address of it in the A and Y registers. Store that somewhere and read the characters using that pointer.

That's were my assembly knowledge falls short.

My current code is:

    LDY #$00
L3:
    LDA mstring,Y
    CMP #0
    BEQ L4
    JSR $FFD2
    INY
    JMP L3
L4:

How would I change that to an address in A.:.Y ?

Link to comment
Share on other sites

  • 0

Here's a piece of code that adds two floating point numbers 1.11 and 1.22 and prints the result 2.33.   Note that $7e/$7f are just 2 zero page locations free for user programs.

            lda  #<float5_111
            ldy  #>float5_111
            jsr  floats.MOVFM
            lda  #<float5_122
            ldy  #>float5_122
            jsr  floats.FADD
            jsr  floats.FOUT
            sta  $7e
            sty  $7f
            ldy  #0
_loop
            lda  ($7e),y
            beq  _done
            jsr  c64.CHROUT
            iny
            bne  _loop
_done
            rts

float5_111    .byte  $81, $0e, $14, $7a, $e1  ; float 1.11
float5_122    .byte  $81, $1c, $28, $f5, $c2  ; float 1.22

 

But this piece of your code above doesn't look correct too:

L1:
    .byte "$87 $48 $00 $00 $00",0

 

Edited by desertfish
Link to comment
Share on other sites

  • 0
On 1/2/2022 at 3:37 PM, Dacobi said:

That's were my assembly knowledge falls short.

My current code is:

    LDY #$00
L3:
    LDA mstring,Y
    CMP #0
    BEQ L4
    JSR $FFD2
    INY
    JMP L3
L4:

How would I change that to an address in A.:.Y ?

The easiest way would be to store A & Y in a zero page pointer that you can use to index indirect.

  ZPPTR = $42 ; whatever address in ZP
  STY ZPPTR+0
  STA ZPPTR+1
  LDY #$00
L3:
  LDA (ZPPTR),Y
  BEQ L4 ; You don't have to compare with 0 first, load will set zero flag for you
  ; the rest goes here

Edit: assuming I'm understanding the question and that A has the high byte and Y has the low byte.

Edited by Scott Robison
Link to comment
Share on other sites

  • 0
On 1/2/2022 at 11:42 PM, desertfish said:

Here's a piece of code that adds two floating point numbers 1.11 and 1.22 and prints the result 2.33.   Note that $7e/$7f are just 2 zero page locations free for user programs.

...

But this piece of your code above doesn't look correct too:

L1:
    .byte "$87 $48 $00 $00 $00",0

 

Thanks 🙂 got it working. But it seems you are using another assembler? I could only get it to compile by adding : after definitions. (ie float5_111:)

Also the programming reference said to select ROM BANK 4 but that doesn't seem to be necessary?

The L1: code was something I found online. Still haven't figured out how to format a float.

Link to comment
Share on other sites

  • 0
On 1/2/2022 at 9:30 PM, desertfish said:

 It’s quite tedious to write this code by hand especially for complex calculations...

I'm trying to port some C code that uses a lot of floating point math, so when I came over the cc65 floatlib I thought my troubles were over.

But looking at https://github.com/mrdudz/cc65-floatlib/blob/master/float.inc there seems to be some difference between which calls are used.

I would just really like to have the code running before trying to do any assembler optimisations.

Link to comment
Share on other sites

  • 0
On 1/2/2022 at 6:00 PM, Dacobi said:

... But it seems you are using another assembler? I could only get it to compile by adding : after definitions. (ie float5_111:)

Old school (1970s era) l assemblers often required a location label to end with a ":" to distinguish it from a value define by an equate ... it seems like most newer assemblers make the ":" optional and work out whether it's an equate or a location from the context.

However, standardization of assembler syntax is more about what people are used to than having an explicit standard to follow, so YMMV.

I always include the ":" ... that's more from habit than from any view on whether it is "best practice".

Edited by BruceMcF
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

Please review our Terms of Use