6

I've been tasked with writing a simple application in mixed C/ASM that has to use math coprocessor.

There's the function cylinder(float x, float y, float z) that returns 1 if the given point is within the cylinder (the cylinder has a base at x=0,y=0, radius = 5 and height = 10), and 0 if it isn't.

So, looks simple. Check whether z is within <0,10>, and then check if x^2 + y^2 < 25.

But my knowledge about x87 is nil.

There's everything I've written.

_cylinder PROC

push ebp
mov ebp, esp
sub esp,8 ; I can't use .data in the application, so I reserve some space on the stack for numbers 10 and 25
mov [esp],10
mov [esp+4],25

finit
fldz
fld [ebp+8]

    ;here i get stuck 

add esp, 8
pop ebp
_cylinder ENDP

So I got stuck. So, I try to find what instructions could I use in the application. And there I get stuck, because every tutorial/instruction list i find on the net is written so badly I can barely understand anything.

The question is, what happens when I pop something from the math coprocessor? Where can I find the popped value? How does it converts from 80-bit value to 32 bit one (if it does, of course) Another question is, how does the FCOM (FCOMP for pop variant) works? It compares what to what ( st0 to st1 or st1 to st0?), and where can I see whether the value is smaller/equal/bigger?

Thanks for any help!

Kara
  • 6,115
  • 16
  • 50
  • 57
user905747
  • 613
  • 1
  • 9
  • 18
  • 5
    Before you get too deep, please consider using SSE2 math instead of x87. It's much easier to work with (you get to use registers instead of a stack), has more functions available, and is generally faster. –  Aug 25 '11 at 18:52
  • What duskwuff said. `x87` is effectively being deprecated, and there is very little reason for new software to be targeting it. – Stephen Canon Aug 25 '11 at 19:14
  • @Stephen - "deprecated" by some OS, not CPU, vendors (but even there, still supported). Reasons for use: 80-bit extended precision and transcendental math functions, for example. – PhiS Aug 25 '11 at 20:19
  • 1
    @PhiS: x87 will only get slower by comparison to SSE and AVX. 80-bit precision is occasionally useful in the hands of a programmer with a deep understanding of floating-point, but often causes more harm then good in the form of unpredictable behavior in the face of compiler optimizations. The transcendental math instructions are slower than software implementations based on SSE or AVX. x87 was incredibly useful in its time, but its long past time to move on. – Stephen Canon Aug 25 '11 at 20:22
  • 2
    I don't understand the question. You have to write the program in "C/ASM"? So why don't you just write the code in C? – jalf Aug 25 '11 at 21:15
  • 1
    http://www.ray.masmcode.com/tutorial/index.html is a nice intro to x87. It has tons of detail, but puts the pieces together in a way that the insn ref manual doesn't. See http://stackoverflow.com/tags/x86/info for more links. – Peter Cordes Nov 28 '15 at 00:14
  • I love it when people don't answer the question and assume they know better than the asker. – mid Oct 09 '20 at 09:05

1 Answers1

5

Floating point comparisons are kind of a pain. You can do the comparison on the FPU, but before you can do anything based on that, you have to transfer the floating point status word to the CPU, test for the flags you care about, and then react based on that.

Just for example, your initial comparison that z>=0.0 would look something like this:

fldz
fcomp z
fnstsw ax
test ah, 041h; I *think* I've got the right flags there...
jp good
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • 4
    Hmm, shouldn't it be `test ah, ...`? [Reference](http://webster.cs.ucr.edu/AoA/Windows/HTML/RealArithmetic.html#1000117). Personally I find using [`FCOMI`](http://stackoverflow.com/questions/7057501/x86-assembler-floating-point-compare/7057771#7057771) easier than messing about with bitmasks for the status word, it's only available on P6+ though. – user786653 Aug 25 '11 at 19:38
  • 3
    @user786653: oops -- yes, it should be ah, not ax. My apologies. Yes, FCOMI is nice, but by the time the P6 came along, I wasn't writing nearly as much assembly code. If I was writing for newer processors, I'd probably use SSE instead. – Jerry Coffin Aug 25 '11 at 21:11
  • 2
    I agree, if I *had* to write it in x86 assembler. Seems like the OP is set on using x87 though, so I figured I'd through it out there. I also seem to hazily recall `sahf` + unsigned tests (as with `fcomi`) working. – user786653 Aug 25 '11 at 21:22
  • 1
    Can you get away with FNSTSW AX there, or did you mean to use FSTSW AX? – Brian Knoblauch Aug 26 '11 at 12:42
  • 2
    @Brian: I *believe* in this case you can use FNSTSW. – Jerry Coffin Aug 26 '11 at 14:29