``````

HitX proc		; Calculate a= rot * (3.14/180)
;// a:=rot*PI/180
;// r:=sqrt(lbr*lbr).
;// hitx:=round(x+sin(a)*r) Used to count X, for Y change it to Cos.
;// The parameter are, [ebp]= PosX, [ebp+4]=Width/lbr(lebar),
;// [ebp+8]=Rotation/angle

fclex
finit			; a:=rot*(pi/180)
fldpi			; st(0)=3.14
mov eax,#180		; 180 decimal
mov [ebp+#100],eax	; mov it to local variable
fild [ebp+#100]		; st(0)=180,st(1)=3.14
fdiv st(1),st		; st(1)=3.14 / st(0)=180
fxch 			; st(0)=st(1)
fild [ebp+8]		; Parameter Degree/rot
fmul st,st(1)		; st(0)=st(0)*st(1)
fsin			; sin(a). a=st(0)
;// The result are at st(0). Now we push another.
fild [ebp+4]		; This is the Widht
fmul st,st(1)		; Mul it, store it at st(0)
;// Its Done, what's more?
mov eax,[ebp]		; Get X value to eax
fist [ebp+#100]		; store integer dword value at [ebp+64h]

ret
HitX endp

``````

Is it Right? I have not Test It
Posted on 2003-07-26 10:15:32 by realvampire
What about hardcoding the pi/180? That would save some instructions.
Posted on 2003-07-26 11:00:46 by roticv
Your assembler would spit back a few errors. When you use memory operands by reference, you MUST specify the size. Otherwise, the assembler cannot know if it's a WORD, a DWORD, a QWORD, and therefore which opcode to generate.

Storing something somewhere on the stack is not a good idea. You may be overwriting something useful.

You could also simplify a few things. Your RED, my BLUE.
``````
[COLOR=red]fclex
;this is useless since finit clears ALL exceptions[/COLOR]
finit			; a:=rot*(pi/180)
fldpi			; st(0)=3.14
[COLOR=red]mov eax,#180		; 180 decimal
mov [ebp+#100],eax	; mov it to local variable
fild [ebp+#100]		; st(0)=180,st(1)=3.14[/COLOR]
[COLOR=blue]pushd 180               ; this won't do any harm
fidiv dword ptr[esp]    ; you can divide directly by a memory operand
; st(0)=3.14/180[/COLOR]
[COLOR=red]fdiv st(1),st		; st(1)=3.14 / st(0)=180
fxch 			; st(0)=st(1)
fild [ebp+8]		; Parameter Degree/rot
fmul st,st(1)		; st(0)=st(0)*st(1)[/COLOR]
[COLOR=blue]fimul dword ptr[ebp+8] ; st(0)=Degree*3.14/180[/COLOR]
fsin			; sin(a). a=st(0)
;// The result are at st(0). Now we push another.
[COLOR=red]fild [ebp+4]		; This is the Widht
fmul st,st(1)		; Mul it, store it at st(0)[/COLOR]
[COLOR=blue]fimul dword ptr[ebp+4]  ; st(0)=Width*sin(a))[/COLOR]
;// Its Done, what's more?
[COLOR=red]mov eax,[ebp]		; Get X value to eax
fist [ebp+#100]		; store integer dword value at [ebp+64h]
[COLOR=blue]fistp dword ptr[esp]    ; overwrite the pushed 180
; AND empties the FPU register
pop eax                 ; get it in EAX and clean the stack
``````

Enjoy

Raymond
Posted on 2003-07-26 11:16:59 by Raymond
Thanks Raymond. I'll use it.
Posted on 2003-07-27 22:10:04 by realvampire
Hope it usefull.

``````
GetDeltaXY proc

mov eax,[ebp+8]		; x2-x
sub [ebp],eax		;
mov eax,[ebp+#12]	; y2-y
sub [ebp+#12],eax	;

ret
GetDeltaXY endp

GetHypot proc	; Basic Function.
; Parameter are [ebp]=dx, [ebp+4]=dy.

mov eax,[ebp]	; Delta X
mul eax		; delta x^2
mov [ebp],eax	;

mov eax,[ebp+4]	; Delta Y
mul eax		; Delta Y^2

add [ebp],eax	; (dx^2) + (dy^2)

finit		; Initialize
fild d.[ebp]	; Load integer at [ebp]
fsqrt		; square root it
fist d.[ebp]	; Store it to ebp back
mov eax,[ebp]	; Return it to Reg a32

ret
GetHypot endp

``````
Posted on 2003-07-29 04:43:15 by realvampire
Originally posted by realvampire
Hope it usefull.

``````
GetDeltaXY proc

mov eax,[ebp+8]		; x2-x
sub [ebp],eax		;
mov eax,[ebp+#12]	; y2-y
sub [ebp+#12],eax	;

ret
GetDeltaXY endp

GetHypot proc	; Basic Function.
; Parameter are [ebp]=dx, [ebp+4]=dy.

mov eax,[ebp]	; Delta X
[COLOR=red]xor edx, edx[/COLOR] ;you HAVE to clear edx in order to prevent an overflow exception
mul eax		; delta x^2
mov [ebp],eax	;

mov eax,[ebp+4]	; Delta Y
[COLOR=red]xor edx, edx[/COLOR]
mul eax		; Delta Y^2

add [ebp],eax	; (dx^2) + (dy^2)

finit		; Initialize
fild d.[ebp]	; Load integer at [ebp]
fsqrt		; square root it
fist d.[ebp]	; Store it to ebp back
mov eax,[ebp]	; Return it to Reg a32

ret
GetHypot endp
``````

and what about just using only the fpu (created on the fly)
``````
GetHypot proc
fild dword [ebp] ;delta x
fmul st0
fild dword [ebp+4] ;delta y
fmul st0
fsqrt
fistp dword [esp-4] ;just a temporary place
mov eax,[esp-4]
ret
GetHypot endp
``````
Posted on 2003-07-29 07:51:11 by hartyl
mov eax, ; Delta X
xor edx, edx ;you HAVE to clear edx in order to prevent an overflow exception
mul eax ; delta x^2
There is NO need to clear EDX before a multiplication. You could even use EDX as the multiplier.
``````mov  eax,deltax
mov  edx,deltay
mul  edx       ;EDX:EAX = deltax*deltay``````
The only time it is necessary to clear EDX is before dividing a number in EAX by another number.

The suggestion of using the FPU for the entire computation could simplify the coding whenever the squared values would exceed the range of the 32-bit registers.

The only advantage in using FPU instructions for this kind of computation is the reduction in code size. Even the square root of a 64-bit integer can be extracted with CPU instructions with similar speed as the FPU.

realvampire:
mov eax, ; y2-y
sub ,eax ;
It's again obvious you have not tested your code. You will NEVER get your deltaY into that way.

Raymond
Posted on 2003-07-29 09:16:04 by Raymond
replace:
``````
fldpi
pushd 180
fidiv dword ptr[esp]
``````

with:
``````
fldpi
db 68h
REAL4 180.0
fdiv REAL4 PTR [esp]
``````

It should save a clock or two.

Mirno
Posted on 2003-07-29 13:24:14 by Mirno
@Mirno: and what instruction's behind that db 0x68?

@Raymond: do you have a reference to a 64bit integer-sqrt using the cpu only?
Posted on 2003-07-29 13:38:21 by hartyl
68h is the full 4 byte immediate push
6Ah is a one (signed) byte expanded to 4 push...

So by using 68h, followed by the REAL4 declaration, the data being pushed is the floating point version of 180. This saves the integer to float conversion.

Mirno
Posted on 2003-07-29 14:04:18 by Mirno
The Mixlib library contains two square root functions, one for 32-bit unsigned integers and one for 64-bit unsigned integers. You can find the zipped file (which also contains all the source code) at the bottom of the page at:

http://www.movsd.com/source.htm

The library is designed to perform fixed point maths with an accuracy of 5 decimal places using strictly CPU instructions. The integer portion is limited to +/-32767, which should generally be good enough for screen displays.

The library is NOT designed for highly accurate scientific computations.

Raymond
Posted on 2003-07-29 18:25:25 by Raymond
Thanks all,

1. If I fild dword 1.0, what is the hex value?
2. If I FIST, does the FPU stack decremented? whats the different with fistp?

``````
line proc
;ebp=x, ebp+4=y, ebp+8=x2, ebp+#12=y2
;ebp+#16=color

push ebp
push d.[ebp]
push d.[ebp+4]
push d.[ebp+8]
push d.[ebp+#12]
pop d.[ebp+#12]
pop d.[ebp+#8]
pop d.[ebp+#4]
pop d.[ebp]
call deltaxy
pop ebp
; ebp+#20=deltaX, ebp+#24=DeltaY
push ebp
push d.[ebp+#20]
push d.[ebp+#24]
pop d.[ebp+#4]
pop d.[ebp]
call gethypot
pop ebp
; ebp+#28=Hypotenusa

ret
line endp
``````

That is my line function, I have not finiished it.
Posted on 2003-07-30 22:00:51 by realvampire
2. all instructions have kinda same format. the only thing i still remember is that if a fpu-instruction has a 'p' at the end of it st0 ist poped off the fpu-stack after the operation.
so, fist just stores (st) st0 as integer (i) and rounds according to the smw.
fistp stores st0 as integer but poppes it off the stack.

and in your line-proc, i don't know what u're doing with the stack before calling the procs...
Posted on 2003-07-31 02:32:32 by hartyl

I dont know...

Here is the complete file.
Posted on 2003-07-31 08:17:14 by realvampire
h?? what are you quoting?!

Originally posted by hartyl

i don't know what u're doing with the stack before calling the procs...

Originally posted by realvampire
``````
push ebp
push d.[ebp]
push d.[ebp+4]
push d.[ebp+8]
push d.[ebp+#12]
pop d.[ebp+#12]
pop d.[ebp+#8]
pop d.[ebp+#4]
pop d.[ebp]
call deltaxy
pop ebp
``````

my sentence sould say that i don't believe that this routine for pushing parameters on the stack works - or: this is a every bad way to push parameters on the stack.
the better (correct one)

``````
function proc
push ebp
mov ebp, esp ;build up stack frame
mov eax, [esp+8] ;param0
mov eax, [esp+12] ;param1
mov eax, [esp+16] ;param2
:
:
:
pop ebp ;resore old basepointer
ret 12 ;correct the 12 bytes of params on the stack
function endp

and the way to call it:

push param2
push param1
push param0
call function
``````
Posted on 2003-07-31 08:33:06 by hartyl
realvampire,

You may get answers to many of your questions related to the FPU in the tutorial (still in progress but almost completed) at:

http://www.masmforum.com/website/tutorials/fptute/index.html

Raymond
Posted on 2003-07-31 10:15:56 by Raymond