News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

FPU question

Started by LordAdef, January 29, 2018, 02:47:58 PM

Previous topic - Next topic

LordAdef

Hi guys,
I wrote this procedure and tried to get away with integer division, using eax and ignoring edx. No, I´ll need FPU, which I am studying/reading... but clearly still incompetent.

I need to

->divide two values,
-> save the float value,  add and iterates the var
-> round it and move into ebx
-> float iteration continues as the loop progresses

QuoteLOCAL byteInc:DWORD   ; the interval of bytes to read. Affects img zoom
   ; LOCAL lineInc:DWORD    ; ==> USED IN THE DWORD VERSION
        ; FPU version:
   LOCAL lineInc:REAL4      ; the interval of lines to read. Affects img zoom
   LOCAL ySum:REAL4

Part of code with commented dword version, and fpu version.
Division of two values:
Quote; -----------------------------------------------------
         ; Fit to dimension: TRUE or FALSE
         ; -----------------------------------------------------
         cmp tFit, TRUE
         jnz fixedInc
         
         ; ------------------------------------------ Fit in img -----------------------------------------------------------
         ; -------- fit mapY minimap ----------
         
         ; ---------------  INTEGER version ------
         ; mov eax, map.height
         ; mov esi, MM_HEIGHT
         ; cdq
         ; div esi
         ; mov lineInc, eax   
         
         ; -------------- NEW ----------------------------
         fild map.height
         fdiv MM_HEIGHT
         fstp lineInc
         ; ---------------------------------------------------

fpu iteration, rounding and moving into ebx.:
Quote; ------ reached the end of the line, next line Ptr please --------------------------------
      
      ; -------- NEW ----------------------
      fld lineInc
      fadd ySum
      fstp ySum
      mov ebx, dword ptr [ySum]   
      ; --------------------------------------      
      
      ; ------ INTEGER version ----------
      ;add ebx,  lineInc      ; we need the Ptr for the next line
      ; ------------------------------------------
      mov cc, 0            ; resets line byte back to start of line      
      mov  xPos, 0         ; reset x coord
      add yPos, 1            ; inc y coord

These are the bits I need. The dword version was perfect but I need the FPU precision. But it´s not working..... Help would be mostly appreciated  :icon_redface: :icon_redface:

ps: I didn´t quote the whole procedure to save space. I´ll be glad to post it if asked to. Cheers

jj2007

Attention to the sizes:
      fld lineInc  ; ok if lineInc is REAL4 or REAL8
      fadd ySum  ; ok if REAL4
      fstp ySum  ; ok if REAL4
      mov ebx, dword ptr [ySum]  ; but it isn't REAL4, apparently :(

The assembler doesn't complain if you use float instructions for integer variables. But the result won't be correct 8)

Other than that, it's difficult to say where you could be wrong without complete code.

Btw deb is perfectly able to show you the content of the FPU.

HSE

Just replace "fstp ySum" with "fistp dSum" where dSum is dword, then "mov ebx, dword ptr[dSum]'
(you can make only "fistp ySum" and will work, but is error prone)

Later: you need to store the new ySum:

replace "fstp ySum" with
       " fst  ySum
         fistp dSum"
Equations in Assembly: SmplMath

LordAdef

The problem was here:
        fild map.height
         fdiv sHeight
         fstp lineInc

I changed to "fld" and it works. My problem is... map.height is a dword, shouldn´t "fild" be the right choice???
         


QuotepCreateMiniMap proc, tFit:DWORD
   ; ---------------------------------------------------------------------------------------------------------
   ; SetPixels in a pre created img, of a minuature map of the main map
   ; tFit == TRUE  makes the map fit into img dimension
   ; tFit == FALSE x /y scales are given by constants xInc and yInc   
   ; ---------------------------------------------------------------------------------------------------------

   LOCAL cc:DWORD         ; increment the line Ptr, searching the line for the target valeu
   LOCAL xPos:DWORD      ; x in miniMap img
   LOCAL yPos:DWORD      ; y in miniMap img
   LOCAL byteInc:DWORD   ; the interval of bytes to read. Affects img zoom

   LOCAL lineInc:REAL4      ; the interval of lines to read. Affects img zoom
   LOCAL sHeight:SDWORD   
   LOCAL ySum:REAL4
   LOCAL dSum:DWORD
      
   PUSH ebx
   PUSH edi
   PUSH esi
         ; ------ CREATE IMG FIRST -----------------------------------------------------------------
         ; First, it creates a compatible bmp
         ; I´m cheating: made beginPaint hdc handle (from CREATE) a global
         ; only to deal with the miniMap here
         ; --------------------------------------------------------------------------------------------------------
         invoke    CreateCompatibleBitmap, gHDC, MM_WIDTH, MM_HEIGHT
           mov     hMiniMapBmp, eax
          invoke    SelectObject, hMiniMapDC, hMiniMapBmp

   ; ----------------- Constants -------------------------------   
   byteVal       EQU    32               ; the target byte we want to setPixel. 32 is space (" ")
   xInc         EQU   8               ; Fixed value for scale x. The bigger, the smaller the Minimap x view is
   yInc      EQU   8               ; Fixed value for scale y. The bigger, the smaller the Minimap y view is   
   ; ------------------------------------------------------------------

   mov cc, 0
   mov xPos, 0
   mov yPos, 0
   mov sHeight, MM_HEIGHT         ; converts the const into a sdword

         ; -----------------------------------------------------
         ; Fit to dimension: TRUE or FALSE
         ; -----------------------------------------------------
         cmp tFit, TRUE
         jnz fixedInc
         ; ------------------------------------------ Fit in img -----------------------------------------------------------
         ; -------- fit mapY minimap ----------
         fld map.height
         fdiv sHeight
         fstp lineInc
         
         ; --------- fit mapX minimap ---------
         mov eax, cWIDTH
         mov esi, MM_WIDTH
         cdq
         div esi
         mov byteInc, eax
         jmp drawMap
         
         fixedInc:
         ; ----------------------------------------------------------------------
         ; It´s fixed.
         ; So, use the values set in xInc and yInc above
         ; ----------------------------------------------------------------------
         mov byteInc,  xInc         ; The bigger, the smaller the Minimap x view is
         mov lineInc, yInc   
   
   drawMap:   
         
   fldz            ; st(0) == 0
   xor ebx, ebx      
   newLinePtr:
      mov edi, [map.mapLinePtr+ ebx * 4]      ; Get line Ptr (map.mapLinePtr is an array of Ptr)
      
   fillLine:   
      cmp byte Ptr [edi], byteVal             ; 32 == space, it´s what we want
      jnz nextPix                           ; it´s not, skip SetPixel
      
      invoke SetPixel, hMiniMapDC, xPos, yPos, 0FFFF0Bh   
         
   nextPix:
      ; Byte is NOT 32, so we don´t setpixel and just keep going
      mov eax, byteInc
      add cc, eax            ; next byte within line
      add edi, eax            ; next byte Ptr      
      add xPos, 1            ; next x coord
      
      cmp cc, cWIDTH      ;  cWIDTH is the number of bytes/line (currently 159)
      jbe fillLine            ; it´s within line
      
      ; ------ reached the end of the line, next line Ptr please --------------------------------
;       fld ySum
;       fadd lineInc
;       fst ySum            ; sum in real4
;       fistp dSum            ; sum in dword
      
      fadd lineInc
      fist dSum
      mov ebx, dword ptr [dSum]   
      
      ;; printf ("ebx: %d \n", ebx)
      mov cc, 0            ; resets line byte back to start of line      
      mov  xPos, 0         ; reset x coord
      add yPos, 1            ; inc y coord
      
      cmp ebx, map.height    ; map.height is the num of lines of map (after is changed, according to map.style)
      jb newLinePtr   
      
   done:
      POP esi
      POP edi
      POP ebx
      ret
pCreateMiniMap endp

LordAdef

Quote from: HSE on January 29, 2018, 10:27:00 PM
Just replace "fstp ySum" with "fistp dSum" where dSum is dword, then "mov ebx, dword ptr[dSum]'
(you can make only "fistp ySum" and will work, but is error prone)

Later: you need to store the new ySum:

replace "fstp ySum" with
       " fst  ySum
         fistp dSum"


Woking version in action. Press 1, and then when you press 4 you move to the next level, and the new miniMap is redrawn (There`re 3 maps)
Thanks HSE. It works! In fact I don´t even need to save ySum, I can iterate straight in st(0)

jj2007

Works fine but I can't see any effect of pressing 4 :(

LordAdef

the 4, not the side pad four, right?

Just skip the current level, and take you to the start of the next level, with the miniMap being redrawn with the new map.

HSE

Before the proc end, "fstp st" will empty FPU       :t
Equations in Assembly: SmplMath

LordAdef

Quote from: HSE on January 31, 2018, 01:59:41 AM
Before the proc end, "fstp st" will empty FPU       :t

Sure, is it a good practice to empty FPU after using it?

concerning my question above, map.height is a dword, but the code only worked with  "fld map.height". Wouldn´t "fild" be the right one??

jj2007

Quote from: LordAdef on January 31, 2018, 04:28:27 AMSure, is it a good practice to empty FPU after using it?
Yes, otherwise you run into trouble when you need it next time, especially in a loop.


Quoteconcerning my question above, map.height is a dword, but the code only worked with  "fld map.height". Wouldn´t "fild" be the right one??

Yes, probably, but check all your types. As mentioned above, unfortunately the assemblers we use do not check the type for FPU instructions. Thus, you can write fdiv someinteger (instead of fidiv), and it will erroneously treat someinteger as a REAL4.

LordAdef

QuoteYes, probably, but check all your types. As mentioned above, unfortunately the assemblers we use do not check the type for FPU instructions. Thus, you can write fdiv someinteger (instead of fidiv), and it will erroneously treat someinteger as a REAL4.

Yep, but that´s the problem... map.height is definitely a "dword", but the code will only work with fld, not with fild

here:
         ; -------- fit mapY minimap ----------
         fld map.height    <=== this should be fild right?? (map.height == dword)
         fdiv sHeight
         fstp lineInc

jj2007

So, when you insert
  deb 4, "fpu in", map.height, sHeight
         ; -------- fit mapY minimap ----------
         fld map.height    <=== this should be fild right?? (map.height == dword)
         fdiv sHeight
         fstp lineInc
  deb 4, "fpu out", lineInc

... does it look right? In particular since LOCAL sHeight:SDWORD?

daydreamer

#12
Quote from: LordAdef on January 31, 2018, 05:01:10 AM
QuoteYes, probably, but check all your types. As mentioned above, unfortunately the assemblers we use do not check the type for FPU instructions. Thus, you can write fdiv someinteger (instead of fidiv), and it will erroneously treat someinteger as a REAL4.

Yep, but that´s the problem... map.height is definitely a "dword", but the code will only work with fld, not with fild

here:
         ; -------- fit mapY minimap ----------
         fld map.height    <=== this should be fild right?? (map.height == dword)
         fdiv sHeight
         fstp lineInc

Use int3 and use debugger to singlestep your fpu code and there you can watch what real4 value endsup in your fpu, its also good singlestep any fpu code to learn how fpu regs behave
I think it 23bits number, 1bit sign and rest of bits is info if number is very big or very small, like scientific number format

Or find right print to invoke for real4 printout
my none asm creations
https://masm32.com/board/index.php?topic=6937.msg74303#msg74303
I am an Invoker
"An Invoker is a mage who specializes in the manipulation of raw and elemental energies."
Like SIMD coding

LordAdef

Hey DDreamer,

Thanks for the tip, I´ll try the debugger. Unfortunately I´m working on a laptop that doesn´t have Olly. 

HSE

lea eax,map
fild [eax].MapStructure.height

Or
Assume eax: ptr MapStructure
fild [eax].height
Equations in Assembly: SmplMath