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;
}


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




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!

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

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.



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.

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.