What I'm currently working on is an ASM program thats composed of objects. It might sound strange at first but its a really simple concept to understand, and has probably already been done by someone.
Basically each object has code that controls it. Its shape, , texture, movement, reactions to other objects, etc. are all controlled by the object itself rather than a traditional engine. I have been working on this for about two years now, mostly when I have nothing else to do. The only major thing that an engine is in control of is integrating all of the interactions of different objects together to form a single output stream to the user. Other things include inputs, constant forces, timekeeping, networking, etc.
While browsing the site I have noticed a number of posts regarding the problem of calculating the distance between 2 points so I decided I should write a quick ASM routine to do this while it was still fresh in my mind. I don't have a library of 3D and graphics related functions yet so this would be a good place to start. So here is the code I threw together in about 10 minutes, unoptimized, untested, and basically unchecked. I will do all that later but have just thought that I need to also make a routine that would compute the distance between multiple sets of 2D points.
dist_between_points: ;calculates the distance between two points in 3D space
MOVAPS XMM0, point 2 ;load XMM0 with point 2 (packed as n, x2, y2, z2)
MOVAPS XMM1, point 1 ;load XMM1 with point 1 (packed as n, x1, y1, z1)
SUBPS XMM0, XMM1 ;subtract XMM1 from XMM0 (subtract x1, y1, z1 from x2, y2, z2)
MULPS XMM0, XMM0 ;multiply XMM0 by itself (square x, y, and z)
HADDPS XMM0, XMM0 ;add FP values in XMM0 horizontally (n + x, y + z)
HADDPS XMM0, XMM0 ;add horizontally again ((n + x) + (y + z))
SQRTPS XMM0, XMM0 ;calculate the square root to get our distance
MOVAPS distance, XMM0 ;store the distance to use later
EMMS ;free the FPU for other operations
RET ;return to caller
...and the code for two sets of 2D points....
2D_dist_two_points ;calculates the distances between two sets of points in 2D space
MOVAPS XMM0, set 2 ;load XMM0 with point set 2 (packed as x2a, y2a, x2b, y2b)
MOVAPS XMM0, set 1 ;load XMM1 with point set 1 (packed as x1a, y1a, x1b, y1b)
SUBPS SMM0, XMM1 ;subtract XMM1 from XMM0 (x2a - x1a, y2a - y1a, x2b - x1b, y2b - y1b)
MULPS XMM0, XMM0 ;multiply XMM0 by itself (square xa, ya, xb, yb)
HADDPS XMM0, XMM0 ;add FP values in XMM0 horizontally (xa + ya, xb + yb)
SQRTPS XMM0, XMM0 ;calculate the square roots to get distances
MOVAPS XMM1, XMM0 ;copy the distances
PUNPCKHDQ XMM0, XMM0 ;unpack distance a (making the distance xx, yy)
PUNPCKLDQ XMM1, XMM1 ;unpack distance b (making the distance xx, yy)
MOVAPS distance_a, XMM0 ;store distance a
MOVAPS distance_b, XMM1 ;store distance b
EMMS ;free FPU for other operations
RET ;return to caller
After messing around with trying to multiply two matricies together I decided to take a break and write something easy, a routine to scale a matrix by a scaling value:
scale_matrix: ;scales a matrix by scaling value xs, ys, zs, n
MOVAPS XMM4, scalar ;load XMM4 with the scaling value (packed as xs, ys, zs, n)
MOVAPS XMM0, column 0 ;load XMM0 with first column (packed as xs, ys, zs, n)
MOVAPS XMM1, column 1 ;load XMM1 with second column (packed same as above)
MULPS XMM0, XMM4 ;multiply first column by scalar
MOVAPS XMM2, column 2 ;load XMM2 with third column (packed same as above)
MULPS XMM1, XMM4 ;multiply second column by scalar
MOVAPS XMM3, column 3 ;load XMM2 with fourth column (packed same as above)
MULPS XMM2, XMM4 ;multiply third column by scalar
MOVAPS column 0, XMM0 ;store first column
MULPS XMM3, XMM4 ;multiply fourth column by scalar
MOVAPS column 1, XMM1 ;store second column
MOVAPS column 2, XMM2 ;store third column
MOVAPS column 3, XMM3 ;store fourth column
EMMS ;free the FPU
RET ;return to caller
...and naturally the translation of a matrix....
translate_matrix: ;translates a matrix by translation value xt, yt, zt, n
MOVAPS XMM4, translate ;load XMM4 with the translation value (packed as xt, yt, zt, n)
MOVAPS XMM0, column 0 ;load XMM0 with first column (packed as x, y, z, n)
MOVAPS XMM1, column 1 ;load XMM1 with second column (packed same as above)
ADDPS XMM0, XMM4 ;add translation value to first column
MOVAPS XMM2, column 2 ;load XMM2 with third column (packed same as above)
ADDPS XMM1, XMM4 ;add translation value to second column
MOVAPS XMM3, column 3 ;load XMM2 with fourth column (packed same as above)
ADDPS XMM2, XMM4 ;add translation value to third column
MOVAPS column 0, XMM0 ;store first column
ADDPS XMM3, XMM4 ;add translation value to fourth column
MOVAPS column 1, XMM1 ;store second column
MOVAPS column 2, XMM2 ;store third column
MOVAPS column 3, XMM3 ;store fourth column
EMMS ;free the FPU
RET ;return to caller
So after running a couple short errands and wasting some time I thought of what I could add to my rountines. The next step I thought about was to make 'streaming' versions of the scaling and translation routines:
scale_matrix_stream: ;scales a number of matricies by scaling values xs, ys, zs, n
MOVAPS XMM7, scalar ;load XMM4 with the scaling value (packed as xs, ys, zs, n)
MOV ECX, repititions ;load ECX with the number of matricies to process
SHR ECX, 1 ;shift LSB of EAX into CF
JNC, evennumber ;the number of matricies to process is even; process matricies
MOVAPS XMM0, column 0 ;load XMM0 with first column (packed as xs, ys, zs, n)
MOVAPS XMM1, column 1 ;load XMM1 with second column (packed same as above)
MULPS XMM0, XMM7 ;multiply first column by scalar
MOVAPS XMM2, column 2 ;load XMM2 with third column (packed same as above)
MULPS XMM1, XMM7 ;multiply second column by scalar
MOVAPS XMM3, column 3 ;load XMM2 with fourth column (packed same as above)
MULPS XMM2, XMM7 ;multiply third column by scalar
MOVAPS column 0, XMM0 ;store first column
MULPS XMM3, XMM7 ;multiply fourth column by scalar
MOVAPS column 1, XMM1 ;store second column
MOVAPS column 2, XMM2 ;store third column
MOVAPS column 3, XMM3 ;store fourth column
TEST ECX, FFFFFFFF ;see if ECX = 0
JZ, streamdone ;finish if ECX = 0
evennumber:
MOVAPS XMM0, column 0 ;load XMM0 with set 0, first column (packed as xs, ys, zs, n)
MOVAPS XMM1, column 1 ;load XMM1 with set 0, second column (packed same as above)
MULPS XMM0, XMM7 ;multiply set 0, first column by scalar
MOVAPS XMM2, column 2 ;load XMM2 with set 0, third column (packed same as above)
MULPS XMM1, XMM7 ;multiply set 0, second column by scalar
MOVAPS XMM3, column 3 ;load XMM3 with set 0, fourth column (packed same as above)
MULPS XMM2, XMM7 ;multiply set 0, third column by scalar
MOVAPS XMM4, column 0 ;load XMM4 with set 1, first column (packed same as above)
MULPS XMM3, XMM7 ;multiply set 0, fourth column by scalar
MOVAPS XMM5, column 1 ;load Xmm5 with set 1, second column (packed same as above)
MULPS XMM4, XMM7 ;multiply set 1, first column by scalar
MOVAPS XMM6, column 2 ;load XMM2 with set 1, third column (packed same as above)
MULPS XMM5, XMM7 ;multiply set 1, second column by scalar
MOVAPS column 0, XMM0 ;store set 0, first column to free XMM0 for use
MULPS XMM6, XMM7 ;multiply set 1, third column by scalar
MOVAPS XMM0, column 3 ;load XMM3 with set 1, fourth column
MOVAPS column 1, xMM1 ;store set 0, column 1
MULPS XMM0, XMM7 ;multiply set 1, fourth column by scalar
MOVAPS column 2, XMM2 ;store results
MOVAPS column 3, XMM3
MOVAPS column 0, XMM4
MOVAPS column 1, XMM5
MOVAPS column 2, XMM6
MOVAPS column 3, XMM0
DEC ECX ;decrement counter
JNZ, evennumber ;process two more matricies if ECX <> 0
steamdone:
EMMS ;free the FPU
RET ;return to caller
If you understand ASM enough to read that, you may ask why I have put two seperate calculation blocks in the routine. Its simple - I want to process as many elements at one time as I can without any branching. So the first block is processed if the number of matricies to process is odd, then the code continues to the next block where two matricies are processed before branching.
So thats all for now. Feel free to comment as you like but please keep comments constructive, otherwise I will just ignore them. Bye bye :)
Oh, and as I believe is customary, welcome to journal land!