[assembly code]
main:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
subl $32, %esp
movl $5, 20(%esp)
movl $3, 24(%esp)
movl 24(%esp), %eax
movl %eax, 4(%esp)
movl 20(%esp), %eax
movl %eax, (%esp)
call add
movl %eax, 28(%esp)
movl $0, %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE0:
.size main, .-main
.globl add
.type add, @function
add:
.LFB1:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $16, %esp
movl 12(%ebp), %eax
movl 8(%ebp), %edx
addl %edx, %eax
movl %eax, -4(%ebp)
movl -4(%ebp), %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
[source code]
int add(int k, int l);
int main(int argc, char **argv) {
int a, b, ret;
a = 5;
b = 3;
ret = add(a, b);
return 0;
}
int add(int k, int l) {
int x;
x = k + l;
return x;
}
I'm studying the calling convention of c function at the assembly language level.
As you know, .cfi is used for adding debug information. I've read some cfi articles and known the meaning of each directives.
In the above assembly code, the .cfi_def_cfa_offset 8
and .cfi_offset 5 -8
directives comes in consecutively. This happens in 'main' function and 'add' function same again.
But, I don't know why this happens. What I know about is .cfi_def_cfa_offset
and .cfi_offset
are used for making reserve memory to store debug information. In this code, that offset is set to +8 at first, and -8 at second. The result is... there are no remained memory space to store cfi. Am I right?
I think that the stack segment work like this way.
.cfi_startproc
|-------------|
| whatever | <- %esp = CFA ↑ increase address
|-------------|
| | ↓ stack grow
|_____________|
.pushl %ebp
|-------------|
| whatever |
|-------------|
| %ebp | <- %esp
|_____________|
.cfi_def_cfa_offset 8
|-------------|
| whatever | <- %esp
|-------------|
| whatever |
|-------------|
| %ebp |
|-------------|
.cfi_offset 5 -8
|-------------|
| whatever |
|-------------|
| whatever |
|-------------|
| %ebp | <- %esp
|-------------|
subl $32, %esp
|-------------|
| whatever |
|-------------|
| %ebp |
|-------------|
| |
|-------------|
| |
|-------------|
| |
|-------------|
| |
|-------------|
| |
|-------------|
| |
|-------------|
| |
|-------------|
| | <- %esp
|-------------|
movl $5, 20(%esp)
|-------------|
| whatever |
|-------------|
| %ebp |
|-------------|
| |
|-------------|
| |
|-------------|
| 5 |
|-------------|
| |
|-------------|
| |
|-------------|
| |
|-------------|
| |
|-------------|
| | <- %esp
|-------------|
and so on...
Question 2.
At the procedure add
, the parameter from the caller function is moved to callee function register.
movl 12(%ebp), %eax
movl 8(%ebp), %edx
But, in my calculation, 8(%ebp) is not pointing the top of the caller stack. Because,
1) at pushl %ebp
, %esp is subtracted 4
2) at cfi_offset 5, -8
, %esp is sbracted 8 (In this way, I neglect .cfi_def_cfa_offset 8
. I'm not sure)
So, the top of the caller function stack should be 12(%ebp) in this way, and 8(%ebp) is pointing the stored base pointer of caller function.
I don't know where I don't know... I need your help.
-added
What do the CFI directives mean? (and some more questions)
This SO question is almost similar to me. But there's no one answers that question clearly.