Professional Documents
Culture Documents
7.1 Local State
7.1 Local State
Local state
ebp
bp
ret
Example
• Extracting the arguments from the stack:
sum_nums: sum_nums:
push ecx
mov esi,dword [esp + 4] mov esi,dword [esp + 8]
mov ecx,dword [esp + 8] mov ecx,dword [esp + 0ch]
xor edx,edx xor edx,edx
jecxz .no_nums jecxz .no_nums
.next_dw: .next_dw:
lodsd lodsd
add edx,eax add edx,eax
loop .next_dw loop .next_dw
.no_nums: .no_nums:
mov eax,edx mov eax,edx
pop ecx
ret ret
Example
• Extracting the arguments from the stack:
sum_nums: sum_nums:
push ecx
mov esi,dword [esp + 4] mov esi,dword [esp + 8]
mov ecx,dword [esp + 8] mov ecx,dword [esp + 0ch]
xor edx,edx xor edx,edx
jecxz .no_nums jecxz .no_nums
.next_dw: .next_dw:
lodsd lodsd
add edx,eax add edx,eax
loop .next_dw loop .next_dw
.no_nums: .no_nums:
mov eax,edx mov eax,edx
pop ecx
ret ret
sum_nums:
mov ebp,esp
push ecx
mov esi,dword [ebp + 4]
mov ecx,dword [ebp + 8]
xor edx,edx
jecxz .no_nums
.next_dw:
lodsd
add edx,eax
loop .next_dw
.no_nums:
mov eax,edx
pop ecx
ret
Holding the stack frame
• We could use EBP to remember what ESP was initially.
• Then we don’t care about changes to esp.
sum_nums:
push ebp ; Keep ebp
mov ebp,esp
push ecx
mov esi,dword [ebp + 4]
mov ecx,dword [ebp + 8]
xor edx,edx
jecxz .no_nums
.next_dw:
lodsd
add edx,eax
loop .next_dw
.no_nums:
mov eax,edx
pop ecx
pop ebp ; Restore ebp
ret
Holding the stack frame
• We could use EBP to remember what ESP was initially.
• Then we don’t care about changes to esp.
func:
push ebp ; Keep ebp
mov ebp,esp
...
func: ...
push ebp ; Keep ebp
mov ebp,esp ????????
... ????????
Address
pop ebp ; Restore ebp ???????? growth
ret
????????
????????
????????
...
Holding the stack frame
• We could use EBP to remember what ESP was initially.
• Then we don’t care about changes to esp.
func: ...
push ebp ; Keep ebp
mov ebp,esp ????????
... ????????
arg2
arg3
...
Holding the stack frame
• We could use EBP to remember what ESP was initially.
• Then we don’t care about changes to esp.
func: ...
push ebp ; Keep ebp
mov ebp,esp ????????
arg2
arg3
...
Holding the stack frame
• We could use EBP to remember what ESP was initially.
• Then we don’t care about changes to esp.
func: ...
push ebp ; Keep ebp
mov ebp,esp ????????
arg2
arg3
...
Holding the stack frame
• We could use EBP to remember what ESP was initially.
• Then we don’t care about changes to esp.
func: ...
push ebp ; Keep ebp
mov ebp,esp ????????
????????
????????
????????
????????
...
Local Variables (Cont.)
• Decrease esp to allocate space on stack:
func: ...
push ebp ; Keep ebp
mov ebp,esp ????????
; ‘Allocate’ 3 dwords on stack:
sub esp,4*3 ????????
...
; ‘Free’ the 3 allocated dwords: ????????
add esp,4*3
pop ebp ; Restore ebp ????????
ret
????????
????????
????????
????????
????????
...
Local Variables (Cont.)
• Decrease esp to allocate space on stack:
func: ...
push ebp ; Keep ebp
mov ebp,esp ????????
; ‘Allocate’ 3 dwords on stack:
sub esp,4*3 ????????
...
; ‘Free’ the 3 allocated dwords: ????????
add esp,4*3
pop ebp ; Restore ebp ????????
ret
????????
esp ret_addr
arg1
arg2
arg3
...
Local Variables (Cont.)
• Decrease esp to allocate space on stack:
func: ...
push ebp ; Keep ebp
mov ebp,esp ????????
; ‘Allocate’ 3 dwords on stack:
sub esp,4*3 ????????
...
; ‘Free’ the 3 allocated dwords: ????????
add esp,4*3
pop ebp ; Restore ebp ????????
ret
esp old_ebp
ret_addr
arg1
arg2
arg3
...
Local Variables (Cont.)
• Decrease esp to allocate space on stack:
func: ...
push ebp ; Keep ebp
mov ebp,esp ????????
; ‘Allocate’ 3 dwords on stack:
sub esp,4*3 ????????
...
; ‘Free’ the 3 allocated dwords: ????????
add esp,4*3
pop ebp ; Restore ebp ????????
ret
esp old_ebp ebp
ret_addr
arg1
arg2
arg3
...
Local Variables (Cont.)
• Decrease esp to allocate space on stack:
func: ...
push ebp ; Keep ebp
mov ebp,esp ????????
; ‘Allocate’ 3 dwords on stack:
sub esp,4*3 esp ????????
...
; ‘Free’ the 3 allocated dwords: ????????
add esp,4*3
pop ebp ; Restore ebp ????????
ret
old_ebp ebp
ret_addr
arg1
arg2
arg3
...
Local Variables (Cont.)
• Decrease esp to allocate space on stack:
func: ...
push ebp ; Keep ebp
mov ebp,esp ????????
; ‘Allocate’ 3 dwords on stack:
sub esp,4*3 esp ????????
... Local
; ‘Free’ the 3 allocated dwords: ????????
vars
add esp,4*3
pop ebp ; Restore ebp ????????
ret
old_ebp ebp
ret_addr
arg1
arguments arg2
arg3
...
Local Variables (Cont.)
• Decrease esp to allocate space on stack:
func: ...
push ebp ; Keep ebp
mov ebp,esp ????????
; ‘Allocate’ 3 dwords on stack:
sub esp,4*3 esp ???????? ebp - 0xC
...
; ‘Free’ the 3 allocated dwords: ???????? ebp - 8
add esp,4*3
pop ebp ; Restore ebp ???????? ebp - 4
ret
old_ebp ebp
ret_addr
arg1 ebp + 8
arg2 ebp + 0xC
arg3 ebp + 0x10
...
Local Variables (Cont.)
• Decrease esp to allocate space on stack:
func: ...
push ebp ; Keep ebp
mov ebp,esp ????????
; ‘Allocate’ 3 dwords on stack:
sub esp,4*3 esp ???????? ebp - 0xC
...
; ‘Free’ the 3 allocated dwords: ???????? ebp - 8
add esp,4*3
pop ebp ; Restore ebp ???????? ebp - 4
ret
old_ebp ebp
ret_addr
• Variables: [𝑒𝑏𝑝 – 4 ⋅ 𝑘]
arg1 ebp + 8
• Arguments: [𝑒𝑏𝑝 + 4 + 4 ⋅ 𝑟]
arg2 ebp + 0xC
arg3 ebp + 0x10
...
Local Variables (Cont.)
• Increase esp to free the allocated stack space:
func: ...
push ebp ; Keep ebp
mov ebp,esp ????????
; ‘Allocate’ 3 dwords on stack:
sub esp,4*3 esp ????????
...
; ‘Free’ the 3 allocated dwords: ????????
add esp,4*3
pop ebp ; Restore ebp ????????
ret
old_ebp ebp
ret_addr
arg1
arg2
arg3
...
Local Variables (Cont.)
• Increase esp to free the allocated stack space:
func: ...
push ebp ; Keep ebp
mov ebp,esp ????????
; ‘Allocate’ 3 dwords on stack:
sub esp,4*3 esp ????????
...
; ‘Free’ the 3 allocated dwords: ????????
add esp,4*3
pop ebp ; Restore ebp ????????
ret
old_ebp ebp
ret_addr
arg1
arg2
arg3
...
Local Variables (Cont.)
• Increase esp to free the allocated stack space:
func: ...
push ebp ; Keep ebp
mov ebp,esp ????????
; ‘Allocate’ 3 dwords on stack:
sub esp,4*3 ????????
...
; ‘Free’ the 3 allocated dwords: ????????
add esp,4*3
pop ebp ; Restore ebp ????????
ret
esp old_ebp ebp
ret_addr
arg1
arg2
arg3
...
Local Variables (Cont.)
• Increase esp to free the allocated stack space:
func: ...
push ebp ; Keep ebp
mov ebp,esp ????????
; ‘Allocate’ 3 dwords on stack:
sub esp,4*3 ????????
...
; ‘Free’ the 3 allocated dwords: ????????
add esp,4*3
pop ebp ; Restore ebp ????????
ret
old_ebp
esp ret_addr
arg1
arg2
arg3
...
Local Variables (Cont.)
• Increase esp to free the allocated stack space:
func: ...
push ebp ; Keep ebp
mov ebp,esp ????????
; ‘Allocate’ 3 dwords on stack:
sub esp,4*3 ????????
...
; ‘Free’ the 3 allocated dwords: ????????
add esp,4*3
pop ebp ; Restore ebp ????????
ret
old_ebp
esp ret_addr
• The local state is freed when the
function returns. arg1
• Local data lives a short life. arg2
arg3
...
The call stack
• Every function being called has a “frame” inside the stack.
• Arguments
• Return address
• Old EBP (Previous frame)
• Local variables
• The stack tells the story of all functions currently “open”, all
the way to the current function.
The call stack (Cont.)
...
start
esp ...
The call stack (Cont.)
...
start
func_a
esp
Locals
old_ebp ebp
ret_addr
Arguments
...
The call stack (Cont.)
...
esp
start Locals
old_ebp ebp
func_a ret_addr
Arguments
func_b
Locals
old_ebp
ret_addr
Arguments
...
The call stack (Cont.)
...
start Locals
old_ebp
func_b’s frame
func_a ret_addr
Arguments
func_b
Locals
old_ebp
func_a’s frame
ret_addr
Arguments
...
The call stack (Cont.)
...
esp
start Locals
old_ebp ebp
func_a ret_addr
Arguments
dword [ebp]
func_b
Locals
old_ebp
ret_addr
Arguments
...
The call stack (Cont.)
• Traversing the call stack:
• EBP entries form a “linked list”!
The call stack (Cont.)
...
• Traversing the call stack: old_ebp ebp
• EBP entries form a “linked list”!
ret_addr
start ...
old_ebp
ret_addr
func_a
...
old_ebp
func_b ret_addr
...
old_ebp
func_c ret_addr
...
func_d
The call stack (Cont.)
...
• Traversing the call stack: old_ebp ebp
• EBP entries form a “linked list”!
ret_addr
start ...
old_ebp
ret_addr
func_a
...
old_ebp
func_b ret_addr
...
old_ebp
func_c ret_addr
...
func_d
The call stack (Cont.)
...
• Traversing the call stack: old_ebp ebp
• EBP entries form a “linked list”!
ret_addr
mov ebp,dword [ebp]
start ...
old_ebp
ret_addr
func_a mov ebp,dword [ebp]
...
old_ebp
...
old_ebp
func_c ret_addr
...
func_d
ENTER and LEAVE
• Almost all functions begin and end in the same standard way.
• Those standard beginning and ending are also called Prologue
and Epilogue.
func:
push ebp
Prologue mov ebp,esp
sub esp,N
func:
push ebp
mov ebp,esp
sub esp,N
...
add esp,N
pop ebp
ret
ENTER and LEAVE (Cont.)
• Building a stack frame using ENTER and LEAVE:
func: func:
push ebp enter N,0
mov ebp,esp
sub esp,N
... ...
func: func:
push ebp enter N,0
mov ebp,esp
sub esp,N
... ...
func: func:
push ebp enter N,0
mov ebp,esp
sub esp,N
... ...
mov esp,ebp
pop ebp leave
ret ret
ENTER and LEAVE (Cont.)
• Building a stack frame using ENTER and LEAVE:
func: func:
push ebp enter N,0
mov ebp,esp
sub esp,N
... ...
mov esp,ebp
pop ebp leave
ret ret
• Much cleaner :)
ENTER and LEAVE (Cont.)
• ENTER Size,NestingLevel
• Make stack frame for procedure parameters.
• Operation (For NestingLevel = 0):
• push ebp
mov ebp,esp ENTER N,0
sub esp,N
• LEAVE
• High level procedure exit.
• Operation:
• mov esp,ebp
pop ebp LEAVE
FAQ
• Do I have to use EBP for stack based argument passing?
• The ENTER and LEAVE instruction build and destroy the stack
frame.
Exercises
• Read code.
• Write code.
• Enjoy :)