Ok, I've been trying to do learn OpenGL programming and I've been bouncing in to this problem, after a call to gluPerspective my stack gets "off" by 10h (4 dwords). Below is the call (fasm syntax), and the comments contains the assembled code (opcode).
	push	100.0f	; 68 0000C842 <-- push 42C80000 :confused: ?????

push 0.1f ; 68 CDCCCC3D <-- push 3CCCCCCD :confused: ?????
push dword [_aspd] ;FF35 18204000 <-- push [402018]
push 45.0f ; 68 00003442 <-- push 42340000 :confused: ?????
call [gluPerspective]

Can some one please explain this to me? I saw some other OGL example and it looks like this (tasm syntax I belive):


_45d0 equ 40468000h ;45.0
_45d1 equ 0
_01d0 equ 1069128089
_01d1 equ -1717986918 ;0.1
_100d0 equ 1079574528
_100d1 equ 0 ;100.0
....
push _100d0
push _100d1
push _01d0
push _01d1
push dword ptr [_aspd+4]
push dword ptr [_aspd]
push _45d0
push _45d1
call gluPerspective

This doesn't make any sence to me, I can't under stand how 40468000 00000000 can tanslate into 45.0.
Posted on 2003-03-16 05:00:42 by scientica
Hi

Oly real4 data type has the same lengt as a dword
real8 have 8 bytes == 2 dwords and real10 have 10bytes ...

Study the IEEE floating point reprezenation of numbers in computers and you will (after a while) understand how 40468000 00000000 can indeed translate into 45.0 for the FPU co-processor.

Basically there is a Mantissa and an Exponent bit fields. The Mantissa keeps track of as much digits as possible for the real number while the Exponent stores a positive or negative power of 2 ...ah and the sign bit

Numbers like 45.0 (and others) can be represented either as a real4,real8 or real10 and usually the FPU will auto recognise the format used when you load them from memory operands (like in fld or fst ) , but that dosent work when you deal with them directly via CPU (like in push,pop,mov instructions)... then you will need to know the length of the number you want to deal with.

Why not use only real4? Well because numbers like 1.3333333333333333333333 or the Euler's constant or PI will nedd more precision to be represented and it is better (if precision is needed) to use real8 or real10 constants


Usually programmers use to store initial values of those numbers / constants used in 3D applications as real4==dword ... because it uses up less space in .data section ...
Posted on 2003-03-16 05:18:35 by BogdanOntanu
Oh and about the error...

it is obviousely that in the working example the programmer used real8 as we can see from the d0=dword zero and d1=dword one suffix he appended to those numbers ...

and indded you should use

push real8 ptr [...]

if OpenGL expects a real8 number as a parameter
Posted on 2003-03-16 05:21:58 by BogdanOntanu
Ok, thanks :)
I made a search on google and found this: http://www.psc.edu/general/software/packages/ieee/ieee.html
I'll read it a few time and I hope fully I will be able to fix the app, but that'l be later since my grand parents just arrived.
Posted on 2003-03-16 05:41:10 by scientica

Ok, now I've made some macros to simplify things for me. I haven't seen if they realy work (only that the stack is ok after call), it compiles but I got lot's of calls/pushes to replace and fix before I see my OGL-window, anyway here they are:
macro glPush GLfloatVar {

push dword [GLfloatVar+4]
push dword [GLfloatVar]
}
macro glCall proc,[arg] {
reverse
glPush arg
common
call [proc]
}

Here's an example of how they're used.
Note, you must pass the address to a real8 (dq, IEEE double precision float) not actual floats (this version of the macros doesn't suport it).


;data
; GLdouble equ dq
_100_0f GLdouble 100.0f
_45_0f GLdouble 45.0f
_0_1f GLdouble 0.1f
...
;bss
_aspd rq 1
....
;code
....
glCall gluPerspective,_45_0f,_aspd,_0_1f,_100_0f
is equal to:
push dword [_100_0f+4]
push dword [_100_0f] ; push 100.0f
push dword [_0_1f+4]
push dword [_0_1f] ; push 0.1f
push dword [_aspd+4]
push dword [_aspd] ; push float
push dword [_45_0f+4]
push dword [_45_0f] ; push 45.0f
call [gluPerspective]



Posted on 2003-03-16 10:04:30 by scientica
You can use doubleconst macro that I've posted here: http://www.asmcommunity.net/board/index.php?topic=11338.msg85763 and you will avoid putting the garbage in the data section.
Posted on 2003-03-17 02:47:17 by Tomasz Grysztar
Thanks Privalov, you are the greatest! :) :) :) (I knew it could be done smother, FASM is fantastic, sic!)

Ok, this is the modified version of glPush, which supports pushing of floats directly.
macro glPush2 GLfloatVar {

local name
name = GLfloatVar
virtual at 0
dq GLfloatVar
load name.l dword from 0
load name.h dword from 4
end virtual
push dword name.h
push dword name.l
}
macro glCall2 proc,[arg] {
reverse
glPush2 arg
common
call [proc]
}


Btw, assembly master (Privalov), is there a way to make the macro differ between floats and adresses?
Let's say: glInvoke function, 45.0f, floatvar
should use glPush2 for 45.0f and glPush for floatvar.
Posted on 2003-03-17 10:10:47 by scientica
Originally posted by scientica
Btw, assembly master (Privalov), is there a way to make the macro differ between floats and adresses?
Let's say: glInvoke function, 45.0f, floatvar
should use glPush2 for 45.0f and glPush for floatvar.


Sure:


if arg eqtype 1.0
glPush2 arg
else
glPush arg
end if


PS: you declare "name" as local, but not "name.l" and "name.h", you can write "name#.l" and "name#.h" instead, but you don't need to declare it as local really - constants can be redefined (and that's why it's working anyway).

PPS: use "pushd" instead of "push dword", because the second one is not optimized (look in the docs - 1.2.6)
Posted on 2003-03-17 15:24:39 by Tomasz Grysztar

PS: you declare "name" as local, but not "name.l" and "name.h", you can write "name#.l" and "name#.h" instead, but you don't need to declare it as local really - constants can be redefined (and that's why it's working anyway).
PPS: use "pushd" instead of "push dword", because the second one is not optimized (look in the docs - 1.2.6)

I'll skip the local definitions, I thought I needed them so there wouldn't be "already defined"-errors, thanks for enligthen me.
Ok, I'll look in to the docs later. But I had some problems with name#.h, got some error, maybe it was related to the other text in the "unposted experemental version", I'll try it again.
Posted on 2003-03-17 23:28:57 by scientica
This is strange, when using this:
macro glCall3 proc,[arg] {

reverse
if arg eqtype 1.0f
glPush2 arg
else
glPush arg
end if
common
call [proc]
}
...
glCall3 glFinish, _1_0f, _45_0f, 1.2f, 45.0f, _0_1f

I get this error (when using FASM):
flat assembler  version 1.45

opengl.asm [241] glPush [1]:
glCall3 glFinish, _1_0f, _45_0f, 1.2f, 45.0f, _0_1f
error: invalid name.

when using FASMW I get these errors:
Error: Invalid name.

Display:
Instruction: push dword [45.0f+4]
Source: OPENGL.ASM[241]
OPENGL.ASM[41]
OPENGL.ASM[10]

As far as I can follow, the macro fixes memmory addr _1_0f, _45_0f and "immediate" 1.2f but fails on 45.0f (line 41 is "glPush arg"). Have I made some misstake when implenting your "if-eqtype-block" or is the error somewhere else?


btw, heres the updated version of glPush2:
macro glPush2 GLfloatVar {

name = GLfloatVar
virtual at 0
dq GLfloatVar
load name#.l dword from 0
load name#.h dword from 4
end virtual
push dword name.h
push dword name.l
}
Posted on 2003-03-18 11:32:48 by scientica
Well, the parser doesn't allow floating point values in the memory addressing - I could fix that, but you can anyway go over this problem with a little trick, just replace glPush arg with:


addr = arg
glPush addr

BTW, as long as you don't declare name as local, there won't be difference between name.h and name#.h, they will result in exactly the same source after the preprocessing.
Posted on 2003-03-18 11:50:33 by Tomasz Grysztar
Maybe you missunderstood me, 1.2f and 45.0f are floats, not addresses to floats, _1_0f, _45_0f and _0_1f are addresses to floats (they stat with "_" and the "." is replaced with a "_").
In my eyes there is no difference between 1.2f and 45.0f they're both "immediate" vars, qwords/real8. So 45.0f should be pushed with glPush2 not glPush, 1.2f is afaik pushed via glPush2.
Posted on 2003-03-18 11:56:39 by scientica
No, I did not missunderstood you. Out problem comes from that the if directive is processed at the assembly stage, and the error from putting floating-point value inside the square brackets emerges at the parsing stage, when everything is processed regardless of if directive. But the code I wrote above should solve your problem.
Posted on 2003-03-18 12:02:56 by Tomasz Grysztar
And 1.2f is causing the same error as 45.0f, but you see the error from the second one because of the reverse directive.
Posted on 2003-03-18 12:05:01 by Tomasz Grysztar
Ok, it seems like it works now, I think I understand it better now. I begin to undestand how it works now, for every re-read of the post it makes more and more sense to me. :)
Posted on 2003-03-18 12:24:14 by scientica
Arhg!!! :mad: :(
/me stupid, me very stupid, me not bashig head against screen (screen might break) ... :grin:
/me also tired

As I was trying to get the OGL app to show the objects I was about to go mad, I used glColorf, glVertex3Df, and a gazillion other functions endingw with f. The thing is that those OGL functions that ends with f are GLfloat (real4) versions, not GLdouble (real8), no wonder why the macros didn't solve everything ( :rolleyes: ). Luckily there are functions that ends with d, they are GLdouble version of the calls, so now I'm using double precision floats even though I only would need single precision floats. (Since I'm not going to consider all this a waist of time (but make some use of it), and who knows maybe I'll need those extra decimals for later projects in the future (/me not so sure about the last being in the near future ;)) )

(now I just have to fix the "rotation" of one of the objects that is a bit funky now :))
Posted on 2003-03-18 15:06:57 by scientica