3.67 Caller and Callee
★★
For this exercise, we will examine the code generated by GCC for functions that have structures as arguments and return values, and from this see how these language features are typically implemented.
The following C code has a function process
having structures as argument and return values, and a function eval
that calls process
:
typedef struct {
long a[2];
long *p;
} strA;
typedef struct {
long u[2];
long q;
} strB;
strB process(strA s) {
strB r;
r.u[0] = s.a[1];
r.u[1] = s.a[0];
r.q = *s.p;
return r;
}
long eval(long x, long y, long z) {
strA s;
s.a[0] = x;
s.a[1] = y;
s.p = &z;
strB r = process(s);
return r.u[0] + r.u[1] + r.q;
}
GCC generates the following code for these two functions:
process: ; strB process(strA s)
movq %rdi, %rax
movq 24(%rsp), %rdx
movq (%rdx), %rdx
movq 16(%rsp), %rcx
movq %rcx, (%rdi)
movq 8(%rsp), %rcx
movq %rcx, 8(%rdi)
movq %rdx, 16(%rdi)
ret
and:
eval: ; long eval(long x, long y, long z)
subq $104, %rsp
movq %rdx, 24(%rsp)
leaq 24(%rsp), %rax
movq %rdi, (%rsp)
movq %rsi, 8(%rsp)
movq %rax, 16(%rsp)
leaq 64(%rsp), %rdi
call process
movq 72(%rsp), %rax
addq 64(%rsp), %rax
addq 80(%rsp), %rax
addq $104, %rsp
ret
A. We can see on line 2 of function eval
that it allocates 104 bytes on the stack. Diagram the stack frame for eval
, showing the values that it stores on the stack prior to calling process
.
104 +------------------+
| |
| |
| |
| |
| |
| |
| |
| |
64 +------------------+ <-- %rdi
| |
| |
| |
| |
| |
| |
32 +------------------+
| z |
24 +------------------+
| &z |
16 +------------------+
| y |
8 +------------------+
| x |
0 +------------------+ <-- %rsp
B. What value does eval
pass in its call to process
?
%rsp+64
C. How does the code for process
access the elements of structure argument s
?
%rsp+offset
D. How does the code for process
set the fields of result structure r
?
process
get %rsp+64 as parameter from eval
, and stores data here for eval
.
E. Complete your diagram of the stack frame for eval
, showing how eval
accesses the elements of structure r
following the return from process
.
104 +------------------+
| |
| |
| |
| |
| |
| |
88 +------------------+
| z |
80 +------------------+
| x |
72 +------------------+
| y |
64 +------------------+ <-- %rdi(eval pass in)
| | \
| | -- %rax(process pass out)
| |
| |
| |
| |
32 +------------------+
| z |
24 +------------------+
| &z |
16 +------------------+
| y |
8 +------------------+
| x |
0 +------------------+ <-- %rsp in eval
| |
-8 +------------------+ <-- %rsp in process
F. What general principles can you discern about how structure values are passed as function arguments and how they are returned as function results?
Caller allocats space in stack and pass the address to callee, callee stores data in the space and return the address to caller.
Last updated
Was this helpful?