Tuesday, November 11, 2014

I'm looking for someone really small...................................

                              We're going to talk about how to find the smallest guy in a crowd. I tweaked my program from the last post,so now instead of finding out how many of the numbers are 8's,we're going to find out which one of the numbers is the smallest.


Here's the program:



The C++ part:


extern "C" void doit();

void main()
{
doit();
}

And the assembly part:


.586
.model flat, c
.stack 100h
.data

 myNumbers dword 7,3,8,2,2,9,8,5,7,4,8,3,8,1,8,7,4,8

.code


doit proc
xor eax,eax
xor ecx,ecx
mov ebx,myNumbers[eax]
again:
add eax,4
mov ecx,myNumbers[eax]
cmp ecx,ebx
jl switcheroo
back:
cmp eax,68
jle again
ret
switcheroo:
mov ebx,ecx
jmp back


doit endp


end

             So get all that typed in and I'll explain how it works.

             This is how it works,just like the program from the last post we xor eax by eax,and ecx by ecx,and also we move myNumbers into ebx,except we only do that once because of the again. Then as always we add 4 to eax so that we can access the next number of myNumbers,except not because we want to place the next number of myNumbers in ebx,we want to place it in ecx,and here's why.
We take the next number of myNumbers and compare it  to the number currently in ebx and if it is smaller than the number currently in ebx then we jump to switcheroo. In switcheroo we move the number currently in ecx into ebx so that we always  have the smallest number we've seen so far in ebx. Then we jump to back compare eax to 68 and if it is less than or equal to 68 we jump back to again.

                                     WELL TTFN TA TA FOR NOW!!!! 



Monday, November 10, 2014

COPS and ROBBERS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

                      We're going to make a program that finds all of the 8's in a jumble of numbers and then tells you how many of them there are, sorta like cops investigating a bunch of people and trying to find out how many of them are criminals.

Here's the program:




1st the C++ part:


extern "C" void doit();

void main()
{
doit();
}


And then the assembly part:

.586
.model flat, c
.stack 100h
.data

 myNumbers dword 7,3,8,2,2,9,8,5,7,4,8,3,8,13,8,7,4,8

.code


doit proc
xor eax,eax
xor ecx,ecx
again:
mov ebx, myNumbers[eax]
cmp ebx,8
je CountingCounter
back:
add eax,4
cmp eax,68
jle again
ret

CountingCounter:
add ecx,1
jmp back


doit endp


end





So get all that typed in and then I'll explain how it works.

The program starts out in C++, and from there calls doit an assembly procedure.Then we create MyNumbers which is our jumble of people. So how do we find out how many are criminals (8's)? Well first we need 2 registers,eax,and ecx to be completely zeroed out because we're going to use one: eax to access MyNumbers correctly,and we'll use ecx to count how many criminals (8's) there are.Now we say mov ebx MyNumbers and you see how I've got eax in the brackets? Well that's because we're using eax to access MyNumbers,and since eax is currently 0 we will access the first number in MyNumbers. Now since the criminals are 8's we compare ebx to 8 and if it is 8 we would do that jump equal to (je) but I'll get back to that later. That "back" is where we jump to from the je so don't worry about it right now,so next we add 4 to eax because every number is a dword and a dword is 4 bytes. Then we compareeax to 68 because that's the number we stop at. Then we do the jle which means if eax is less than or equal to 68 jump back to again. Now I'll talk about what would happen if ebx was an 8. We would do the je  down to CountingCounter. Then we would add 1 to ecx because we're using it to count how many 8's there are, Then we jump to back.





WELL TTFN TA TA FOR NOW!!!!!!!!!!!!!!!!!!







Monday, October 27, 2014

SPACESHIP!!!!!!!!!!!!!!!!!!!!!!!!!!!SPACESHIP!!!!!!!!!!!!!!!!!!!!SPACESHIP!!!!!!!!!!!!!SPACESHIP!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Hi! Long time no see huh! Well I've been working on a little something that I'm going to show you now. I've been working on a program that makes a little spaceship video game! You drive a little spaceship around a black screen and it bounces off the walls. You can adjust the speed (speed = magnitude),and direction (magnitude + direction = velocity) of the spaceship anddddddd, it will never leave the screen!





Here's my program:



#include <Core.h>
#include <Vector.h>

Vector position;
Vector velocity;

void checkin ( )
{
if(Core::Input::IsPressed(Core::Input::KEY_LEFT))
{
velocity.x = velocity.x - 1;
}
if(Core::Input::IsPressed(Core::Input::KEY_RIGHT))
{
velocity.x = velocity.x + 1;
}
if(Core::Input::IsPressed(Core::Input::KEY_UP))
{
velocity.y = velocity.y - 1;
}

if(Core::Input::IsPressed(Core::Input::KEY_DOWN))
{
velocity.y = velocity.y + 1;
}
}






bool MyUpdateFn( float dt )
{
checkin ();

position = position +  velocity * dt;



if (position.x > 800)
{
velocity.x = velocity.x * -1;
}

if (position.x < 0)
{
velocity.x = velocity.x * -1;
}

if (position.y > 800)
{
velocity.y = velocity.y * -1;
}


if (position.y < 0)
{
velocity.y = velocity.y * -1;
}
return false;
}


void drawship (Core::Graphics& graphics)
{
Vector a(-50,50);
Vector b(-50,-50);
Vector c(50,-50);
Vector d(50,50);
Vector e(0,-100);

Vector aPrime = position + a;
Vector bPrime = position + b;
Vector cPrime = position + c;
Vector dPrime = position + d;
Vector ePrime = position + e;

graphics.DrawLine(aPrime.x,aPrime.y,bPrime.x,bPrime.y);// 1
graphics.DrawLine(aPrime.x,aPrime.y,dPrime.x,dPrime.y);// 4
graphics.DrawLine(bPrime.x,bPrime.y,cPrime.x,cPrime.y);// 2
graphics.DrawLine(cPrime.x,cPrime.y,dPrime.x,dPrime.y);// 3
graphics.DrawLine(ePrime.x,ePrime.y,cPrime.x,cPrime.y);// 5
graphics.DrawLine(ePrime.x,ePrime.y,bPrime.x,bPrime.y);// 6



}


void MyDrawFn( Core::Graphics& graphics)
{
// drawship(graphics);
}


int main()
{
Core::Init("Collin", 800, 800);
Core::RegisterUpdateFn(MyUpdateFn);
Core::RegisterDrawFn(MyDrawFn);
Core::GameLoop();
}



As you can see, it's a ton of code. So I'll start explaining it so we're not here for a century or 2. At the top we make our 2 vectors: position, and velocity. Next we make our void checkin procedure. After that we make our bool MyUpdateFn .  Then we type in the void drawship procedure,and after that we type in void MyDrawFn,and finally.........last but not least...........int........main!! Once you've gotten all that typed in we'll take a peek at how it fits together to make a game.




HI THERE!! REMEMBER ME!!?? OF COURSE YOU DO!! So the reason we make our 2 vectors is because we're gonna need vectors right? The reason we call them position and velocity is because one of them represents the ships' position and the other represents the ships' velocity. The position of the ship is where it's at on the screen and the velocity of the ship is what direction the ship is going in and how fast it's going in that direction,so whenever you change the ships' velocity you indirectly change the ships position so together velocity and position make the ship move. But that  doesn't mean that you have to change velocity to change position, in fact position has to be updated every single frame or else the ship stops when you let go of the arrow keys and then you have to start again at the lowest speed. The top procedure: void checkin controls which direction the ship is going in and how fast it's going in that direction,those little bits of code each control one of the arrow keys, you see how on left we're taking away from velocity.x and on right we are adding to it? Plus when we do up, we subtract from velocity.y,and when we do down  we add to it. Then it's off to see bool MyUpdateFn! In MyUpdateFn we make the ship bounce off the "walls" of the screen,here's how we do it. The screen is 800 by 800 pixels right? Well how we make the ship bounce off the walls is this. We say "if position.x is less than 0 or bigger than 800 multiply it by -1 and the same thing with position.y. The reason we multiply them by -1 is because whenever you multiply a number by -1 if it's a positive number it becomes a negative number,and if it's a negative number it becomes a positive number which flips the direction of the ship so whenever the ship hits a wall it goes in the opposite direction at the same speed. Now we're going to talk about my drawship procedure. This procedure as it's name suggests draws the ship on our screen using vectors a,b,c,d, and e and then sets them to the x,and y positions that we want to put the lines that make up the ship between. Now, you're probably wondering, if we set the ship to one position how is it supposed to move?  How we do that is we take these vectors and add them to position so that they will move, and name those new vectors aPrime,bPrime etc. etc. Then we take those Prime vectors and build the ship with them. And everything else after that is stuff my dad put in that I don't know how to explain.


                                           WELL   TTFN TA TA FOR NOW!!!!



Wednesday, June 25, 2014

The Case of the Missing Sphere

 Hi, it's been awhile. I've been working on ray tracing, and I have something new to teach you. Have you ever looked at a really realistic movie made out of computer graphics, or a really good video game and wondered how they made it ? They might have used ray tracing. Ray tracing is using rays and vectors to make a picture.  I've been working on it and I'm going to teach you what I know so far.  We are going
to put a sphere in the middle of a picture and use rays to color it so we can see it. First off we're going to need to place the sphere, and since we need to place it in the middle first we need to figure out how big our screen is. We're not going to use the entire screen, instead we're going to use a smaller 300*300 pixels screen. That means to place the sphere in the middle of the screen we need to place it's origin at -150 y,  150 x, and -300 z, and make it's radius 150. So we have our sphere. Now we need our rays. We need to hit every single pixel with a ray. So that means we need to put a ray at every single pixel. Doing them individually would take forever, so instead we're going to use a loop.

 This loop is going to create new rays and place them at different points.

for(int row = 0 ; row < NUM_PIXELS_Y ; row++)
for(int col = 0; col < NUM_PIXELS_X ; col++)
{
Ray explorer;
explorer.origin.x = -149.5 + col;
explorer.origin.y = -149.5 + row;
explorer.direction.z =-1;
   

Notice that I didn't close it off with a curly brace. That's because this is only the 1st 1/2 of the loop.  We'll get into the second 1/2 later but for now let's focus on this.

Our ray is called explorer, and what's nice about this loop is that after it does explorer it automatically does all the other rays, so we don't have to do another loop along with it. When we say col we mean columns, and obviously row means rows. The "for" part up there is the 1st part of the loop, they're the actions we do to determine if we go into the 2nd part of the loop. So there's int row = 0; which creates row and then makes it 0, then we compare row to NUM_PIXELS_Y;, row++ means increment row(if you don't know what increment means it means add 1) and the next line is the same except col replaces row and  NUM_PIXELS_X; replaces NUM_PIXELS_Y;. Then we have all this stuff about rays' origin. Origin.x is -149.5 + col, and origin.y is -149.5 + row, so as columns goes across and rows goes up and down we end up with rays at every single pixle of our 300*300 screen. And direction.z is the direction of the rays.


glm::vec3 hipotenoose = sphere.origin - explorer.origin;
 float adjacentLength = glm::dot(explorer.direction,hipotenoose);
 glm::vec3 adjacent = explorer.direction * adjacentLength; glm::vec3 opposite = hipotenoose - adjacent; if(glm::length(opposite) < sphere.radius) { 



qimage.setPixel(col,row,qRgb(0xFF,0,0)); }

Now for the 2nd 1/2 of the loop.

We've got our sphere and our rays, and now we have to figure out what rays hit the sphere and what rays don't and what to do if the ray hits the sphere. Here's the math.
                                                       
I know, it looks ridiculous but this is what we do. See we've got our ray which we can tell just by looking at this picture is going to hit the sphere. But the computer doesn't know that, so we need to do some math to figure it out. We've got our sphere, the spheres' origin,the spheres' radius, and our point of the world ( the + ). So 1st we draw a line from the spheres' origin to the rays' origin ( hypotenuse ), a line coming off of the ray ( adjacent ), a line coming off the point of the world to the rays' origin,and a line coming off the point of the world to the spheres' origin. The reason we're drawing these lines from the point of the world is so we can figure out hypotenuse, and how we do that is we say: ray origin - sphere origin = hypotenuse. So now we've got one side but we need the others to. So on to adjacent !!! To figure out adjacent we need to do hypotenuse, dot, rays' direction. Dot sort of means multiplication but you end up with the magnitudes of the vectors you're using and cos theta. So this is what we got from dotting those 2 together: |hypotenuse| |rays ' direction| cos theta. Now we scale it off of the ray's direction and we've got our adjacent! The next part is easy since we've got our hypotenuse and our adjacent now we need to get our opposite. All we have to do is subtract one from the other and we've got our opposite. Then we compare it to the spheres' radius and if it's longer the ray didn't hit  the sphere but if it's shorter the ray did hit the sphere. And the last line of code colors the pixels and you can fiddle around with the numbers to change the color of the sphere.

Detective, case solved!

Wednesday, November 27, 2013

The battle of AbstractionMan and Evil Dr.Details

        Ahoy there mateys! This day we shall plunge ourselves down into the sea of C++! I'm serious there so get ready to type! Now you know what we've been doing so far, we've been coding up vectors. But we've had trouble with Evil Dr.Redundancy.....and a new villain Evil Dr.Details. That's why I've prepared two procedures to get rid of them called add, and subtract so that instead of  having a ton of redundant code and a ton of details we can just do the code that's in the procedures and have a lot of abstraction. And for each of those two procedures we changed the're names to something special. On add we changed the name to  operator+ and on subtract we changed the name to operator- so instead of calling the procedures we can just say resultVector=leftVector+rightVector and it will call operator+ or we can say resultVector=leftVector-rightVector and it will call operator-. And guess what, that helps to get rid of details so we fired a shot at Evil Dr.Details. Aaaaaaaannnnnnnd that also gets rid of redundancy so we hit Evil Dr.Redundancy prrrrrretty hard. And AbstractionMan is now here to help us,and you can't have abstraction without the code to produce it so we've had some help from MemoryMan too. And how MemoryMan helps us is that instead of having six floats to keep track of we have 3 vectors called leftVector,rightVector,and resultVector. Now we're on a roll!

Here is my program:

struct Vector
{
float x;
float y;
};
Vector operator- (Vector left,Vector right)
{
Vector resultMan;
resultMan.x=left.x-right.x;
    resultMan.y=left.y-right.y;
return resultMan;
}
Vector operator+ (Vector left,Vector right)
{
Vector resultMan;
resultMan.x=left.x+right.x;
resultMan.y=left.y+right.y;
    return resultMan;
}
Vector leftVector;
Vector rightVector;
Vector resultVector;

void CollinsBasicVectorEquationCallback(const BasicVectorEquationInfo& data)
{
leftVector.x=data.x1*data.scalar1;
leftVector.y=data.y1*data.scalar1;
rightVector.x=data.x2*data.scalar2;
    rightVector.y=data.y2*data.scalar2;

if(data.add)
{
resultVector= leftVector + rightVector;
}
else
{
       resultVector=leftVector - rightVector;
}
}



Thursday, November 21, 2013

Vector!!!!......is back. dendenduuuuuuuuuun!

Direction
Magnitude
X components
Y components
                 Those are what vectors have. Ever watch Despicable Me? Well the rival bad guys name is vector,now your going to learn what a vector is. A vector is an arrow with direction,which is what "direction" the arrow points in,and magnitude,which is how long or short the arrow is. When you subtract 2 vectors then there is a result vector which is a different colored vector that connects the tips of the 2 other vectors to finish the shape. Then there's adding vectors. When you add vectors the 2nd vector starts from the tip of the 1st vector.  On a graph,vectors start from the origin (Middle point) for instance: when you subtract vectors then the vectors start from the origin and the result vector connects the tips of the 2 vectors. But when your adding vectors the 1st vector starts from the origin and the 2nd vector starts from the tip of the 1st one,and the result vector starts from the origin.

     Here's what some vector addition would resemble to:

    Here's what some vector subtraction would look like:

            The blue vectors are the vectors that I've been talking about and the red vector is the result vector. Now I'm going to talk about X components and Y components. The X component is how far right or left the vector points. And the Y component is how far up or down the vector points. When you add vectors you add the individual components,for example:if my X component for one vector was 3 and my Y component was 5 then if I add that to another vector that has a X component that's 4 and a Y component that is 2 then my result vector would be X 7 Y 7. And for subtraction it's the same thing.

Now I'm going to talk about scalar multiplication. There are 2 sliders that we haven't used yet called the scalars. The scalars are multiplication sliders that are usually at 1 because 1 times anything is exactly that value but If you change that 1 to a 2 then it will double the magnitude and change the direction of the vectors.
For example: here are my vectors with scalars of 1.

And here are vectors with scalars of 2.
I bet you can see the difference huh? Well even though they aren't the same size they are the same shape. Oh and make sure that you change the scalar for both vectors not just 1.

And last but not least here is my program:

float myFloats[6];

void CollinsBasicVectorEquationCallback(const BasicVectorEquationInfo& data)
{
myFloats[0]=data.x1*data.scalar1;
myFloats[1]=data.y1*data.scalar1;
myFloats[2]=data.x2*data.scalar2;
myFloats[3]=data.y2*data.scalar2;

if(data.add)
{
myFloats[4]=myFloats[0]+myFloats[2];
myFloats[5]=myFloats[1]+myFloats[3];
}
else
{
myFloats[4]=myFloats[0]-myFloats[2];
myFloats[5]=myFloats[1]-myFloats[3];
}

}  
Catch you later! 

Friday, November 8, 2013

Who's the New Guy?

Your going to hate me when I say this but this post is not about assembly.......it's about C++. Now C++ is a type of code that is very commonly used and instead of using the CPU to build it uses the compiler and (here's the funny part) C++'s disassembly builds as assembly so you can double check that it's working right. SO now I have to talk about how C++ works. For one thing C++ is a lot shorter than assembly because 1 C++ instruction can make several assembly instructions. Plus (surprisingly) it takes care of all the hard stuff for you. But don't get to carried away with it or else your assembly skills will drop. I'm still going to have you do some assembly programs after we go over some C++. C++ procedures and assembly procedures look almost nothing alike and as I said C++ procedures are a lot shorter than assembly procedures.
Here is a C++ procedure:

int main()
{
int total=0;
int termindex=0;
while (termindex < 6)
{
// calculate the next term value
int TermValue = raiseToThePower(bases[termindex],exponents[termindex]);

total = determineOperations(operations[termindex],total,TermValue);
termindex++;
}
std::cout << total;
}


Here is an assembly procedure:

doit proc
push eax
push edx
push ebx
push ebp
push ecx
sub esp,4               ; allocating termindex so we can use it 
mov ebp,esp
mov dword ptr [ebp],0
restart:
mov eax,4 ; calculate 4-byte offset into our data
mul dword ptr [ebp] ; Multiply term index
mov edx,eax ; Saving the 4-byte offset into edx

    ; calculate the next term value
mov ecx,bases[edx]
mov ebx,exponents[edx]
call raiseToThePower

    ; do the operation
mov ecx,eax
mov ebx,total
mov eax,operations[edx]
call determineOperations
mov total,ebx

; See if we need to repeat
inc dword ptr [ebp]               
cmp dword ptr [ebp],6
jl restart
pop ecx 
pop ebp
pop ebx
pop edx
pop eax 
add esp,4 ; deallocating termindex
  ret
doit endp


You see in assembly we need to define everything to the right register and it takes so much time and dudududududududu but in C++ it doesn't take so long and you don't have to worry about the registers because  C++ takes care of  them for us. And you don't have to worry about the "Leave No Trace"rule because C++ automatically does the pushes and pops. Now, you know how we carry certain values back and forth between the different procedures? Well how we do that in C++ is we say "return"and then the name of the dword that has the value that we want to pass to a different procedure. But still don't let it get the best of you because assembly is still pretty important.

Well the previous post (Assembly Town) had a program didn't it. This is that same program except in C++.



#include <iostream>

// We go from main to raiseToThePower
// with the bases and exponents (2,7) and go
// into the loop to multiply them together
// as many times as the exponent

int determineOperations(int operation, int currentTotal, int termValue)
{  
int newtotal;
switch(operation)
{
case 0:
newtotal=currentTotal + termValue;
break;
case 1:
       newtotal=currentTotal - termValue;
break;
case 2:
newtotal=currentTotal * termValue;
break;
}
return newtotal;
}      

int raiseToThePower(int base, int exponent)
{
int count=0;
int answerToThePower=1;
while (count <exponent)
{
answerToThePower=answerToThePower * base;
count++;
}
return answerToThePower;
}

int bases      [] = {2,3,6,9,4,2};
int exponents []  = {7,5,3,2,3,3};
int operations [] = {0,0,1,2,0,2};

int main()
{
int total=0;
int termindex=0;
while (termindex < 6)
{
// calculate the next term value
int TermValue = raiseToThePower(bases[termindex],exponents[termindex]);

total = determineOperations(operations[termindex],total,TermValue);
termindex++;
}
std::cout << total;
}