News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Area of a Cirlce problem

Started by infoMASM, March 14, 2014, 07:08:11 PM

Previous topic - Next topic

infoMASM

Hello everyone! I am having trouble with my code to try to find the area of a circle based on what the user inputs as a radius. I need to use the ReadFloat and WriteFloat procedures and use the FLDPI instruction to load pi onto the register stack. I do not believe I am getting the correct values with my code. If anyone can help I would really appreciate it!! Thank you!

INCLUDE Irvine32.inc
.data
myMessage BYTE "Lets calculate the area of a circle!!!!",0dh,0ah,0
prompt BYTE "Please enter a radius: ",0
result BYTE "Your area of the circle is: ",0
temp DWORD ?

.code
main PROC
call Clrscr

mov edx,OFFSET myMessage
call WriteString

mov edx, OFFSET prompt
call WriteString
call ReadFloat ;get radius put on stack

FLDPI ;put pi on stack
fmul st(0), st(0) ;radius squared
fmul st(0), st(1) ;multiplied by pi

mov edx, OFFSET result ;see them off
call WriteString
call WriteFloat ;write from stack
call Crlf

exit
main ENDP

END main

GoneFishing

After executing FLDPI instruction PI is loaded into st(0) register.
So what you're doing is calculating PI^2 

jj2007

You should use either Olly or the deb macro to understand what your code does:

include \masm32\MasmBasic\MasmBasic.inc              ; download
include \masm32\MasmBasic\IrvineMb\Irvine32Mb.inc      ; needed to build Irvine's (many but not all) 32-bit examples

.data
myMessage BYTE "Lets calculate the area of a circle!!!!",0dh,0ah,0
prompt      BYTE "Please enter a radius: ",0
result      BYTE "Your area of the circle is: ",0
temp      DWORD ?

  Init
  call Clrscr

  mov edx,OFFSET myMessage
  call WriteString

  mov edx, OFFSET prompt
  call WriteString
  call ReadFloat      ;get radius put on stack
  deb 4, "ReadFloat", ST(0), ST(1), ST(2)
  FLDPI                  ;put pi on stack
  deb 4, "fldpi", ST(0), ST(1), ST(2)
  fmul st(0), st(0)      ;radius squared
  deb 4, "fmul_1", ST(0), ST(1), ST(2)
  fmul st(0), st(1)      ;multiplied by pi
  deb 4, "fmul_2", ST(0), ST(1), ST(2)

  mov edx, OFFSET result      ;see them off
  call WriteString
  call WriteFloat      ;write from stack
  call Crlf
  Exit
end start


Output:

Lets calculate the area of a circle!!!!
Please enter a radius: 100

ReadFloat
ST(0)           100.000000000000000
ST(1)           0.0
ST(2)           0.0

fldpi
ST(0)           3.14159265358979324
ST(1)           100.000000000000000
ST(2)           0.0

fmul_1
ST(0)           9.86960440108935862
ST(1)           100.000000000000000
ST(2)           0.0

fmul_2
ST(0)           986.960440108935862
ST(1)           100.000000000000000
ST(2)           0.0

Your area of the circle is: +9.8696044E+002


So you see, as vertograd already posted, you are calculating 100*PI*PI - which is not intended...

GoneFishing

#3
Also you may use VKdebug macros ( assuming you have MASM32 pack installed on your system : run QEDITOR -> menu Help -> VKdebug Help ):
Quote
include  \masm32\include\masm32rt.inc
include   \masm32\include\debug.inc
includelib \masm32\lib\debug.lib

.data
       var REAL10 123.12345
.code
       start:
              call main
              inkey
              exit
main proc 
        FLD var
        FLDPI
        DumpFPU  ; VKdebug macro , displays the FPU content
        ret
main endp
end  start

jj2007

Quote from: vertograd on March 14, 2014, 08:19:31 PM
Also you may use VKdebug macros

They throw a bunch of errors, apparently there are name conflicts with Irvine32.inc

debug.inc(235) : error A2005: symbol redefinition : DumpMem
etc

GoneFishing

I didn't test them for compatibility with Irvine's macros ( that's why I didn't include IRVINE32.INC in my code sample ) which seem to have their own debugging routines ...





dedndave

you're original code is pretty close
i moved the first FMUL up one line
and added 2 FFREE's
i didn't test it, but it looks good on paper   :P
call ReadFloat ;get radius put on stack
fmul st(0), st(0) ;radius squared

FLDPI ;put pi on stack
fmul st(0), st(1) ;multiplied by pi

mov edx, OFFSET result ;see them off
call WriteString
call WriteFloat ;write from stack
call Crlf

ffree st(0)
ffree st(1)

raymond

infoMASM
If you intend to continue using fpu instructions directly, you should have at least a basic understanding of what you are doing. You may thus want to spend a few minutes to start reading the following:

http://www.ray.masmcode.com/fpu.html

If you don't care about the learning, you could always use the accompanying fpu library which has a detailed help file.
Whenever you assume something, you risk being wrong half the time.
https://masm32.com/masmcode/rayfil/index.html

jj2007

Raymond's tutorial is the best you can get, infoMasm - go for it. Chapter 1 will help you to understand why your instructions above were done in the "wrong" order. Especially Figure 1 is an excellent description of how the FPU works.

@Raymond: One para in Chapter 1 that might be slightly misleading:
QuoteIf, however, an attempt is made to load a value when all the compartments have a value in them, the barrel would still turn by one notch but the attempted loading would fail (just like trying to insert a bullet into a compartment which already contains one). And, in addition, whatever valid value would have been in that compartment now at the TOP is also destroyed, leaving unusable trash in that register at the TOP.

Actually, the value destroyed is the one in ST(7); the value that was in ST(0) is still available, now in ST(1).

QuoteRule #1: An FPU 80-bit register compartment MUST be free (empty) in order to load a value into it.

All values get loaded into ST(0), and normally, ST(0) is not free. But ST(7) must be free. There are two options to guarantee that ST(7) is free:
- fstp st (which discards, however, the current value of ST(0))
- ffree ST(7) (in the frequent case that you still need ST(0))

Simple test:

include \masm32\MasmBasic\MasmBasic.inc
  Init
  FpuFill      ; fill the FPU with 1001 ... 1008
  int 3        ; breakpoint for Olly
  fldpi        ; see what happens with ST(0)
  Exit
end start

infoMASM

Thank you guys for the help! I wasn't understanding that when I used the FLDPI that pi was being loaded onto st(0) and I was squaring pi. I got the code to work by calling FLDPI first then using the ReadFloat call to get the radius from the user. Thank you everyone!

raymond

Quotewhatever valid value would have been in that compartment now at the TOP is also destroyed

What WAS in st(7) is now at the top as described earlier in the paragraph. And that value now in st(0) is then trashed. The value destroyed WAS (and not is) the one in st(7). The value now in st(7) was the one in st(6) and is not destroyed.

I fully agree that the value that was in ST(0) is still available, now in ST(1).

This may just seem as semantics (and might be slightly misleading to some if not studied carefully) but must be clearly understood.
Whenever you assume something, you risk being wrong half the time.
https://masm32.com/masmcode/rayfil/index.html

dedndave

ReadFloat initializes the FPU
try the code i posted previously

jj2007

Quote from: raymond on March 15, 2014, 11:30:12 AMmight be slightly misleading to some if not studied carefully

Obviously I should study your tutorial more carefully ;-)

So where did I misinterpret Rule #1?

@Dave:
> ReadFloat initializes the FPU
That would be bad news, but it's wrong news ;): Put fldpi, int 3 before ReadFloat, then hit F8 in Olly and see 3.14... in ST(1)

dedndave

my mistake, Jochen
SetFpu is called, which sets the control word

jj2007

Quote from: dedndave on March 15, 2014, 01:29:07 PM
SetFpu is called, which sets the control word
ReadFloat does not modify the precision, though. And both ST6 & ST7 must be free.

This one doesn't trash ST6:
MovVal ST(0), Input$("Gimme a float please: \t",   "1000.001")

And this one trashes ST6 but produces a nice result:

  fldpi
  MovVal ST(0), Input$("Please enter a radius: \t", Str$("%If", 17.8412411615277111))
  fmul st(0), st(0)      ; radius squared
  fmul st(0), st(1)      ; multiplied by pi


I didn't know that fmul st(0), st(0) is possible. The fmul st(0), st(1) can be shortened as fmul without arguments.