Author Topic: Min max with math coprocessor  (Read 18737 times)

Offline akus85

  • Jr. Member
  • *
  • Posts: 5
Min max with math coprocessor
« on: June 01, 2010, 11:02:24 AM »
Hi,
i work with the coprocessor and i have scan an array and store in ST1 the lowest number and in ST2 the biggest number.
My idea is first store in ST1 and ST2 the first element of array and the scan and compare with ST1 and ST2 but everytime that i put in ST0 the element to compare ST1 and ST2 become ST3 and ST3 and so on..
How can i leave the value in ST1 and ST2 ?  ???

This is my code:
Code: [Select]
#include <stdio.h>
#define N 3

int main(){

  double X[N]={1,2,0};
  double Y[N]={3,2,0};

  _min_rect(X,Y,N);
}


Code: [Select]
%include "asm_io.inc"

%define x [ebp+8]
%define y [ebp+12]
%define n [ebp+16]

segment .text
global _min_rect
_min_rect:
enter 0,0

mov esi,x
mov ecx,n
push esi
push ecx
call _searchx
add esp,12

leave
ret


_searchx:
push ebp
mov ebp,esp

        ; Load in ST1 and ST2 the first element of x array
fld qword [esi] ; ST1 = [esi]
fld qword [esi] ; ST0 = [esi]
fxch ST2         ; ST2 = ST0
ffree ST0
add esi,8
dec ecx
dump_math 2

cycle1:
cmp ecx,0
jl _out_searchx ; end scan of x array
fld qword [esi] ; ST0 = [esi]
dump_math 1



fcomi ST1       ; compare ST0 with ST1
jl _exchange_min       ; ST0 < ST1
fcomi ST2
jg _exchange_max ; ST0 > ST2
ffree ST0

dec ecx
jmp cycle1




_exchange_min:
;; fxch ST1 ; ST1 = ST0
;; ffree ST0
fstp ST1
dec ecx
jmp cycle1

_exchange_max:
;; fxch ST2 ; ST2 = ST0
;; ffree ST0
fstp ST2
dec ecx
jmp cycle1


_out_searchx:
pop ebp
ret


Thanks in advance!  ;)

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Min max with math coprocessor
« Reply #1 on: June 02, 2010, 01:41:19 AM »
I'm not too good with FPU... I'm kinda feeling my way along. Last time I tried to do a floating point compare, "fcomi" was an illegal instruction on that machine, and I had to do it the old fashioned way... "fcomi" is much nicer!

Your immediate problem seems to be that "ffree" marks the register empty, but doesn't pop the stack. I dealt with this by making a "local variable" (sub esp, 4 - if you do this, do "mov esp, ebp" at the end of your function!), and "fstp dword [ebp -4]" to get rid of st0. There's probably a better way.

You neglect to bump esi in the "loop", so you keep loading the second float. Easily fixed.

Then I found that "_exchange_min" was never being executed (I put print_char with 'i' in "min" and 'a' in "max" for debugging purposes - inspired by how much "dump_math" helps with debugging!) . You've got "jl", which should be right for signed comparisons, and floats are, by their nature, signed. But I think (and experiment seems to confirm it) that "fcomi" sets the flags as if an unsigned comparison had happened. I changed your code to "jb" and "ja", and it seems to work better. (actually, changing just jl to jb worked, but I changed jg to ja too... for consistency...).

I fiddled with a few other things - bumped "N" in the caller up to 7 so I'd have a few more values to play with... put another "dump_math" right at the exit from your function... I've got it so that, at function exit "min" is in st0, and "max" is in st1. I don't know where you want to go from there.

Anyway... try popping st0 into a "dummy" variable with "fstp dword [dummy]" instead of "ffree", and see if that helps...

Best,
Frank