0% found this document useful (0 votes)
44 views21 pages

Assembly Language: Function Calls: Goals of This Lecture

The document discusses problems and solutions related to function calls in assembly language. Some key points: - Problem 1 is how the caller and callee functions handle the transfer of control between them. The IA-32 solution uses the stack and call/ret instructions, with call pushing the return address and ret popping it. - Problem 2 is how parameters are passed from the caller to the callee. One attempted solution was to pass parameters in registers, but this cannot handle nested function calls. - Other problems discussed include storing local variables, handling register usage between functions, and returning values. The document focuses on the IA-32 instruction set solutions for these function call problems.

Uploaded by

xpgong
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
44 views21 pages

Assembly Language: Function Calls: Goals of This Lecture

The document discusses problems and solutions related to function calls in assembly language. Some key points: - Problem 1 is how the caller and callee functions handle the transfer of control between them. The IA-32 solution uses the stack and call/ret instructions, with call pushing the return address and ret popping it. - Problem 2 is how parameters are passed from the caller to the callee. One attempted solution was to pass parameters in registers, but this cannot handle nested function calls. - Other problems discussed include storing local variables, handling register usage between functions, and returning values. The document focuses on the IA-32 instruction set solutions for these function call problems.

Uploaded by

xpgong
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 21

Assembly Language: 


Function Calls

Goals of this Lecture

•  Help you learn:


•  Function call problems:
•  Calling and returning
•  Passing parameters
•  Storing local variables
•  Handling registers without interference
•  Returning values
•  IA-32 solutions to those problems
•  Pertinent instructions and conventions

Function Call Problems


1.  Calling and returning
•  How does caller function jump to callee function?
•  How does callee function jump back to the right place in caller
function?

2.  Passing parameters


•  How does caller function pass parameters to callee function?

3.  Storing local variables


•  Where does callee function store its local variables?

4.  Handling registers


•  How do caller and callee functions use same registers without
interference?

5.  Returning a value


•  How does callee function send return value back to caller function?
3

1
Problem 1: Calling and Returning

How does caller function jump to callee function?


•  I.e., Jump to the address of the calleeʼs first instruction
How does the callee function jump back to the right place in
caller function?
•  I.e., Jump to the instruction immediately following the
most-recently-executed call instruction

Attempted Solution: Use Jmp Instruction


•  Attempted solution: caller and callee use jmp instruction
P: # Function P R: # Function R
… …
jmp R # Call R jmp Rtn_point1 # Return
Rtn_point1:

Attempted Solution: Use Jmp Instruction


•  Problem: callee may be called by multiple callers
P: # Function P R: # Function R
… …
jmp R # Call R jmp ??? # Return
Rtn_point1:

Q: # Function Q

jmp R # Call R
Rtn_point2:

6

2
Attempted Solution: Use Register
•  Attempted solution 2: Store return address in register

P: # Function P R: # Function R
movl $Rtn_point1, %eax …
jmp R # Call R jmp *%eax # Return
Rtn_point1:

Q: # Function Q
movl $Rtn_point2, %eax
Special form of jmp
jmp R # Call R
instruction; we will not use
Rtn_point2:

7

Attempted Solution: Use Register


•  Problem: Cannot handle nested function calls
P: # Function P R: # Function R
movl $Rtn_point1, %eax …
jmp Q # Call Q jmp *%eax # Return
Rtn_point1:

Q: # Function Q
movl $Rtn_point2, %eax
Problem if P calls Q, and Q
calls R
jmp R # Call R
Rtn_point2: Return address for P to Q
… call is lost
jmp %eax # Return
8

IA-32 Solution: Use the Stack


•  May need to store many return addresses
•  The number of nested functions is not known in advance
•  A return address must be saved for as long as the
function invocation continues, and discarded thereafter

•  Addresses used in reverse order


•  E.g., function P calls Q, which then calls R
EIP for Q
•  Then R returns to Q which then returns to P
EIP for P
•  Last-in-first-out data structure (stack)
•  Caller pushes return address on the stack
•  … and callee pops return address off the stack

•  IA 32 solution: Use the stack via call and ret


9

3
IA-32 Call and Ret Instructions
•  Ret instruction “knows” the return address
P: # Function P R: # Function R
… …
1
call R ret
2
call Q

Q: # Function Q

call R

ret

10

IA-32 Call and Ret Instructions


•  Ret instruction “knows” the return address
P: # Function P R: # Function R
… …
call R ret
call Q

3 4 5
Q: # Function Q

call R

6
ret

11

Implementation of Call
•  ESP (stack pointer register)
0
points to top of stack

Instruction Effective Operations

pushl src subl $4, %esp


movl src, (%esp)
popl dest movl (%esp), dest
addl $4, %esp

ESP

12

4
Implementation of Call
•  EIP (instruction pointer
0
register) points to next
instruction to be executed
Note: can’t really access EIP
Instruction Effective Operations directly, but this is implicitly
pushl src subl $4, %esp what call is doing
movl src, (%esp)
popl dest movl (%esp), dest
addl $4, %esp
call addr pushl %eip
jmp addr ESP
before
Call instruction pushes return call
address (old EIP) onto stack
13

Implementation of Call
0
Instruction Effective Operations

pushl src subl $4, %esp


movl src, (%esp)
popl dest movl (%esp), dest
addl $4, %esp
call addr pushl %eip
jmp addr ESP Old EIP
after
call

14

Implementation of Ret
0
Instruction Effective Operations

pushl src subl $4, %esp Note: can’t really access EIP
movl src, (%esp) directly, but this is implicitly
popl dest movl (%esp), dest
what ret is doing.
addl $4, %esp
call addr pushl %eip
jmp addr ESP Old EIP
ret pop %eip before
ret
Ret instruction pops stack, thus
placing return address (old EIP)
into EIP 15

5
Implementation of Ret
0
Instruction Effective Operations

pushl src subl $4, %esp


movl src, (%esp)
popl dest movl (%esp), dest
addl $4, %esp
call addr pushl %eip
jmp addr
ret pop %eip ESP
after
ret

16

Problem 2: Passing Parameters


•  Problem: How does caller function pass parameters to
callee function?

int add3(int a, int b, int c)


{
int d;
d = a + b + c;
return d;
}

int f(void)
{
return add3(3, 4, 5);
}

17

Attempted Solution: Use Registers


•  Attempted solution: Pass parameters in registers
f: add3:
movl $3, %eax …
movl $4, %ebx # Use EAX, EBX, ECX
movl $5, %ecx …
call add3 ret

18

6
Attempted Solution: Use Registers
•  Problem: Cannot handle nested function calls
f: add3:
movl $3, %eax …
movl $4, %ebx movl $6, %eax
movl $5, %ecx call g
call add3 # Use EAX, EBX, ECX
… # But EAX is corrupted!

ret

•  Also: How to pass parameters that are longer than 4 bytes?


19

IA-32 Solution: Use the Stack


•  Caller pushes parameters before 0
executing the call instruction

ESP before
pushing
params

20

IA-32 Parameter Passing


•  Caller pushes parameters in the 0
reverse order
•  Push Nth param first
•  Push 1st param last
•  So first param is at top of 

the stack at the time of the Call

ESP Param 1
before Param …
call
Param N

21

7
IA-32 Parameter Passing
•  Callee addresses params relative to 0
ESP: Param 1 as 4(%esp)

ESP Old EIP


after Param 1
call
Param …
Param N

22

IA-32 Parameter Passing


•  After returning to the caller… 0

ESP Param 1
after Param …
return
Param N

23

IA-32 Parameter Passing


•  … the caller pops the parameters 0
from the stack

ESP
after
popping
params
24

8
IA-32 Parameter Passing
For example:

f: add3:
… …
# Push parameters movl 4(%esp), wherever
pushl $5 movl 8(%esp), wherever
pushl $4 movl 12(%esp), wherever
pushl $3 …
call add3 ret
# Pop parameters
addl $12, %esp

25

Base Pointer Register: EBP


•  Problem:
•  As callee executes, ESP may 0
change
•  E.g., preparing to call
another function
•  Error-prone for callee to
reference params as offsets
relative to ESP ESP Old EIP
after Param 1
•  Solution: call
Param …
•  Use EBP as fixed reference
point to access params Param N

EBP
26

Using EBP
•  Need to save old value of EBP
•  Before overwriting EBP register 0

•  Callee executes “prolog”


pushl %ebp
movl %esp, %ebp ESP Old EBP
Old EIP
Param 1
Param …
Param N

EBP
27

9
Base Pointer Register: EBP
•  Callee executes “prolog”
0
pushl %ebp
movl %esp, %ebp

ESP, Old EBP


EBP
Old EIP
•  Regardless of ESP, callee can Param 1
reference param 1 as 8(%ebp), Param …
param 2 as 12(%ebp), etc. Param N

28

Base Pointer Register: EBP


•  Before returning, callee must 0
restore ESP and EBP to their
ESP
old values
•  Callee executes “epilog”
movl %ebp, %esp EBP Old EBP
popl %ebp Old EIP
Param 1
ret
Param …
Param N

29

Base Pointer Register: EBP


•  Callee executes “epilog” 0
movl %ebp, %esp
popl %ebp
ret
ESP, Old EBP
EBP Old EIP
Param 1
Param …
Param N

30

10
Base Pointer Register: EBP
•  Callee executes “epilog” 0
movl %ebp, %esp
popl %ebp
ret

ESP Old EIP


Param 1
Param …
Param N

EBP
31

Base Pointer Register: EBP


•  Callee executes “epilog” 0
movl %ebp, %esp
popl %ebp
ret

ESP Param 1
Param …
Param N

EBP
32

Problem 3: Storing Local Variables

•  Where does callee function store its local variables?

int add3(int a, int b, int c)


{
int d;
d = a + b + c;
return d;
}

int foo(void)
{
return add3(3, 4, 5);
}

33

11
IA-32 Solution: Use the Stack
•  Local variables:
•  Short-lived, so donʼt need a
permanent location in
memory int add3(int a, int b, int c)
•  Size known in advance, so {
int d;
donʼt need to allocate on the d = a + b + c;
heap return d;
}
•  So, the function just uses
int foo(void)
the top of the stack {
•  Store local variables on the return add3(3, 4, 5);
top of the stack }
•  The local variables disappear
after the function returns

34

IA-32 Local Variables


•  Local variables of the callee
are allocated on the stack 0

•  Allocation done by moving the ESP Var 2


stack pointer
Var 1
•  Example: allocate memory for EBP Old EBP
two integers Old EIP
•  subl $4, %esp Param 1
•  subl $4, %esp Param …
•  (or equivalently, subl $8, %esp)
Param N
•  Reference local variables as
negative offsets relative to EBP
•  -4(%ebp)
•  -8(%ebp)
35

IA-32 Local Variables


For example:

add3:

# Allocate space for d
subl $4, %esp

# Access d
movl whatever, -4(%ebp)

ret

36

12
Problem 4: Handling Registers
•  Problem: How do caller and callee functions use
same registers without interference?
•  Registers are a finite resource!
•  In principle: Each function should have its own set of
registers
•  In reality: All functions must use the same small set of
registers

•  Callee may use a register that the caller also is


using
•  When callee returns control to caller, old register
contents may be lost
•  Caller function cannot continue where it left off
37

IA-32 Solution: Define a Convention

•  IA-32 solution: save the registers on the stack


•  Someone must save old register contents
•  Someone must later restore the register contents

•  Define a convention for who saves and restores


which registers

38

IA-32 Register Handling


0
•  Caller-save registers
•  EAX, EDX, ECX
ESP Var 2
•  If necessary…
Var 1
•  Caller saves on stack before call
•  Caller restores from stack after call Saved EBX,
ESI,EDI
•  Callee-save registers EBP Old EBP
•  EBX, ESI, EDI
Old EIP
•  If necessary…
Param 1
•  Callee saves on stack after prolog
Param …
•  Callee restores from stack before
epilog Param N
•  Caller can assume that values in EBX, Saved EAX,
ESI, EDI will not be changed by callee EDX,ECX
39

13
Problem 5: Return Values
•  Problem: How does callee
function send return value
back to caller function?
int add3(int a, int b, int c)
•  In principle: {
int d;
•  Store return value in stack d = a + b + c;
frame of caller return d;
}
•  Or, for efficiency:
int foo(void)
•  Known small size => store {
return value in register return add3(3, 4, 5);
•  Other => store return value in }
stack

40

IA-32 Return Values


IA-32 Convention:
•  Integral type or pointer:
•  Store return value in EAX int add3(int a, int b, int c)
•  char, short, int, long, pointer {
int d;
d = a + b + c;
•  Floating-point type: return d;
•  Store return value in floating- }
point register
int foo(void)
•  (Beyond scope of course) {
return add3(3, 4, 5);
•  Structure: }
•  Store return value on stack
•  (Beyond scope of course)

41

Stack Frames
Summary of IA-32 function handling:
•  Stack has one stack frame per active function invocation
•  ESP points to top (low memory) of current stack frame
•  EBP points to bottom (high memory) of current stack
frame
•  Stack frame contains:
•  Return address (Old EIP)
•  Old EBP
•  Saved register values
•  Local variables
•  Parameters to be passed to callee function
42

14
A Simple Example

int add3(int a, int b, int c)


{
int d;
d = a + b + c;
return d;
}

/* In some calling function */


x = add3(3, 4, 5);

43

Trace of a Simple Example 1


x = add3(3, 4, 5); Low memory

ESP

EBP
High memory 44

Trace of a Simple Example 2


x = add3(3, 4, 5); Low memory

# Save caller-save registers if necessary


pushl %eax
pushl %ecx
pushl %edx

ESP Old EDX


Old ECX
Old EAX

EBP
High memory 45

15
Trace of a Simple Example 3
x = add3(3, 4, 5); Low memory

# Save caller-save registers if necessary


pushl %eax
pushl %ecx ESP 3
pushl %edx 4
# Push parameters
pushl $5 5
pushl $4 Old EDX
pushl $3 Old ECX
Old EAX

EBP
High memory 46

Trace of a Simple Example 4


x = add3(3, 4, 5); Low memory

# Save caller-save registers if necessary


pushl %eax ESP Old EIP
pushl %ecx 3
pushl %edx 4
# Push parameters
pushl $5 5
pushl $4 Old EDX
pushl $3 Old ECX
# Call add3
call add3 Old EAX

EBP
High memory 47

Trace of a Simple Example 5


int add3(int a, int b, int c) { Low memory
int d;
d = a + b + c;
return d;
}
ESP Old EBP
# Save old EBP Old EIP
pushl %ebp
Prolog 3
4
5
Old EDX
Old ECX
Old EAX

EBP
High memory 48

16
Trace of a Simple Example 6
int add3(int a, int b, int c) { Low memory
int d;
d = a + b + c;
return d;
}
ESP Old EBP
# Save old EBP EBP Old EIP
pushl %ebp
# Change EBP Prolog 3
movl %esp, %ebp 4
5
Old EDX
Old ECX
Old EAX

High memory 49

Trace of a Simple Example 7


int add3(int a, int b, int c) { Low memory
int d;
d = a + b + c; ESP Old EDI
return d; Old ESI
} Old EBX
EBP Old EBP
# Save old EBP Old EIP
pushl %ebp
# Change EBP 3
movl %esp, %ebp 4
# Save caller-save registers if necessary 5
pushl %ebx Unnecessary here; add3 will not
pushl %esi Old EDX
pushl %edi change the values in these registers Old ECX
Old EAX

High memory 50

Trace of a Simple Example 8


int add3(int a, int b, int c) { Low memory
int d; ESP
d = a + b + c; Old EDI
return d; Old ESI
} Old EBX
EBP Old EBP
# Save old EBP Old EIP
pushl %ebp
# Change EBP 3
movl %esp, %ebp 4
# Save caller-save registers if necessary 5
pushl %ebx
pushl %esi Old EDX
pushl %edi Old ECX
# Allocate space for local variable Old EAX
subl $4, %esp

High memory 51

17
Trace of a Simple Example 9
int add3(int a, int b, int c) { Low memory
int d; ESP 12
d = a + b + c; Old EDI
return d; Old ESI
} Old EBX
EBP Old EBP
# Save old EBP Old EIP
pushl %ebp
# Change EBP 3
movl %esp, %ebp 4
# Save caller-save registers if necessary 5
pushl %ebx
pushl %esi Old EDX
pushl %edi Old ECX
# Allocate space for local variable Old EAX
subl $4, %esp Access params as positive
# Perform the addition offsets relative to EBP
movl 8(%ebp), %eax
addl 12(%ebp), %eax Access local vars as negative
addl 16(%ebp), %eax
movl %eax, -16(%ebp) offsets relative to EBP
High memory 52

Trace of a Simple Example 10


int add3(int a, int b, int c) { Low memory
int d; ESP 12
d = a + b + c; Old EDI
return d; Old ESI
} Old EBX
EBP Old EBP
# Copy the return value to EAX Old EIP
movl -16(%ebp), %eax
# Restore callee-save registers if necessary 3
movl -12(%ebp), %edi 4
movl -8(%ebp), %esi 5
movl -4(%ebp), %ebx
Old EDX
Old ECX
Old EAX

High memory 53

Trace of a Simple Example 11


int add3(int a, int b, int c) { Low memory
int d; 12
d = a + b + c; Old EDI
return d; Old ESI
} Old EBX
ESP Old EBP
# Copy the return value to EAX EBP Old EIP
movl -16(%ebp), %eax
# Restore callee-save registers if necessary 3
movl -12(%ebp), %edi 4
movl -8(%ebp), %esi 5
movl -4(%ebp), %ebx
# Restore ESP Old EDX
movl %ebp, %esp Old ECX
Epilog Old EAX

High memory 54

18
Trace of a Simple Example 12
int add3(int a, int b, int c) { Low memory
int d; 12
d = a + b + c; Old EDI
return d; Old ESI
} Old EBX
Old EBP
# Copy the return value to EAX ESP Old EIP
movl -16(%ebp), %eax
# Restore callee-save registers if necessary 3
movl -12(%ebp), %edi 4
movl -8(%ebp), %esi 5
movl -4(%ebp), %ebx
# Restore ESP Old EDX
movl %ebp, %esp Old ECX
# Restore EBP Epilog Old EAX
popl %ebp

EBP
High memory 55

Trace of a Simple Example 13


int add3(int a, int b, int c) { Low memory
int d; 12
d = a + b + c; Old EDI
return d; Old ESI
} Old EBX
Old EBP
# Copy the return value to EAX Old EIP
movl -16(%ebp), %eax
# Restore callee-save registers if necessary ESP 3
movl -12(%ebp), %edi 4
movl -8(%ebp), %esi 5
movl -4(%ebp), %ebx
# Restore ESP Old EDX
movl %ebp, %esp Old ECX
# Restore EBP Old EAX
popl %ebp
# Return to calling function
ret

EBP
High memory 56

Trace of a Simple Example 14


x = add3(3, 4, 5); Low memory
12
Old EDI
# Save caller-save registers if necessary
pushl %eax Old ESI
pushl %ecx Old EBX
pushl %edx Old EBP
# Push parameters
pushl $5 Old EIP
pushl $4 3
pushl $3 4
# Call add3
call add3 5
# Pop parameters ESP Old EDX
addl $12, %esp Old ECX
Old EAX

EBP
High memory 57

19
Trace of a Simple Example 15
x = add3(3, 4, 5); Low memory
12
Old EDI
# Save caller-save registers if necessary
pushl %eax Old ESI
pushl %ecx Old EBX
pushl %edx Old EBP
# Push parameters
pushl $5 Old EIP
pushl $4 3
pushl $3 4
# Call add3
call add3 5
# Pop parameters ESP Old EDX
addl %12, %esp Old ECX
# Save return value
movl %eax, wherever Old EAX

EBP
High memory 58

Trace of a Simple Example 16


x = add3(3, 4, 5); Low memory
12
Old EDI
# Save caller-save registers if necessary
pushl %eax Old ESI
pushl %ecx Old EBX
pushl %edx Old EBP
# Push parameters
pushl $5 Old EIP
pushl $4 3
pushl $3 4
# Call add3
call add3 5
# Pop parameters Old EDX
addl %12, %esp Old ECX
# Save return value
movl %eax, wherever Old EAX
# Restore caller-save registers if necessary ESP
popl %edx
popl %ecx
popl %eax
EBP
High memory 59

Trace of a Simple Example 17


x = add3(3, 4, 5); Low memory

# Save caller-save registers if necessary


pushl %eax
pushl %ecx
pushl %edx
# Push parameters
pushl $5
pushl $4
pushl $3
# Call add3
call add3
# Pop parameters
addl %12, %esp
# Save return value
movl %eax, wherever
# Restore caller-save registers if necessary ESP
popl %edx
popl %ecx
popl %eax
# Proceed! EBP
… 60
High memory

20
Summary
•  Calling and returning
•  Call instruction: push EIP onto stack and jump
•  Ret instruction: pop stack to EIP

•  Passing parameters
•  Caller pushes onto stack
•  Callee accesses as positive offsets from EBP
•  Caller pops from stack

61

Summary (cont.)
•  Storing local variables
•  Callee pushes on stack
•  Callee accesses as negative offsets from EBP
•  Callee pops from stack

•  Handling registers
•  Caller saves and restores EAX, ECX, EDX if necessary
•  Callee saves and restores EBX, ESI, EDI if necessary

•  Returning values
•  Callee returns data of integral types and pointers in EAX

62

21

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy