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




No comments:

Post a Comment