hello (again),

first of all, i'm writing my main program in c++.
i figured out how to use external functions that i wrote with MASM32, all fine.

my program works like..(pseudo)

DrawScene()
{

glBegin(GL_QUADS);

for(numberofquads=0; numberofquads<max; numberofquads++)
{



get x, y, z (float) coordinates to calculate normal

l = asm_squad3(x,y,z);
if(l==0) l=1;
v.x /= l;
v.y /= l;
v.z /= l;

glNormal3f(v.x, v.y, v.z);

draw Vertices

}
glEnd();
}


the assembler file:

.486
;.387
.model flat, stdcall
option casemap:none

char TYPEDEF SBYTE
long TYPEDEF DWORD
float TYPEDEF REAL4
double TYPEDEF REAL8

asm_squad3 proto :float, :float, :float ; calcs sqrt(x?+y?+z?)

start:

asm_squad3 PROC X:float, Y:float, Z:float

finit
fld X
fmul st, st
fld Y
fmul st, st
fadd st, st(1)
fld Z
fmul st, st
fadd st, st(1)
fsqrt
fwait

ret

asm_squad3 ENDP

END start



i did the olly debug and the result was correct...

when i actually USE the asm-function, it messes up the drawing with trash vertices coming from or going to upper left corner.

what could that be? is it a no-no to to such stuff within glBegin() - glEnd()? if so, how cuold one do everything in asm? that can't be the point, can it?

i have no idea

please help me
Posted on 2002-03-11 12:54:17 by 08/15
Dunno if this is the problem, but why do you call finit in your asm code?
And, probably more important, how have you set up the function
prototype in your c file? If you haven't already, either add __stdcall ,
or change the asm file to "proc c".
Posted on 2002-03-11 13:22:12 by f0dder
thx fodder, here's the c declaration:

extern "C" {

float __stdcall asm_squad3(float, float, float);

}

it is accessible, but when called in the drawing process it messes things up

? weird

the FINIT i thought would be the safe way
Posted on 2002-03-11 13:30:47 by 08/15
maybe the c-code description lacks some info

basically, don't flame me for that, i call the asm-function from another function called Norm(), which is called from DrawObject() which is invoked by DrawGLscene() which is called from winmain.
phew.

as one can easily see, it's a bit nested. maybe a near/far and so on problem? this just came into my mind...
Posted on 2002-03-11 13:40:28 by 08/15
the extern looks fairly reasonable to me.
finit should only be necessary at program startup, and the runtime
libraries will probably handle this... I dunno if this would be the
problem though.

I do notice, however, that you exit your proc with three float values
on the stack... I don't think this is too good? =)
Posted on 2002-03-11 13:43:28 by f0dder
could be... i did recognize it while debugging and had a bad feeling - no joke. MASM reference says the called procedure has to clear the stack:rolleyes:
sad but true, all diagrams in the reference are deleted or blackened out

could you tell me how to clear the stack?
Posted on 2002-03-11 13:47:43 by 08/15
yeee-harrrrr
:alright: :grin: :alright: :grin: :alright:

thank you for pointing me to the right direction
somewhere in the INTEL reference (haha!) i found useful info and more detailed descriptions...

now i'm a good boy, cleaning the FPU stack and VOILA!
Posted on 2002-03-11 16:14:44 by 08/15
since nothing has happened for some time, i'll complete this thread with a woriking version of my sqrt(x?+y?+z?)...
tips are welcome ;)

i'm not sure what is faster actually, giving intermediates to the function or memory addresses?



.486
.model flat, stdcall
option casemap:none

char TYPEDEF SBYTE
long TYPEDEF DWORD
float TYPEDEF REAL4
double TYPEDEF REAL8

ptrfloat TYPEDEF NEAR PTR REAL4


asm_squad3ptr proto :ptrfloat, :ptrfloat, :ptrfloat ; calcs sqrt(x?+y?+z?)



.data

PUBLIC global
PUBLIC asm_result

global long 0
asm_result float 0



.code

start:

asm_squad3ptr PROC uses esi X:ptrfloat, Y:ptrfloat, Z:ptrfloat

mov esi, X
fld DWORD PTR DS:
fmul st, st

mov esi, Y
fld DWORD PTR DS:
fmul st, st

faddp st(1), st
mov esi, Z
fld DWORD PTR DS:
fmul st, st

faddp st(1), st


fsqrt

fwait
ret

asm_squad3ptr ENDP


END start


bye



here's the intermediate function...

asm_squad3 PROC X:float, Y:float, Z:float
fld X
fmul st, st

fld Y
fmul st, st

faddp st(1), st
fld Z
fmul st, st

faddp st(1), st


fsqrt


fwait
ret

asm_squad3 ENDP


which is better/faster?
Posted on 2002-03-13 07:06:37 by 08/15
Whould it be better to make a struct in you C++ code like



struct V3D
{
float x;
float y;
float z;
};

void __stdcall V3D_Length(const V3D& pV);


V3D& is a pointer to a vector. But is better this way than V3D* so you dint accidentaly give a NULL pointer.

The assembly pointer could be something like:


;
; This will calculate sqrt(x?+y?+z?)
;
; In:
; pV Pointer to V3D structure
; Out:
; st(0), length of vector wich is sqrt(x?+y?+z?)
;
V3D_Length proc, pV:DWORD
mov eax, pV
fld [eax] ;st(0) = x
fmul st(0), st(0) ;st(0) = xx
fld [eax + 4] ;st(0) = y, st(1) = xx
fmul st(0), st(0) ;st(0) = yy, st(1) = xx
fld [eax + 8] ;st(0) = z, st(1) = yy, st(2) = xx
fmul st(0), st(0) ;st(0) = zz, st(1) = yy, st(2) = xx
fxch st(2) ;st(0) = xx, st(1) = yy, st(2) = zz
faddp st(1), st ;st(0) = xx+yy, st(1) = zz
faddp st(1), st ;st(0) = xx+yy+zz
fsqrt ;st(0) = sqrt(xx+yy+zz)
ret
V3D_Length endp


And you can call it this way:



float l = V3D_Length(v);


Since you need the vector length function for vector normalization, the fastest one will be an aproximation of the inverse square root. Unfortunately I dont have the code at hand.
Posted on 2002-03-13 12:59:00 by dxantos
thank you very much dxantos!

in fact, i am using vertice-structures already, but i declared it as a class.

does that affect the data-structure in memory?
correct me if i'm wrong, i think structures are the same as classes with all public members, aren't they?

well, i'm not sure though...and how about object-arrays? how are they organized?

your solution is really cool because i understand the addressing thing much better now


:alright:
Posted on 2002-03-13 14:48:29 by 08/15
For an assembly point of view structures and classes are the same the assembler does not care about public, private, etc.

As long as the class does not have virtual functions and is not inherited, it should be pretty easy to use with assembly functions.

In C++ the only difference between struct and class is that

class - default to members being private.
struct - default to members being public

so



struct V3D
{
float _x;
float _y;
float _z;
};


and


class V3D
{
public:
float _x;
float _y;
float _z;
};


Are basically the same.

In this case the size of the strucure (since its not inherited and have no virtual functions) is 12 bytes (4 for each float).

This will also have the same size (12 bytes)



struct V3D
{
float _x;
float _y;
float _z;
V3D();
V3D(const V3D& v_);
V3D& operator += (const V3D& v_);
};


Since none of the functions is virtual.

But:



struct V3D
{
float _x;
float _y;
float _z;
V3D();
V3D(const V3D& v_);
V3D& operator += (const V3D& v_);
virtual ~V3D();
};


Will need to add 4 bytes (or 8 bytes in case of a 64 bit processor) for the virtual function pointer. So the size will be 16 or 20 bytes. depending for what processor is compiled.

Now in the case of an array

V3D v[2];

The order in memory will be

XYZXYZ

or

XYZ~XYZ~

In case it has a virtual destructor (which IMHO is not needed here). (The ~ simbolizes here the Pointer to the virtual function pointer)

Hope this help.

PS:
Forgot that when you have a static member the size of the structure is less. Thats because the member is not in the structure but in a global variable.
Posted on 2002-03-14 08:53:31 by dxantos