Author Topic: Basic FPU Float32 Vector2D NASM Macros (Example code)  (Read 8679 times)

Offline encryptor256

  • Full Member
  • **
  • Posts: 250
  • Country: lv
  • Win64 .
    • On Youtube: encryptor256
Basic FPU Float32 Vector2D NASM Macros (Example code)
« on: October 08, 2013, 10:45:54 AM »
Hello!

Basic FPU Float32 Vector2D NASM Macros.

If i would like to build some OpenGL or other 2D, or even 3D program,
then, these macros would be quite useful, maybe for you too.

Vector2D structure: There are two 4x byte fields

Code: [Select]
struc VECTOR2D
   VECTOR2D.X: resd 1
   VECTOR2D.Y: resd 1
endstruc

These are basic Vector2D macros to manage FPU stack:

; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
; vector2d (Basic)
; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
; 1. vector2d.push 1
; 2. vector2d.pushv 2
; 3. vector2d.set 3
; 4. vector2d.pop 1
; 5. vector2d.pops 0

Code: [Select]
; [*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*]
; [*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*]
; [*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*]
; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
; vector2d (Basic)
; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----

struc VECTOR2D
VECTOR2D.X: resd 1
VECTOR2D.Y: resd 1
endstruc

; 1. vector2d.push:
; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----

%macro vector2d.push 1
float32.push %1
float32.push %1+4
%endmacro

; 2. vector2d.pushv:
; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----

%macro vector2d.pushv 2
sub esp,dword 8
mov dword [esp],__float32__(%1)
mov dword [esp+4],__float32__(%2)
vector2d.push esp
add esp,dword 8
%endmacro

; 3. vector2d.set:
; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----

%macro vector2d.set 3
mov dword [%1],__float32__(%2)
mov dword [%1+4],__float32__(%3)
%endmacro

; 4. vector2d.pop:
; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----

%macro vector2d.pop 1
float32.pop %1+4
float32.pop %1
%endmacro

; 5. vector2d.pops:
; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----

%macro vector2d.pops 0
  sub esp,dword 8
  float32.pop esp+4
  float32.pop esp
%endmacro

These are Vector2D arithmetic macros:

; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
; vector2d (Math)
; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
; 1. vector2d.add 0-2
; 2. vector2d.addv 1-2
; 3. vector2d.sub 0-2
; 4. vector2d.subv 1-2
; 5. vector2d.mul 0-2
; 6. vector2d.mulv 1-2
; 7. vector2d.div 0-2
; 8. vector2d.divv 1-2

Code: [Select]
; [*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*]
; [*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*]
; [*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*]
; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
; vector2d (Math)
; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----

; 1. vector2d.add:
; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----

%macro vector2d.add 0-2
  %if %0 > 0
    %rep %0
vector2d.push %1
      %rotate 1
    %endrep
  %endif
  faddp st2,st0
  faddp st2,st0
%endmacro

; 2. vector2d.addv:
; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----

%macro vector2d.addv 2-4
%if %0 = 3
%error Accepted 2x or 4x params (x0,y0 / x0,y0,x1,y1)
%endif
%rep %0 / 2
vector2d.pushv %1, %2
%rotate 2
%endrep
faddp st2,st0
faddp st2,st0
%endmacro

; 3. vector2d.sub:
; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----

%macro vector2d.sub 0-2
  %if %0 > 0
    %rep %0
vector2d.push %1
      %rotate 1
    %endrep
  %endif
  fsubp st2,st0
  fsubp st2,st0
%endmacro

; 4. vector2d.subv:
; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----

%macro vector2d.subv 2-4
%if %0 = 3
%error Accepted 2x or 4x params (x0,y0 / x0,y0,x1,y1)
%endif
%rep %0 / 2
vector2d.pushv %1, %2
%rotate 2
%endrep
fsubp st2,st0
fsubp st2,st0
%endmacro

; 5. vector2d.mul:
; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----

%macro vector2d.mul 0-2
  %if %0 > 0
    %rep %0
vector2d.push %1
      %rotate 1
    %endrep
  %endif
  fmulp st2,st0
  fmulp st2,st0
%endmacro

; 6. vector2d.mulv:
; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----

%macro vector2d.mulv 2-4
%if %0 = 3
%error Accepted 2x or 4x params (x0,y0 / x0,y0,x1,y1)
%endif
%rep %0 / 2
vector2d.pushv %1, %2
%rotate 2
%endrep
fmulp st2,st0
fmulp st2,st0
%endmacro

; 7. vector2d.div:
; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----

%macro vector2d.div 0-2
  %if %0 > 0
    %rep %0
vector2d.push %1
      %rotate 1
    %endrep
  %endif
  fdivp st2,st0
  fdivp st2,st0
%endmacro

; 8. vector2d.divv:
; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----

%macro vector2d.divv 2-4
%if %0 = 3
%error Accepted 2x or 4x params (x0,y0 / x0,y0,x1,y1)
%endif
%rep %0 / 2
vector2d.pushv %1, %2
%rotate 2
%endrep
fdivp st2,st0
fdivp st2,st0
%endmacro

These are Vector2D macros:

; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
; vector2d (Math)
; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
; 9. vector2d.magnitude 0-1
; 10. vector2d.normalize 0-1
; 11. vector2d.normal 0-1
; 12. vector2d.dot 0-2

Code: [Select]
; [*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*]
; [*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*]
; [*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*],[*]
; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
; vector2d (Math)
; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----

; 9. vector2d.magnitude:
; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----

%macro vector2d.magnitude 0-1

%if %0 = 1
vector2d.push %1
%endif

; Two times of "fld st1" is the same as vector2d.push %1
fld st1
fld st1

vector2d.mul
float32.add
fsqrt
%endmacro

; 10. vector2d.normalize:
; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----

%macro vector2d.normalize 0-1

%if %0 = 1
; One for the division
vector2d.push %1
%endif

; Second for the magnitude
fld st1
fld st1

vector2d.magnitude

; magnitude returned float, load second time
fld st0

vector2d.div

%endmacro

; 11. vector2d.normal:
; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----

%macro vector2d.normal 0-1
; For now, don't do auto normalize on incoming vector,
; let normalization for user.
; Disabled: vector2d.normalize %1

%if %0 = 1
vector2d.push %1
%endif

fchs
fxch st1
%endmacro

; 12. vector2d.dot:
; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----

%macro vector2d.dot 0-2
%if %0 > 0
%rep %0
vector2d.push %1
%rotate 1
%endrep
%endif
vector2d.mul
float32.add
%endmacro

Example code description:

Example code uses float32 macros.
Example code uses two output procedures.
Most of Vector2D macros are based on float32 macros.

For example, vector magnitude is a single float32, so, that's why we need a procedure to print that.

Procedure 1:
; ---------------------------------------------------------
; Procedure printfFloat32
; This procedure prints float32
; Param1: Index
; Param2: float32 Value
; ---------------------------------------------------------

Procedure 2:
; ---------------------------------------------------------
; Procedure printftVector2d
; This procedure prints Vector2d
; Param1: Index
; Param2: vector2d Value in stack: x, y
; ---------------------------------------------------------

Example code:

Demonstration of Vector2D macro usage, variations.

Code: [Select]
        ; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
; vector2d
; ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----

; 1. ------------------------------- (add)
vector2d.pushv 4.5,0.5
vector2d.pushv 3.0,2.0
vector2d.add
vector2d.pops
push dword 1
call printftVector2d

; 2. ------------------------------- (add)
vector2d.set vector1,4.5,0.5
vector2d.set vector2,3.1,2.1
vector2d.push vector1
vector2d.push vector2
vector2d.add
vector2d.pops
push dword 2
call printftVector2d

; 3. ------------------------------- (add)
vector2d.set vector1,4.5,0.5
vector2d.set vector2,3.2,2.2
vector2d.push vector1
vector2d.push vector2
vector2d.add
vector2d.pop vectorResult
push dword [vectorResult+4]
push dword [vectorResult+0]
push dword 3
call printftVector2d

; 4. ------------------------------- (add)
vector2d.set vector1,4.5,0.5
vector2d.set vector2,3.3,2.3
vector2d.add vector1,vector2
vector2d.pops
push dword 4
call printftVector2d

; 5. ------------------------------- (add)
vector2d.pushv 4.5,0.5
vector2d.addv 3.4,2.4
vector2d.pops
push dword 5
call printftVector2d

; 6. ------------------------------- (add)
vector2d.addv 4.5,0.5,3.5,2.5
vector2d.pops
push dword 6
call printftVector2d

; 7. ------------------------------- (div)
vector2d.pushv 30.0,40.0
vector2d.pushv 3.0,4.0
vector2d.div
vector2d.pops
push dword 7
call printftVector2d

; 8. ------------------------------- (divv)
vector2d.divv 33.0,44.0,3.0,4.0
vector2d.pops
push dword 8
call printftVector2d

; 9. ------------------------------- (sub)
vector2d.pushv 15.0,16.0
vector2d.pushv 3.0,4.0
vector2d.sub
vector2d.pops
push dword 9
call printftVector2d

; 10. ------------------------------- (subv)
vector2d.subv 16.0,17.0,3.0,4.0
vector2d.pops
push dword 10
call printftVector2d

; 11. ------------------------------- (mul)
vector2d.pushv 30.0,40.0
vector2d.pushv 3.0,4.0
vector2d.mul
vector2d.pops
push dword 11
call printftVector2d

; 12. ------------------------------- (mulv)
vector2d.mulv 31.0,41.0,3.0,4.0
vector2d.pops
push dword 12
call printftVector2d

; 13. ------------------------------- (magnitude)
vector2d.set vector1,5.0,4.0
vector2d.magnitude vector1
float32.pops
push dword 13
call printfFloat32

; 14. ------------------------------- (normalize)
vector2d.set vector1,5.0,4.0
vector2d.normalize vector1
vector2d.pops
push dword 14
call printftVector2d

; 15. ------------------------------- (normal)
vector2d.set vector1,5.0,4.0
vector2d.normal  vector1
vector2d.pops
push dword 15
call printftVector2d

; 16. ------------------------------- (dot)
vector2d.set vector1,1.7,2.5
vector2d.set vector2,3.8,1.2
vector2d.dot vector1,vector2
float32.pops
push dword 16
call printfFloat32

Example code output:

1. vector2d: x: 7.500000, y:2.500000
2. vector2d: x: 7.600000, y:2.600000
3. vector2d: x: 7.700000, y:2.700000
4. vector2d: x: 7.800000, y:2.800000
5. vector2d: x: 7.900000, y:2.900000
6. vector2d: x: 8.000000, y:3.000000
7. vector2d: x: 10.000000, y:10.000000
8. vector2d: x: 11.000000, y:11.000000
9. vector2d: x: 12.000000, y:12.000000
10. vector2d: x: 13.000000, y:13.000000
11. vector2d: x: 90.000000, y:160.000000
12. vector2d: x: 93.000000, y:164.000000
13. float32: 6.403124
14. vector2d: x: 0.780869, y:0.624695
15. vector2d: x: -4.000000, y:5.000000
16. float32: 9.460000

Source files:

Added attachment:
1. Main compile file "fpu_float32_main.asm".
2. Included at compile time automatically: "fpu_float32_macros.asm".
3. Included at compile time automatically: "fpu_float32_vector2d_macros.asm".

Main compile file, also will contain, float32 macro examples too.

How to compile:

.Like this, in the way i did!

.NASM: "nasm.exe fpu_float32_main.asm -f win32 -o fpu_float32_main.o"

.GCC: "gcc fpu_float32_main.o -m32 -o fpu_float32_main.exe"

.That's it!

.Encryptor256.

Encryptor256's Investigation \ Research Department.

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Basic FPU Float32 Vector2D NASM Macros (Example code)
« Reply #1 on: October 08, 2013, 04:36:13 PM »
Thanks for all the real examples, Encryptor256! I think that with some minor tweaks, most of the examples you've posted can be made to run on Linux as well. I haven't tried them yet. I will(?) and maybe I'll get back to you. Just wanted to let you know that your contributions are appreciated!

Best,
Frank