If someone can please help me understand the following code, I would greatly appreciate it.
We are starting to learn about push and pop in my MASM class, and like many, we are using Kip Irvine's stuff.
The questions are the following:
1. what is TYPE DWORD, is that generic for "data" that is DWORD size?
2. How is the function ArraySum falling out Loop L1? add ESI, TYPE DWORD.....what are we adding?
3. Why are we pushing ESI at the start of the function? is it so that when we RET we are back at the start of the array?
; Testing the ArraySum procedure (TestArraySum.asm)
.386
.model flat,stdcall
.stack 4096
ExitProcess PROTO, dwExitCode:dword
.data
array dword 10000h,20000h,30000h,40000h,50000h
theSum dword ?
.code
main proc
mov esi,OFFSET array ; ESI points to array
mov ecx,LENGTHOF array ; ECX = array count
call ArraySum ; calculate the sum
mov theSum,eax ; returned in EAX
invoke ExitProcess,0
main endp
;-----------------------------------------------------
ArraySum proc
;
; Calculates the sum of an array of 32-bit integers.
; Receives: ESI = the array offset
; ECX = number of elements in the array
; Returns: EAX = sum of the array elements
;-----------------------------------------------------
push esi ; save ESI, ECX
push ecx
mov eax,0 ; set the sum to zero
L1:
add eax,[esi] ; add each integer to sum
add esi,TYPE DWORD ; point to next integer
loop L1 ; repeat for array size
pop ecx ; restore ECX, ESI
pop esi
ret ; sum is in EAX
ArraySum endp
end main
Thank you
Quote from: Jbarrera on March 23, 2018, 03:22:13 PM1. what is TYPE DWORD, is that generic for "data" that is DWORD size?
Yes, more or less. In reality, it's just the number 4. And nobody writes TYPE DWORD here. Sometimes, we write add esi, DWORD instead of add esi, 4 to indicate that we are working with a DWORD array.
Quote2. How is the function ArraySum falling out Loop L1? add ESI, TYPE DWORD.....what are we adding?
loop is an instruction; read the help file.
Quote3. Why are we pushing ESI at the start of the function? is it so that when we RET we are back at the start of the array?
The registers esi edi ebx ebp are reserved, i.e. you can use them as you like but Windows wants them back in their original state. More here (http://www.webalice.it/jj2006/Masm32_Tips_Tricks_and_Traps.htm) in the section
The "register gets trashed" trap
Ok, that makes sense.
In the example, he pushes ESI and ECX, calculates then POPS back. How about if I want to do something like this (no specifically this but similar)
go into a PROC and push 2 values to the stack so I can use them for something, then exit the PROC
.data
myArray byte "3,6",0
.code
main PROC
lea ESI,myArray
call Example
main ENDP
Example PROC
PUSH ESI
PUSH ebx
mov ebx,0
mov bl,[esi]
PUSH ebx
add esi,2
mov bl,[esi]
PUSH ebx
;Do I need to pop off the 2 PUSHes for ebx when I was PUSHing 3 and 6, before I do POP ESI and POP ebx?
POP ESI
POP ebx
ret
Example ENDP
or does it scrap everything once it exits Example PROC?
Quote from: Jbarrera on March 24, 2018, 05:11:55 AM
Ok, that makes sense.
In the example, he pushes ESI and ECX, calculates then POPS back. How about if I want to do something like this (no specifically this but similar)
go into a PROC and push 2 values to the stack so I can use them for something, then exit the PROC
.data
myArray byte "3,6",0
.code
main PROC
lea ESI,myArray
call Example
main ENDP
Example PROC
PUSH ESI
PUSH ebx
mov ebx,0
mov bl,[esi]
PUSH ebx
add esi,2
mov bl,[esi]
PUSH ebx
;Do I need to pop off the 2 PUSHes for ebx when I was PUSHing 3 and 6, before I do POP ESI and POP ebx?
POP ESI
POP ebx
ret
Example ENDP
or does it scrap everything once it exits Example PROC?
You must balance the stack with equal number of POP's as you have PUSH's before RET
Otherwise RET will send execution elsewhere
This is because CALL pushes adress of right where you call your proc, RET retrieves that adress from stack so it can return execution to right after where proc been called
I was reading my assembly book to understand stacks and how to effectively use the stack to indirectly computer data, but I am still confused. I understand c++ better and I know some people have tried explaining using c++ as an example on other forums.
Quote
A stack frame (or activation record) is the area of the stack set aside for passed arguments, subroutine return address, local variables, and saved registers. The stack frame is created by the following sequential steps:
1. Passed arguments, if any, are pushed on the stack.
2. The subroutine is called, causing the subroutine return address to be pushed on the stack.
3. As the subroutine begins to execute, EBP is pushed on the stack.
4. EBP is set equal to ESP. From this point on, EBP acts as a base reference for all of the sub-
routine parameters.
5. If there are local variables, ESP is decremented to reserve space for the variables on the stack.
6. If any registers need to be saved, they are pushed on the stack.
Ok, so the stack frame, is this what would be manipulated when we do push and pops. Does the stack frame already "exist" as a "reserved" space or is it specifically created when doing the following 6 processes?
1. This is, for example, push or pop before calling a procedure. Saving values and addresses so we can get them back when done calling a procedure.
2. Is the subroutine automatic or is this something we are also doing? is this like doing the return after a procedure?
3. EBP is pushed to the stack....is this automatic or do we have to do it?
4. EBP is set to ESP. what information is being handed off here? is it an address or a list of "values / data / addresses". Also, why do we need to use EBP is it because EBP will not change automatically?
5. I don't understand exactly what they are referring to." local variables where, on the stack?" Does this apply to addresses too or specifically local variable and by local variables are they referring to stuff inside function or procedures?
6. how is this different from instruction number 1?
Go to Google images and search for stack frame push pop eax
Or, even better, get Olly (http://www.ollydbg.de/version2.html), open a simple exe file and press F7 until you have understood what happens.
I'm using visual studio, where do i save olly? Or can i just save it to my desktop and open a .asm file with it?
Yes. And next time, before posting such a question, try it out. It won't bite you.
Quote from: Jbarrera on March 24, 2018, 05:11:55 AM
Ok, that makes sense.
In the example, he pushes ESI and ECX, calculates then POPS back. How about if I want to do something like this (no specifically this but similar)
go into a PROC and push 2 values to the stack so I can use them for something, then exit the PROC
Quote
.data
myArray byte "3,6",0
.code
main PROC
lea ESI,myArray
call Example
main ENDP
Example PROC ; we dont need to preserve EBP
PUSH ESI ; preserve esi
PUSH ebx ; preserve ebx
mov ebx,0
mov bl,[esi]
;PUSH ebx ; why this ? -> it is for nothing here
add esi,2
mov bl,[esi]
; PUSH ebx ; why another ?
;Do I need to pop off the 2 PUSHes for ebx when I was PUSHing 3 and 6, before I do POP ESI and POP ebx?
;POP ESI
;POP ebx
POP ebx ; pop the last push -> ebx
POP ESI ; pop the first push -> esi
ret
Example ENDP
or does it scrap everything once it exits Example PROC?