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;
}
}
Wednesday, November 27, 2013
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.
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;
}
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;
}
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;
}
Wednesday, October 30, 2013
Assembly Town
Now we're going to go farther into the "Leave no trace rule".You know my last program? Well yeah it was good but there a few spots where we aren't cleaning up after ourselves but it doesn't affect our program. So what? I'll tell you what we aren't following the "Leave no trace rule". So In this program you are gonna see a lot of pushes and pops. Why? Because we push values onto the stack to save it and then we pop the values back into the registers to restore them. Well most of them anyway. The only ones that we don't push or pop are the return values (outputs). Which basically means that if there's a register that's supposed to change like on determineOperations ebx comes in as the current total and comes out as the new total so you don't push or pop ebx on determineOperations same thing with eax on raiseToThePower. Now I have just a little comment about the pushes and pops they follow LIFO (last in,first out) so we're going to pop in the opposite order we push which means if we say push eax,and then we say push ebx then we have to say pop ebx,and then we say pop eax.
Another thing we need is documentation,documentation is when you put a semi-colon on a blank line or off to the side of a line and type what you are doing there. But when you have documentation you have to make sure you follow it or else your going to have a lot of confusion so if I were you I'd update my code to follow my documentation. But one thing I want to tell you about. Once you change one procedure you have to make sure the other procedures follow it so that the program is going crazy and throwing random numbers at you. And another thing you'll want to do is put white space (blank lines) in between the different parts of the program that do different things and then put documentation above them. Now documentation doesn't hurt your program unless you forget to put a semi-colon at the front of line.
For example:
raiseToThePower proc
;inputs:
; ecx->current base
; ebx->current exponent
;output:
; eax->answer to the power
So you see how I have the word inputs then I put ecx->current base well the arrow points to the thing that the register is carrying in if it's an input or carrying out if it's an output (get it in-put out-put).
So now we are going to talk about a new word.......abstraction. Abstraction means that we don't care about the details only the important stuff. For example: we don't need to memorize every cog (line of code) in the factory (procedure) unless we're running that factory. So now our code has turned into a business doit prepares the ingredients ships them off to raiseToThePower industries raiseToThePower works with them then sends the output to determineOperations co. determineOperations modifies it then sends it off to doit then it starts all over again.
Now one more thing I want to talk about with you. You know the push and pop thing? Well I have a question about it. Since determine operations has multiple parts should we put the pops after every one of them? To that I say HA! Because of EVIL DR. REDUNDANCY! We can't have him around here so since there's a return at the end of each part we should change it to a jump and do the pops there and put the return at the end of that.
But do you know what the craziest thing about this whole thing is?.........DENDEDEDEN WE DON'T NEED TO CHANGE THE CHART AT ALL!
Now here's my code:
.model flat, c
.stack 100h
.data
bases dword 2,3,6,9,4,2
exponents dword 7,5,3,2,3,3
operations dword 0,0,1,2,0,2
total dword 0
.code
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
;inputs:
; operation -> eax
; current total -> ebx
; term value -> ecx
;output:
; new total -> ebx
determineOperations proc
; See which operation we need to perform
push eax
push ecx
cmp eax,0
je Addition
cmp eax,1
je Subtraction
cmp eax,2
je Multiplication
ret
Multiplication:
mov eax,ebx ; Move current total to the accumulator
mul ecx ; Multiply the term value against the current total
mov ebx,eax ; Move the new total back to the return register (ebx)
jmp popland
Subtraction:
sub ebx,ecx
jmp popland
Addition:
add ebx,ecx
jmp popland
Popland:
pop ecx
pop eax
ret
determineOperations endp
; inputs:
; ecx -> current base
; ebx -> current exponent
; output:
; eax -> answer to the power
raiseToThePower proc
push ebp
push edx
push ebx
push ecx
sub esp,4 ; Allocating 4 bytes on the stack for count
mov ebp,esp
mov dword ptr [ebp],0 ; Initializing count to zero
mov eax,1 ; Start with base^0
again:
cmp dword ptr [ebp],ebx
je weAreDone
mul ecx ; Raise to the next power
inc dword ptr [ebp]
jmp again
weAreDone:
mov ebx,eax
add esp,4
pop ecx
pop ebx
pop edx
pop ebp
ret
raiseToThePower endp
end
Another thing we need is documentation,documentation is when you put a semi-colon on a blank line or off to the side of a line and type what you are doing there. But when you have documentation you have to make sure you follow it or else your going to have a lot of confusion so if I were you I'd update my code to follow my documentation. But one thing I want to tell you about. Once you change one procedure you have to make sure the other procedures follow it so that the program is going crazy and throwing random numbers at you. And another thing you'll want to do is put white space (blank lines) in between the different parts of the program that do different things and then put documentation above them. Now documentation doesn't hurt your program unless you forget to put a semi-colon at the front of line.
For example:
raiseToThePower proc
;inputs:
; ecx->current base
; ebx->current exponent
;output:
; eax->answer to the power
So you see how I have the word inputs then I put ecx->current base well the arrow points to the thing that the register is carrying in if it's an input or carrying out if it's an output (get it in-put out-put).
So now we are going to talk about a new word.......abstraction. Abstraction means that we don't care about the details only the important stuff. For example: we don't need to memorize every cog (line of code) in the factory (procedure) unless we're running that factory. So now our code has turned into a business doit prepares the ingredients ships them off to raiseToThePower industries raiseToThePower works with them then sends the output to determineOperations co. determineOperations modifies it then sends it off to doit then it starts all over again.
Now one more thing I want to talk about with you. You know the push and pop thing? Well I have a question about it. Since determine operations has multiple parts should we put the pops after every one of them? To that I say HA! Because of EVIL DR. REDUNDANCY! We can't have him around here so since there's a return at the end of each part we should change it to a jump and do the pops there and put the return at the end of that.
But do you know what the craziest thing about this whole thing is?.........DENDEDEDEN WE DON'T NEED TO CHANGE THE CHART AT ALL!
Now here's my code:
.model flat, c
.stack 100h
.data
bases dword 2,3,6,9,4,2
exponents dword 7,5,3,2,3,3
operations dword 0,0,1,2,0,2
total dword 0
.code
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
;inputs:
; operation -> eax
; current total -> ebx
; term value -> ecx
;output:
; new total -> ebx
determineOperations proc
; See which operation we need to perform
push eax
push ecx
cmp eax,0
je Addition
cmp eax,1
je Subtraction
cmp eax,2
je Multiplication
ret
Multiplication:
mov eax,ebx ; Move current total to the accumulator
mul ecx ; Multiply the term value against the current total
mov ebx,eax ; Move the new total back to the return register (ebx)
jmp popland
Subtraction:
sub ebx,ecx
jmp popland
Addition:
add ebx,ecx
jmp popland
Popland:
pop ecx
pop eax
ret
determineOperations endp
; inputs:
; ecx -> current base
; ebx -> current exponent
; output:
; eax -> answer to the power
raiseToThePower proc
push ebp
push edx
push ebx
push ecx
sub esp,4 ; Allocating 4 bytes on the stack for count
mov ebp,esp
mov dword ptr [ebp],0 ; Initializing count to zero
mov eax,1 ; Start with base^0
again:
cmp dword ptr [ebp],ebx
je weAreDone
mul ecx ; Raise to the next power
inc dword ptr [ebp]
jmp again
weAreDone:
mov ebx,eax
add esp,4
pop ecx
pop ebx
pop edx
pop ebp
ret
raiseToThePower endp
end
Tuesday, October 15, 2013
GET YOUR HANDS OFF MY STUFF!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
On this post we're going to talk more into privacy of the separate procedures. you know count and termindex? Well raisetothepower is the only procedure that uses count and doit and determineoperations are the only ones that use termindex. So why should they be in global scope (.data)? the answer is they shouldn't. So how are we going to make count invisible to doit and determineoperations but not to raisetothepower,and termindex invisible to raisetothepower but not to doit and determineoperations? Well 1st I need to introduce you to the 3 sections of ram: .code,data,and stack. But which one will we need? The answer is................
STACK
Yes stack is the one that can help us because we have esp,and ebp and we have tons of room in stack. The way we can access the stack is with ebp because that's what it's made for accessing into other sections of memory. So it's simple to access the stack all we need to do is say mov ebp,esp. But wait little red flag coming up if it's at the top of the stack it's important right so we should swim through it not over it (hee hee hee Nemo) and how we do that is we say sub esp,4 (each spot in ram is 4 bytes apart and 4 bytes is just enough room so this is our new top of the stack.) because we don't wanna mess with those jellyfish (heehee) or stomp on our ret value that will also be held in ram because it will be located at the top of the stack and if we don't update the stack pointer to a different location the instruction pointer (eip) will have the value of termindex and eip will take us off into neverneverland when we return, thus it's critical that we update the stack pointer because each procedure should be able to assume that the stack pointer is pointing to the top of the stack,so now that we have a spot that we can do whatever we want we can get going on using it as a spot for count.
remember we're trying to make each procedure as independent from each other as possible
Now we gotta talk about what I call the "Every man for himself"rule. It's basically stating that the procedures must be as independent from each other as possible so we need to make sure that doit, determineoperations, & raiseToThePower are getting as little help from each other as possible which means that they need to manage by themselves. So how are we going to do that?Well we need to talk about the "Leave no trace"rule. It means that if raiseToThePower wants to use the stack pointer and ebp sure it can use them BUT only as long as it sets them back to where they originally were.
Here's my code:
.model flat, c
.stack 100h
.data
total dword 0
bases dword 2,3,6,9,4,2
exponents dword 7,5,3,2,3,3
operations dword 0,0,1,2,0,2
.code
doit proc
; ecx will get the base ebx will get the exponent and the program will run all the way through
; when we get back to doit we will start over again
sub esp,4
mov ebp,esp
mov dword ptr [ebp],0
; inc may be in the wrong spot,or be inc the wrong thing because it should be inc termindex
restart:
mov eax,4
mul dword ptr [ebp]
mov ebx,eax
mov ecx,bases[ebx]
mov ebx,exponents[ebx]
call raiseToThePower
call determineOperations
inc dword ptr [ebp]
cmp dword ptr [ebp],6
jl restart
add esp,4
ret
doit endp
;inputs:
; termindex
;output:
; total will have the current total
determineOperations proc
mov ebx,eax
mov eax,4
mul dword ptr [ebp]
cmp operations[eax],0
je Addition
cmp operations[eax],1
je Subtraction
cmp operations[eax],2
je Multiplication
ret
Multiplication:
mov eax,total
mul ebx
mov total,eax
ret
Subtraction:
sub total,ebx
ret
Addition:
add total,ebx
ret
determineOperations endp
; inputs:
; ecx -> current base
; ebx ->current exponent
; output:
; eax ->answer to the power
raiseToThePower proc
push dword ptr [ebp]
sub esp,4
mov ebp,esp
mov dword ptr [ebp],0
mov eax,1
again:
cmp dword ptr [ebp],ebx
je weAreDone
mul ecx
inc dword ptr [ebp]
jmp again
weAreDone:
add esp,4
pop dword ptr [ebp]
ret
raiseToThePower endp
end
So what's different about this program and other programs that we've done so far? Well at the top of raiseToThePower we have a push to save the value of ebp to the top of the stack and a pop at the end to restore it and lots of various changes that I would advise you to look for. WELL that has been the end of this post so good-bye now see ya!
STACK
Yes stack is the one that can help us because we have esp,and ebp and we have tons of room in stack. The way we can access the stack is with ebp because that's what it's made for accessing into other sections of memory. So it's simple to access the stack all we need to do is say mov ebp,esp. But wait little red flag coming up if it's at the top of the stack it's important right so we should swim through it not over it (hee hee hee Nemo) and how we do that is we say sub esp,4 (each spot in ram is 4 bytes apart and 4 bytes is just enough room so this is our new top of the stack.) because we don't wanna mess with those jellyfish (heehee) or stomp on our ret value that will also be held in ram because it will be located at the top of the stack and if we don't update the stack pointer to a different location the instruction pointer (eip) will have the value of termindex and eip will take us off into neverneverland when we return, thus it's critical that we update the stack pointer because each procedure should be able to assume that the stack pointer is pointing to the top of the stack,so now that we have a spot that we can do whatever we want we can get going on using it as a spot for count.
remember we're trying to make each procedure as independent from each other as possible
Now we gotta talk about what I call the "Every man for himself"rule. It's basically stating that the procedures must be as independent from each other as possible so we need to make sure that doit, determineoperations, & raiseToThePower are getting as little help from each other as possible which means that they need to manage by themselves. So how are we going to do that?Well we need to talk about the "Leave no trace"rule. It means that if raiseToThePower wants to use the stack pointer and ebp sure it can use them BUT only as long as it sets them back to where they originally were.
Here's my code:
.model flat, c
.stack 100h
.data
total dword 0
bases dword 2,3,6,9,4,2
exponents dword 7,5,3,2,3,3
operations dword 0,0,1,2,0,2
.code
doit proc
; ecx will get the base ebx will get the exponent and the program will run all the way through
; when we get back to doit we will start over again
sub esp,4
mov ebp,esp
mov dword ptr [ebp],0
; inc may be in the wrong spot,or be inc the wrong thing because it should be inc termindex
restart:
mov eax,4
mul dword ptr [ebp]
mov ebx,eax
mov ecx,bases[ebx]
mov ebx,exponents[ebx]
call raiseToThePower
call determineOperations
inc dword ptr [ebp]
cmp dword ptr [ebp],6
jl restart
add esp,4
ret
doit endp
;inputs:
; termindex
;output:
; total will have the current total
determineOperations proc
mov ebx,eax
mov eax,4
mul dword ptr [ebp]
cmp operations[eax],0
je Addition
cmp operations[eax],1
je Subtraction
cmp operations[eax],2
je Multiplication
ret
Multiplication:
mov eax,total
mul ebx
mov total,eax
ret
Subtraction:
sub total,ebx
ret
Addition:
add total,ebx
ret
determineOperations endp
; inputs:
; ecx -> current base
; ebx ->current exponent
; output:
; eax ->answer to the power
raiseToThePower proc
push dword ptr [ebp]
sub esp,4
mov ebp,esp
mov dword ptr [ebp],0
mov eax,1
again:
cmp dword ptr [ebp],ebx
je weAreDone
mul ecx
inc dword ptr [ebp]
jmp again
weAreDone:
add esp,4
pop dword ptr [ebp]
ret
raiseToThePower endp
end
So what's different about this program and other programs that we've done so far? Well at the top of raiseToThePower we have a push to save the value of ebp to the top of the stack and a pop at the end to restore it and lots of various changes that I would advise you to look for. WELL that has been the end of this post so good-bye now see ya!
Wednesday, September 25, 2013
The pattern destroying procedure
On this post we're gonna learn about some stuff a lot like what we learned on the previous post. (You should read the previous post before you read this post.) 1st we'll start with the way that we switch between the different operations. Before we were just doing a ton of addition but now we're gonna do some multiplication and subtraction too.
Here is the problem we're trying to solve:
0+2^7+3^5-6^3*9^2+4^3*2^3
And you notice how there isn't really a pattern like on other programs? Well because of that we have to describe the pattern using memory. This is a data driven approach because the data is memory so instead of using a pattern to do the problem we use memory (ram) to do the problem.
You remember how we did the termindex thing on the previous post? Well that's what we're gonna be doing a lot of so you better remember it! (by the way you might wanna have some paper handy.)On the previous post on our program we used termindex to offset R.A.M to get the bases and exponents and we have to multiply termindex by 4 because the different numbers are 4 bytes apart and to get to the next number on the next time around we have to inc termindex so when we multiply by 4 we get bigger numbers to get to the numbers that are further in the program. That's how we're going to get the numbers we need. 0,1,2,0,2 those are the numbers in operations 0=addition 1=subtraction 2=multiplication so when we termindex and get the number that we're at at the time we are in a procedure called determineOperations so we cmp the number to 0 and je to addition we cmp it to 1 and je to subtraction then we cmp it to 2 and je to multiplication.
One thing I have to tell you,if you want to do a long program like this you are gonna have to get organized. And what comes in handy there is a chart because last I checked its really hard to hold a million numbers in you're head. You'll want to keep track of the bases and the exponents,total,and hex total.
Here is my chart:
Now I'm going to talk about scope. What scope means is that you can't jl to a label outside of the procedure that your at. For example: If I put a label called restart in doit and I said jl restart in raiseToThePower I wouldn't be able to do that.And one more thing I need to talk aboutprocedures only worry about themselves they don't care for any thing else. For example:If determineOperations needed to use ebx it woudn't care if raiseToThePower had done something with it it would just take it and use it.
Here is my program:
.model flat, c
.stack 100h
.data
count dword 0
total dword 0
bases dword 2,3,6,9,4,2
exponents dword 7,5,3,2,3,3
operations dword 0,0,1,2,0,2
termIndex dword 0
.code
doit proc
restart:
mov eax,4
mul termIndex
mov ebx,eax
mov ecx,bases[ebx]
mov ebx,exponents[ebx]
call raiseToThePower
call determineOperations
inc termindex
cmp termindex,6
jl restart
ret
doit endp
determineOperations proc
mov ebx,eax
mov eax,4
mul termindex
cmp operations[eax],0
je Addition
cmp operations[eax],1
je Subtraction
cmp operations[eax],2
je Multiplication
ret
Multiplication:
mov eax,total
mul ebx
mov total,eax
ret
Subtraction:
sub total,ebx
ret
Addition:
add total,ebx
ret
determineOperations endp
; inputs: bases ecx,exponents ebx,output:eax (answer)
raiseToThePower proc
mov count,0
mov eax,1
again:
mul ecx
inc count
cmp count,ebx
jl again
ret
raiseToThePower endp
end
Here is the problem we're trying to solve:
0+2^7+3^5-6^3*9^2+4^3*2^3
And you notice how there isn't really a pattern like on other programs? Well because of that we have to describe the pattern using memory. This is a data driven approach because the data is memory so instead of using a pattern to do the problem we use memory (ram) to do the problem.
You remember how we did the termindex thing on the previous post? Well that's what we're gonna be doing a lot of so you better remember it! (by the way you might wanna have some paper handy.)On the previous post on our program we used termindex to offset R.A.M to get the bases and exponents and we have to multiply termindex by 4 because the different numbers are 4 bytes apart and to get to the next number on the next time around we have to inc termindex so when we multiply by 4 we get bigger numbers to get to the numbers that are further in the program. That's how we're going to get the numbers we need. 0,1,2,0,2 those are the numbers in operations 0=addition 1=subtraction 2=multiplication so when we termindex and get the number that we're at at the time we are in a procedure called determineOperations so we cmp the number to 0 and je to addition we cmp it to 1 and je to subtraction then we cmp it to 2 and je to multiplication.
One thing I have to tell you,if you want to do a long program like this you are gonna have to get organized. And what comes in handy there is a chart because last I checked its really hard to hold a million numbers in you're head. You'll want to keep track of the bases and the exponents,total,and hex total.
Here is my chart:
Now I'm going to talk about scope. What scope means is that you can't jl to a label outside of the procedure that your at. For example: If I put a label called restart in doit and I said jl restart in raiseToThePower I wouldn't be able to do that.And one more thing I need to talk aboutprocedures only worry about themselves they don't care for any thing else. For example:If determineOperations needed to use ebx it woudn't care if raiseToThePower had done something with it it would just take it and use it.
Here is my program:
.model flat, c
.stack 100h
.data
count dword 0
total dword 0
bases dword 2,3,6,9,4,2
exponents dword 7,5,3,2,3,3
operations dword 0,0,1,2,0,2
termIndex dword 0
.code
doit proc
restart:
mov eax,4
mul termIndex
mov ebx,eax
mov ecx,bases[ebx]
mov ebx,exponents[ebx]
call raiseToThePower
call determineOperations
inc termindex
cmp termindex,6
jl restart
ret
doit endp
determineOperations proc
mov ebx,eax
mov eax,4
mul termindex
cmp operations[eax],0
je Addition
cmp operations[eax],1
je Subtraction
cmp operations[eax],2
je Multiplication
ret
Multiplication:
mov eax,total
mul ebx
mov total,eax
ret
Subtraction:
sub total,ebx
ret
Addition:
add total,ebx
ret
determineOperations endp
; inputs: bases ecx,exponents ebx,output:eax (answer)
raiseToThePower proc
mov count,0
mov eax,1
again:
mul ecx
inc count
cmp count,ebx
jl again
ret
raiseToThePower endp
end
Thursday, September 12, 2013
PROcedures-The battle of Memoryman and Evil Dr.Redundandancy
On my previous post I told you that on this post I would show you how to deal with the redundancy,and yes I am. The first thing we gotta do is make 3 more pieces of R.AM and we'll label them bases,exponents and termindex. The next thing we do is put these numbers 2,3,6,9,4 (make sure you put comma's in between the numbers)and these numbers in exponents 7,5,3,2,3 and a 0 in termindex example:
bases dword 2,3,6,9,4
exponents dword 7,5,3,2,3
termindex dword 0
P.S don't forget to put count and total in.
Now I'm going to talk about a new word............consecutive. Consecutive means things come right after each other. You notice that in bases and exponents there are numbers just all together in a line? Well how consecutive go's in with this is that the 1st number is in the 1st 4 bytes and the next number is in the next 4 bytes so on so on. Her'es my program that uses memory to get rid of the redundancy and simplify the process.
.model flat, c
.stack 100h
.data
count dword 0
total dword 0
bases dword 2,3,6,9,4
exponents dword 7,5,3,2,3
termIndex dword 0
.code
doit proc
restart:
mov eax,4
mul termIndex
mov ebx,eax
mov ecx,bases[ebx]
mov ebx,exponents[ebx]
call raiseToThePower
add total,eax
inc termIndex
cmp termIndex,5
jl restart
ret
doit endp
raiseToThePower proc
mov count,0
mov eax,1
again:
mul ecx
inc count
cmp count,ebx
jl again
ret
raiseToThePower endp
end
Now I'm going to explain how this program is running through. Well the first few lines are what I'm going to talk about first (because they're the FIRST few lines),you see there's mov eax,4 then mul termindex,and what that's doing is there are 4 bytes in between the different numbers so there there needs to be a 4 in termindex at 1st nothing happens because termindex is a 0 and the first 2 numbers are right there but you see how there's an inc termindex at the end of the doit procedure? Well that means that termindex will be a 1 so when we come around to the beginning of the loop it does that again and walla! We skip 4 bytes to the next number.
So you see how the numbers go down in a row? The top 5 numbers are the bases and the next 5 are the exponents. And you see how there are 3 sets of 0's (bytes) before the next number? Well the number counts as 1 so all together that makes 4 bytes.
Now I'm going to talk about something called byteswapping. What byteswapping is is the way memory show's number's. It shows the numbers backward's. The reason for that is because of the way memory uses big endian and little endian. When you use big endian you store the most significant byte in the smallest address. When you use little endian it's the other way around you store the LEAST significant value in the smallest address.
If you want to learn more go to this address: http://www.cs.umd.edu/class/sum2003/cmsc311/Notes/Data/endian.html
Have you ever heard of an alias? It's like a fake name,example: You know how Dr.Seuss puts the name Theo lesieg on his books? That's an alias. I bet your wondering what does any of this have to do with what we're doing? Well I'll answer that question. You know these names that we're using for R.A.M such as termindex and count? They're aliases for ram addresses. But you know how bases and exponents have several numbers? The first number is the only one with an exact alias so to get to the other numbers you need to termindex into them.
bases dword 2,3,6,9,4
exponents dword 7,5,3,2,3
termindex dword 0
P.S don't forget to put count and total in.
Now I'm going to talk about a new word............consecutive. Consecutive means things come right after each other. You notice that in bases and exponents there are numbers just all together in a line? Well how consecutive go's in with this is that the 1st number is in the 1st 4 bytes and the next number is in the next 4 bytes so on so on. Her'es my program that uses memory to get rid of the redundancy and simplify the process.
.model flat, c
.stack 100h
.data
count dword 0
total dword 0
bases dword 2,3,6,9,4
exponents dword 7,5,3,2,3
termIndex dword 0
.code
doit proc
restart:
mov eax,4
mul termIndex
mov ebx,eax
mov ecx,bases[ebx]
mov ebx,exponents[ebx]
call raiseToThePower
add total,eax
inc termIndex
cmp termIndex,5
jl restart
ret
doit endp
raiseToThePower proc
mov count,0
mov eax,1
again:
mul ecx
inc count
cmp count,ebx
jl again
ret
raiseToThePower endp
end
Now I'm going to explain how this program is running through. Well the first few lines are what I'm going to talk about first (because they're the FIRST few lines),you see there's mov eax,4 then mul termindex,and what that's doing is there are 4 bytes in between the different numbers so there there needs to be a 4 in termindex at 1st nothing happens because termindex is a 0 and the first 2 numbers are right there but you see how there's an inc termindex at the end of the doit procedure? Well that means that termindex will be a 1 so when we come around to the beginning of the loop it does that again and walla! We skip 4 bytes to the next number.
So you see how the numbers go down in a row? The top 5 numbers are the bases and the next 5 are the exponents. And you see how there are 3 sets of 0's (bytes) before the next number? Well the number counts as 1 so all together that makes 4 bytes.
Now I'm going to talk about something called byteswapping. What byteswapping is is the way memory show's number's. It shows the numbers backward's. The reason for that is because of the way memory uses big endian and little endian. When you use big endian you store the most significant byte in the smallest address. When you use little endian it's the other way around you store the LEAST significant value in the smallest address.
If you want to learn more go to this address: http://www.cs.umd.edu/class/sum2003/cmsc311/Notes/Data/endian.html
Have you ever heard of an alias? It's like a fake name,example: You know how Dr.Seuss puts the name Theo lesieg on his books? That's an alias. I bet your wondering what does any of this have to do with what we're doing? Well I'll answer that question. You know these names that we're using for R.A.M such as termindex and count? They're aliases for ram addresses. But you know how bases and exponents have several numbers? The first number is the only one with an exact alias so to get to the other numbers you need to termindex into them.
Tuesday, September 10, 2013
PROcedures-The warning
On my previous post about procedures I showed you how to do several different operations or in other words a very long problem. Well there was a big problem with that..........REDUNDANCY!(see below)
mov ecx,3
mov ebx,4
call raiseToThePower
add total,eax
mov ecx,2
mov ebx,7
call raiseToThePower
add total,eax
Now the reason these 2 sections are redundant is because they are very similar,because if you look at it it all makes sense,both sections have 2 mov's then a call and last but certainly not least an add. The only things that are different between them are the numbers that are being moved,the 1st one has 3,and 4 and the 2nd one has 2,and 7.Now this equation isn't pretty but it get's worse when you do a program and you have several numbers so it's like evil Dr. Redundancy right there. Example:
mov ecx,2
mov ebx,7
call raiseToThePower
add total,eax
mov ecx,3
mov ebx,5
call raiseToThePower
add total,eax
mov ecx,6
mov ebx,3
call raiseToThePower
add total,eax
mov ecx,9 1
mov ebx,2
call raiseToThePower
add total,eax
The problem we're trying to solve is 2^7+3^5+6^3+9^2. But look at all that redundant code!!!!!(I've highlighted the redundant code in different colors.)On my next post I'll show you how to fix this using arrays.
mov ecx,3
mov ebx,4
call raiseToThePower
add total,eax
mov ecx,2
mov ebx,7
call raiseToThePower
add total,eax
Now the reason these 2 sections are redundant is because they are very similar,because if you look at it it all makes sense,both sections have 2 mov's then a call and last but certainly not least an add. The only things that are different between them are the numbers that are being moved,the 1st one has 3,and 4 and the 2nd one has 2,and 7.Now this equation isn't pretty but it get's worse when you do a program and you have several numbers so it's like evil Dr. Redundancy right there. Example:
mov ecx,2
mov ebx,7
call raiseToThePower
add total,eax
mov ecx,3
mov ebx,5
call raiseToThePower
add total,eax
mov ecx,6
mov ebx,3
call raiseToThePower
add total,eax
mov ecx,9 1
mov ebx,2
call raiseToThePower
add total,eax
The problem we're trying to solve is 2^7+3^5+6^3+9^2. But look at all that redundant code!!!!!(I've highlighted the redundant code in different colors.)On my next post I'll show you how to fix this using arrays.
Thursday, September 5, 2013
PROcedures-The great switcheroo
Note to reader: if you haven't read my post called PROcedures you should read it before you read this post.
On my previous post about procedures I told you what a procedure is and what they do, on this post I'm going to show you something about them that allows you to use the same procedure to do 2,3,4,5,6 etc things it just depends on how much code you are willing to write,and sadly loops can't help with this,on my program I just did 2. Now I'm not saying you can do like you can do subtraction and addition in fact the "things" that I'm talking about are powers like: 3^3 + 2^4. Now I'm going to talk about input and output. So all an input is is a number so look at 3^3 the 3's are input and the answer (27) is the output. Example:if you put 2 different types of materials such as wool or thread into a sweater machine they come out as a sweater. Or 2^4 7^8 or even 10^9.
.model flat, c
.stack 100h
.data
count dword 0
total dword 0
.code
doit proc
mov ecx,3
mov ebx,4
call raiseToThePower
add total,eax
mov ecx,2
mov ebx,7
call raiseToThePower
add total,eax
ret
doit endp
raiseToThePower proc
mov count,0
mov eax,1
again:
mul ecx
inc count
cmp count,ebx
jl again
ret
raiseToThePower endp
end
Now we get to the part I've been talking about: the part where you switch between the 2 different powers! If you look at the top part of the program you will see that I'm calling the raiseToThePower proc twice and in between those calls I'm doing some mov's. The only thing I'm changing with those mov's is the base (ecx) and the exponent (ebx). Now ebx and ecx are the input's that we've been talking so much about. And That's all there is to it really in between the call's change the base and the exponent.
On my previous post about procedures I told you what a procedure is and what they do, on this post I'm going to show you something about them that allows you to use the same procedure to do 2,3,4,5,6 etc things it just depends on how much code you are willing to write,and sadly loops can't help with this,on my program I just did 2. Now I'm not saying you can do like you can do subtraction and addition in fact the "things" that I'm talking about are powers like: 3^3 + 2^4. Now I'm going to talk about input and output. So all an input is is a number so look at 3^3 the 3's are input and the answer (27) is the output. Example:if you put 2 different types of materials such as wool or thread into a sweater machine they come out as a sweater. Or 2^4 7^8 or even 10^9.
.model flat, c
.stack 100h
.data
count dword 0
total dword 0
.code
doit proc
mov ecx,3
mov ebx,4
call raiseToThePower
add total,eax
mov ecx,2
mov ebx,7
call raiseToThePower
add total,eax
ret
doit endp
raiseToThePower proc
mov count,0
mov eax,1
again:
mul ecx
inc count
cmp count,ebx
jl again
ret
raiseToThePower endp
end
Now we get to the part I've been talking about: the part where you switch between the 2 different powers! If you look at the top part of the program you will see that I'm calling the raiseToThePower proc twice and in between those calls I'm doing some mov's. The only thing I'm changing with those mov's is the base (ecx) and the exponent (ebx). Now ebx and ecx are the input's that we've been talking so much about. And That's all there is to it really in between the call's change the base and the exponent.
Thursday, August 29, 2013
Congruence-Numbers that are same, but not equal?
On this post I'm going show you how to do multiple operations on a program that involves powers. Also I'm going to show you how to switch between the different operations such as: +,/,%,and *.
Here is the problem we're trying to solve:
Look carefully at the problem and notice that there's several operations but they are still in a pattern. If you can't see it very well the pattern goes +,+,*,/,%. Now I'm going to talk about the symbol %. If your'e good at division this shouldn't be too hard to understand. That symbol stands for what we call mod (short for modulus). If your'e moding something all your'e doing is dividing it by a number except you don't show the answer you show the remainder. If your'e reading this you probably know what I mean by the remainder,but if you don't I'll tell you. Sometimes you can't divide some thing without having a few left. The remainder is the number that's left. For example: 5 % 3=2.
Here's my program:
.model flat, c
.stack 100h
.data
powerof3 dword 1
count dword 0
five dword 5
.code
doit proc
mov ecx, 3
mov ebx, 1
again:
call calculateNextPower
;Determine the next operation
mov eax,count
xor edx,edx
div five
cmp edx,0
je addition
cmp edx,1
je addition
cmp edx,2
je multiplication
cmp edx,3
je division
cmp edx,4
je modulus
multiplication:
; Multiplying the power of 3 and the sum
mov eax,powerof3
mul ebx
mov ebx,eax
jmp hop
addition:
; adding the sum and the power of 3
add ebx,powerof3
jmp hop
division:
xor edx,edx
mov eax,ebx
div powerof3
mov ebx,eax
jmp hop
modulus:
xor edx,edx
mov eax,ebx
div powerof3
mov ebx,edx
jmp hop
hop:
; Repeat if necessary
cmp count,5
jl again
ret
doit endp
calculateNextPower proc
; Raising to the next power of 3
mov eax,powerof3
mul ecx
mov powerof3,eax
inc count
ret
calculatenextpower endp
end
If you observe the top parts of the program do you notice how there are a lot of cmps? That part is how we switch between the different operations. It's actually best described as a large modulus. First you divide count by 5(count is the register that we use to count up on the program)and the remainder is placed in edx(by the way you have to make sure edx is all zeroed out because it's gotta be ready to hold the remainder). Then you cmp edx to 0 and you je to addition and if it dosen't jump you cmp it to 1 and je to addition (because there are 2 additions in the pattern) and if it still doesn't jump then you cmp it to 2 and je to multiplication and if it still doesn't jump then you cmp it to 3 and je to division and if it doesn't jump then you cmp it to 4 and you je to modulus and if it doesn't jump by then you got something wrong.
So as I said it's like a giant modulus and we're moding by 5 so when the power get's to 5 the pattern starts all over again.
Now I'm going to talk about congruence. Congruence is something that goes with modulus. Look at this:
0 % 3= 0
1 % 3= 1
2 % 3= 2
3 % 3= 0
4 % 3= 1
5 % 3= 2
6 % 3= 0
7 % 3= 1
8 % 3= 2
Now if you look at the example above, do you notice that the remainders (answers to the problem are not in here because we look at the remainder when we mod) are in a pattern 0,1,2? Well the answers are CONGRUENT to the number that is being moded, for example:0 is congruent to 3, and 6 because they have the same remainder which is 0. 1 is congruent to 4,and 7 because they have the same remainder which is 1. 2 is congruent to 5,and 8 because they have the same remainder which is 2.
This program works, and the way I can tell is it follows along with my chart as I debug it.
Here is the problem we're trying to solve:
Look carefully at the problem and notice that there's several operations but they are still in a pattern. If you can't see it very well the pattern goes +,+,*,/,%. Now I'm going to talk about the symbol %. If your'e good at division this shouldn't be too hard to understand. That symbol stands for what we call mod (short for modulus). If your'e moding something all your'e doing is dividing it by a number except you don't show the answer you show the remainder. If your'e reading this you probably know what I mean by the remainder,but if you don't I'll tell you. Sometimes you can't divide some thing without having a few left. The remainder is the number that's left. For example: 5 % 3=2.
Here's my program:
.model flat, c
.stack 100h
.data
powerof3 dword 1
count dword 0
five dword 5
.code
doit proc
mov ecx, 3
mov ebx, 1
again:
call calculateNextPower
;Determine the next operation
mov eax,count
xor edx,edx
div five
cmp edx,0
je addition
cmp edx,1
je addition
cmp edx,2
je multiplication
cmp edx,3
je division
cmp edx,4
je modulus
multiplication:
; Multiplying the power of 3 and the sum
mov eax,powerof3
mul ebx
mov ebx,eax
jmp hop
addition:
; adding the sum and the power of 3
add ebx,powerof3
jmp hop
division:
xor edx,edx
mov eax,ebx
div powerof3
mov ebx,eax
jmp hop
modulus:
xor edx,edx
mov eax,ebx
div powerof3
mov ebx,edx
jmp hop
hop:
; Repeat if necessary
cmp count,5
jl again
ret
doit endp
calculateNextPower proc
; Raising to the next power of 3
mov eax,powerof3
mul ecx
mov powerof3,eax
inc count
ret
calculatenextpower endp
end
If you observe the top parts of the program do you notice how there are a lot of cmps? That part is how we switch between the different operations. It's actually best described as a large modulus. First you divide count by 5(count is the register that we use to count up on the program)and the remainder is placed in edx(by the way you have to make sure edx is all zeroed out because it's gotta be ready to hold the remainder). Then you cmp edx to 0 and you je to addition and if it dosen't jump you cmp it to 1 and je to addition (because there are 2 additions in the pattern) and if it still doesn't jump then you cmp it to 2 and je to multiplication and if it still doesn't jump then you cmp it to 3 and je to division and if it doesn't jump then you cmp it to 4 and you je to modulus and if it doesn't jump by then you got something wrong.
So as I said it's like a giant modulus and we're moding by 5 so when the power get's to 5 the pattern starts all over again.
Now I'm going to talk about congruence. Congruence is something that goes with modulus. Look at this:
0 % 3= 0
1 % 3= 1
2 % 3= 2
3 % 3= 0
4 % 3= 1
5 % 3= 2
6 % 3= 0
7 % 3= 1
8 % 3= 2
Now if you look at the example above, do you notice that the remainders (answers to the problem are not in here because we look at the remainder when we mod) are in a pattern 0,1,2? Well the answers are CONGRUENT to the number that is being moded, for example:0 is congruent to 3, and 6 because they have the same remainder which is 0. 1 is congruent to 4,and 7 because they have the same remainder which is 1. 2 is congruent to 5,and 8 because they have the same remainder which is 2.
This program works, and the way I can tell is it follows along with my chart as I debug it.
Wednesday, August 21, 2013
What do you do if you wanna be true?
In my previous post about powers there was an error because we could only do even powers because we would raise the power twice per loop. Well in this post I'm going to show you a program that you can do any power you want because it only raises the power of 3 once. (if you haven't read my post called the powers you should read it before you read this post.) The way this will work is you divide count by 2 and you don't need to worry about what the answer will be because what we really care about is the remainder which will be in edx. We compare edx to 1 and if it is = to 1 we je to the multiplication and if it is less than we jl to the addition part. And I advise you that one teeny tiny mistake can throw off the whole program but that's no reason to race through the program and think there's a problem when there's really nothing wrong. (that's the mistake I made.) There are a few ways you can see a fake problem, here I'll list them for you: looking at the wrong thing and thinking it's something else,and getting mixed up with names. And there's one more thing dividing is just like multiplying because you can't use immediate values and you can't type the name of the implied register (eax) in the instruction.
.model flat, c
.stack 100h
.data
powerof3 dword 1
count dword 0
two dword 2
.code
doit proc
mov ecx, 3
mov ebx, 1
again:
call calculateNextPower
mov eax,count
xor edx
div two
cmp edx,1
je multiplication
jl addition
multiplication:
; Multiplying the power of 3 and the sum
mov eax,powerof3
mul ebx
mov ebx,eax
jmp hop
addition:
; adding the sum and the power of 3
add ebx,powerof3
hop:
; Repeat if neccesary
cmp count,5
jl again
ret
doit endp
calculateNextPower proc
; Raising to the next power of 3
mov eax,powerof3
mul ecx
mov powerof3,eax
inc count
ret
calculatenextpower endp
end
.model flat, c
.stack 100h
.data
powerof3 dword 1
count dword 0
two dword 2
.code
doit proc
mov ecx, 3
mov ebx, 1
again:
call calculateNextPower
mov eax,count
xor edx
div two
cmp edx,1
je multiplication
jl addition
multiplication:
; Multiplying the power of 3 and the sum
mov eax,powerof3
mul ebx
mov ebx,eax
jmp hop
addition:
; adding the sum and the power of 3
add ebx,powerof3
hop:
; Repeat if neccesary
cmp count,5
jl again
ret
doit endp
calculateNextPower proc
; Raising to the next power of 3
mov eax,powerof3
mul ecx
mov powerof3,eax
inc count
ret
calculatenextpower endp
end
Monday, August 19, 2013
PROcedures
Now I'm going to talk to you about procedures. Procedures are certain pieces of code that are labeled specially. Take this example: a procedure is like a kingdom or country of it's own. Procedures can help you with what we call redundancy. Redundancy is when you have 2 pieces of code that are exactly alike so when you make a change to 1 of them you have to remember to make the same change to the other 1 and that's just such a headache!
So do you remember that program I did in my post called The powers? Well if you haven't read it yet you should before you read the rest of this post. So if you have read it do you remember how we had to raise to the next power of 3 and we did it twice? That's redundancy. Now look at my program below and notice the word proc. That stands for procedure.
.model flat, c
.stack 100h
.data
powerof3 dword 1
count dword 0
.code
doit proc
mov ecx, 3
mov ebx, 1
again:
call calculateNextPower
; Multiplying the power of 3 and the sum
mov eax,powerof3
mul ebx
mov ebx,eax
call calculateNextPower
; adding the sum and the power of 3
add ebx,powerof3
; Repeat if neccesary
cmp count,5
jl again
ret
doit endp
calculateNextPower proc
; Raising to the next power of 3
mov eax,powerof3
mul ecx
mov powerof3,eax
inc count
ret
calculatenextpower endp
end
So do you remember that program I did in my post called The powers? Well if you haven't read it yet you should before you read the rest of this post. So if you have read it do you remember how we had to raise to the next power of 3 and we did it twice? That's redundancy. Now look at my program below and notice the word proc. That stands for procedure.
.model flat, c
.stack 100h
.data
powerof3 dword 1
count dword 0
.code
doit proc
mov ecx, 3
mov ebx, 1
again:
call calculateNextPower
; Multiplying the power of 3 and the sum
mov eax,powerof3
mul ebx
mov ebx,eax
call calculateNextPower
; adding the sum and the power of 3
add ebx,powerof3
; Repeat if neccesary
cmp count,5
jl again
ret
doit endp
calculateNextPower proc
; Raising to the next power of 3
mov eax,powerof3
mul ecx
mov powerof3,eax
inc count
ret
calculatenextpower endp
end
How this works is there are 2 procedures and there is something new, if you look at the program above you'll notice the word call and then calculateNextPower well if you look right above you'll see calculateNextPower proc.
When you call a location it's kind of like jl. You go to the location and then execute the code but then you get to the ret and this get's fun. You see when you do the call it moves the value of the instruction to the top of the stack and when you do the ret that's the same as saying pop eip which stands for instruction pointer so you move the value of the instruction after the call into the instruction pointer so you go back to where you came from.
Saturday, August 17, 2013
Reverso
Here's a program that stores 1,2,3,4 in the registers, and then reverses it to 4,3,2,1.
.model flat, c
.stack 100h
.data
store dword 0
.code
doit proc
mov eax,1
mov ebx,2
mov ecx,3
mov edx,4
mov store,eax
mov eax,edx
mov edx,store
mov store,ebx
mov ebx,ecx
mov ecx,store
Here's another way that you can do it except this way uses the stack.
.model flat, c
.stack 100h
.data
store dword 0
.code
doit proc
mov eax,1
mov ebx,2
mov ecx,3
mov edx,4
push eax
push ebx
push ecx
push edx
pop eax
pop ebx
pop ecx
pop edx
Now the stack is a section of R.A.M . I'm going to give you a little lesson to show you a little example of what it looks like and what it does.
Imagine your'e inside a restaurant. There is a pile of plates on a table. A neat stack if you please. This stack is an example of what we call LIFO which stands for last in, first out. This means: the last plate that gets put on the stack is the first one to get taken off.
Now that I've told you about that take a look at the program. You see how I've got the words pop and push in there? Let me tell you how that relates with the stack of plates. When I "pop" the stack that means I take a plate off the top. When I "push" the stack that means I put a plate on the top. You notice how I'm popping in the same order I'm pushing? That's what reverses the registers.
.model flat, c
.stack 100h
.data
store dword 0
.code
doit proc
mov eax,1
mov ebx,2
mov ecx,3
mov edx,4
mov store,eax
mov eax,edx
mov edx,store
mov store,ebx
mov ebx,ecx
mov ecx,store
Here's another way that you can do it except this way uses the stack.
.model flat, c
.stack 100h
.data
store dword 0
.code
doit proc
mov eax,1
mov ebx,2
mov ecx,3
mov edx,4
push eax
push ebx
push ecx
push edx
pop eax
pop ebx
pop ecx
pop edx
Now the stack is a section of R.A.M . I'm going to give you a little lesson to show you a little example of what it looks like and what it does.
Imagine your'e inside a restaurant. There is a pile of plates on a table. A neat stack if you please. This stack is an example of what we call LIFO which stands for last in, first out. This means: the last plate that gets put on the stack is the first one to get taken off.
Now that I've told you about that take a look at the program. You see how I've got the words pop and push in there? Let me tell you how that relates with the stack of plates. When I "pop" the stack that means I take a plate off the top. When I "push" the stack that means I put a plate on the top. You notice how I'm popping in the same order I'm pushing? That's what reverses the registers.
The powers
On this post I'm going to show you a program that I did with my dad to do a little adding and multiplication. This program is supposed to do this problem: 31 + 32 + 33 + ... 3n
In this program ebx tracks the SUM,and ecx tracks the base. Eax serves as a general purpose multiply. This program was challenging for me because I didn't know very much about powers.
32 = 3 x 3
33 = 3 x 3 x 3
34 = 3 x 3 x 3 x 3
35 = 3 x 3 x 3 x 3 x 3
36 = 3 x 3 x 3 x 3 x 3 x 3
32 is a short way of saying 3 x 3,33
is a short way of saying 3 x 3 x 3 etc. SUM is the total of adding the 2 powers together. If you go high enough going up power by power you will get HUGE amounts of overflow so much in fact the amount in R.A.M is nothing compared to the real answer. Sometimes when you are doing a big enough problem you have to use R.A.M because edx doesn't cooperate because when you do multiplication it tells you what you didn't use. So you gotta use R.A.M instead. If you don't know what ram is you should read my earlier blogs.
Now I'm going to tell you which registers are doing what while this is all going on. R.A.M tracks the power of 3 which is how many 3's are being multiplied. Ecx is tracking the base which is 3. Ebx is tracking the SUM or total. And as for edx it is not doing anything because as I said before edx wouldn't work. As for R.A.M it takes over for edx as the power of 3.
Here is a chart I made to track everything for each iteration:
And here's the program.
.model flat, c
.stack 100h
.data
powerof3 dword 1
count dword 0
.code
doit proc
mov ecx, 3
mov ebx, 1
again:
; Raise to the next power of 3
mov eax, powerof3
mul ecx
mov powerof3,eax
inc count
; Multiplying the power of 3 and the sum
mov eax,powerof3
mul ebx
mov ebx,eax
; Raising to the next power of 3
mov eax,powerof3
mul ecx
mov powerof3,eax
inc count
; adding the sum and the power of 3
add ebx,powerof3
; Repeat if neccesary
cmp count,5
jl again
Now I'm going to tell you which registers are doing what while this is all going on. R.A.M tracks the power of 3 which is how many 3's are being multiplied. Ecx is tracking the base which is 3. Ebx is tracking the SUM or total. And as for edx it is not doing anything because as I said before edx wouldn't work. As for R.A.M it takes over for edx as the power of 3.
Here is a chart I made to track everything for each iteration:
As you can see I have shown you what is in R.A.M,and ebx,and I have written down what ecx,eax,and edx are doing.
And here's the program.
.model flat, c
.stack 100h
.data
powerof3 dword 1
count dword 0
.code
doit proc
mov ecx, 3
mov ebx, 1
again:
; Raise to the next power of 3
mov eax, powerof3
mul ecx
mov powerof3,eax
inc count
; Multiplying the power of 3 and the sum
mov eax,powerof3
mul ebx
mov ebx,eax
; Raising to the next power of 3
mov eax,powerof3
mul ecx
mov powerof3,eax
inc count
; adding the sum and the power of 3
add ebx,powerof3
; Repeat if neccesary
cmp count,5
jl again
Thursday, August 1, 2013
The Secrets Of cmp
Sign flag and zero flag
efl is flags register
how cmp changes the flags
how the jumps analyze the state of the flag bits
what inc does to the flags, and why we can't inc after we cmp
example programs with issues:
mov eax,1
mov ebx,2
again:
inc ebx ; inc changes the state of flags due to the value of the last result
mul ebx
cmp ebx,100
jl again
; stops at 0
doit proc
mov eax, -5 ; what will be the sign and carry as we inc eax?
again:
cmp eax, 10
inc eax
jl again
ret
On this blog I'm going to talk about the sign flag and the zero flag. The sign flag and the zero flag are both in the same register and they determine whether or not you pass on when you get to the jl or the jle. Now the secret to what happens in the sign flag and the zero flag lies in cmp. Now if you don't know what cmp means you should read the post called loop de loop 1st.
All that a cmp does is a subtraction. The sign flag shows whether or not the number is negative when you subtract the number that your'e counting to from it. If it is negative the sign flag will be a 1,if it isn't the sign flag will be a 0. The zero flag shows whether or not the answer is 0. If the answer is 0 the zero flag will be a 1. If the answer isn't 0 the zero flag will be 0.
Here are some examples:
cmp 5, 6
The results would be: sign flag 1 zero flag 0
cmp 5,5
The results would be: 0 1
cmp 6,5
The results would be: 0 0
Those are the 3 possible combinations you can have with this. Now I bet your'e thinking that can't be right if there are 2 bits there should be 4 possible combinations well the one that both of them would be a 1 wouldn't be possible because the answer can't be 0 and negative at the same time.
efl is flags register
how cmp changes the flags
how the jumps analyze the state of the flag bits
what inc does to the flags, and why we can't inc after we cmp
example programs with issues:
mov eax,1
mov ebx,2
again:
inc ebx ; inc changes the state of flags due to the value of the last result
mul ebx
cmp ebx,100
jl again
; stops at 0
doit proc
mov eax, -5 ; what will be the sign and carry as we inc eax?
again:
cmp eax, 10
inc eax
jl again
ret
On this blog I'm going to talk about the sign flag and the zero flag. The sign flag and the zero flag are both in the same register and they determine whether or not you pass on when you get to the jl or the jle. Now the secret to what happens in the sign flag and the zero flag lies in cmp. Now if you don't know what cmp means you should read the post called loop de loop 1st.
All that a cmp does is a subtraction. The sign flag shows whether or not the number is negative when you subtract the number that your'e counting to from it. If it is negative the sign flag will be a 1,if it isn't the sign flag will be a 0. The zero flag shows whether or not the answer is 0. If the answer is 0 the zero flag will be a 1. If the answer isn't 0 the zero flag will be 0.
Here are some examples:
cmp 5, 6
The results would be: sign flag 1 zero flag 0
cmp 5,5
The results would be: 0 1
cmp 6,5
The results would be: 0 0
Those are the 3 possible combinations you can have with this. Now I bet your'e thinking that can't be right if there are 2 bits there should be 4 possible combinations well the one that both of them would be a 1 wouldn't be possible because the answer can't be 0 and negative at the same time.
Loop De Loop
adding 1 + 2 + 3 + 4 + 5 + 6 + 7 up to a really big number like 100, first talk about adding 1 to 5, but then you can change the 5 to a 100
inc
cmp
jl
jle
63
multiple ways to write the same program
talk about the problems that you get when you put the inc between the cmp and the jl
Write blog post down here:
Have you ever wondered what you would get if you added 1+2+3+4 etc.? Well if you have this should be a good learning experience. First you need to put a 0 in eax, then you need to put a 1 in ebx. Then you add them together and after you do that you have two choices you can move the answer into another register and put a 2 in eax and a 3 in ebx and add them together and then add that to the answer and keep moving the numbers in eax and ebx up one time and write tons of code until you reach the number you want to go to, or you can take the easy way that takes a little bit more learning but it will save you a ton of headache if you do it.
The easy way has a lot to do with something called loops. A loop is when you do little bit of code that if repeated will make a good program and that's where the little bit of learning comes in. The first thing you need to know about if you want to take the easy way is cmp which is compare. Now cmp is when you put a number in a certain piece of ram, or register and use it as a counter. To count you can do a little piece of code called inc which means increment. When you inc ram or a register it adds one to that ram or register.
So when you inc the piece of ram or register it gets bigger and when it gets to the number that you are counting to you are done, but the bit of magic that makes the program start all over again and completely save the headache there is one more thing.
The final piece of the puzzle lies in a little piece of code called jle. Now jl stands for jump less than or equal to that means if the digit in the counter is less than or equal to lets say 5 then go back to again. What I mean by again is you set a point in the program that you want to start over from. I like to call it again.
mov eax,0
mov ebx,1
again:
add eax,ebx
inc ebx
cmp ebx,5
jle again
inc
cmp
jl
jle
63
multiple ways to write the same program
talk about the problems that you get when you put the inc between the cmp and the jl
Write blog post down here:
Have you ever wondered what you would get if you added 1+2+3+4 etc.? Well if you have this should be a good learning experience. First you need to put a 0 in eax, then you need to put a 1 in ebx. Then you add them together and after you do that you have two choices you can move the answer into another register and put a 2 in eax and a 3 in ebx and add them together and then add that to the answer and keep moving the numbers in eax and ebx up one time and write tons of code until you reach the number you want to go to, or you can take the easy way that takes a little bit more learning but it will save you a ton of headache if you do it.
The easy way has a lot to do with something called loops. A loop is when you do little bit of code that if repeated will make a good program and that's where the little bit of learning comes in. The first thing you need to know about if you want to take the easy way is cmp which is compare. Now cmp is when you put a number in a certain piece of ram, or register and use it as a counter. To count you can do a little piece of code called inc which means increment. When you inc ram or a register it adds one to that ram or register.
So when you inc the piece of ram or register it gets bigger and when it gets to the number that you are counting to you are done, but the bit of magic that makes the program start all over again and completely save the headache there is one more thing.
The final piece of the puzzle lies in a little piece of code called jle. Now jl stands for jump less than or equal to that means if the digit in the counter is less than or equal to lets say 5 then go back to again. What I mean by again is you set a point in the program that you want to start over from. I like to call it again.
mov eax,0
mov ebx,1
again:
add eax,ebx
inc ebx
cmp ebx,5
jle again
Thursday, May 23, 2013
Expression Trees
On this post I'm going to teach you about expression trees. Expression trees are when you take an expression and build it up so that it looks like a tree. There are 2 types of calculator modes which build 2 different expression trees. Standard mode is when you take the numbers as soon as they appear in the problem. Scientific mode is when you be patient and make sure you pay attention to the operators and how much precedents each operator has.
This is how it looks after you've done the first collapsing. You see that the 3,4,and * are gone? That's because the way you collapse is do the numbers against there operator so that you come out with the answer .
This is what you get after you do the 2nd collapsing. This time do you see the difference? Yep the /,6, and 2 are gone because I did the same thing except I divided them instead of multiplying them.
This is what you get after the 3rd collapsing and its easy to spot the difference right? Well if you can't the 12,3,and the + are gone and there is a 15. That's because there was a + above the 12 and the 3 so I added them together.
This is what it looks like after the 4th collapsing. The difference here is very easy to spot. The 2,5,and 2nd * are gone and instead there is a 10. That's because the * was above the 2 and 5 so I multiplied them together.
; 3 * 4 + 6 / 2 + 2 * 5
mov eax,3
mov ebx,4
mul ebx ; This collapses 3 * 4 to 12 into eax
mov ecx,eax ; This moves eax into ecx temporarily
mov eax,6
mov ebx,2
div ebx ; This collapses 6 / 2 to 3 into eax
add ecx,eax ; This collapses 3 * 4 and 6 / 2 together into 15
mov eax,2
mov ebx,5
mul ebx ; This collapses 2 * 5 to 10 into eax
add eax,ecx ; This collapses 15 and 10 into 25
This expression tree is for scientific mode for the problem 3*4+6/2+2*5 is:
To do the problem with an expression tree you need to collapse the nodes (numbers) with there operators (such as *,+,and/).
This is how it looks after you've done the first collapsing. You see that the 3,4,and * are gone? That's because the way you collapse is do the numbers against there operator so that you come out with the answer .
This is what you get after you do the 2nd collapsing. This time do you see the difference? Yep the /,6, and 2 are gone because I did the same thing except I divided them instead of multiplying them.
This is what you get after the 3rd collapsing and its easy to spot the difference right? Well if you can't the 12,3,and the + are gone and there is a 15. That's because there was a + above the 12 and the 3 so I added them together.
This is what it looks like after the 4th collapsing. The difference here is very easy to spot. The 2,5,and 2nd * are gone and instead there is a 10. That's because the * was above the 2 and 5 so I multiplied them together.
This is the easiest difference to spot of all. The 10 and 15 and the + are gone and there instead there is a 25.That's because the + was above the 10 and 15 so I added them together.
Here is the assembly program to evaluate the above expression tree:
; 3 * 4 + 6 / 2 + 2 * 5
mov eax,3
mov ebx,4
mul ebx ; This collapses 3 * 4 to 12 into eax
mov ecx,eax ; This moves eax into ecx temporarily
mov eax,6
mov ebx,2
div ebx ; This collapses 6 / 2 to 3 into eax
add ecx,eax ; This collapses 3 * 4 and 6 / 2 together into 15
mov eax,2
mov ebx,5
mul ebx ; This collapses 2 * 5 to 10 into eax
add eax,ecx ; This collapses 15 and 10 into 25
Subscribe to:
Posts (Atom)