问题1:当执行第8行时,我推断%esp和%ebp都等于CFA-4,它们指向存储在堆栈中的返回地址。这样对吗?
: :
| whatever | <--- CFA: the value of the stack pointer at the
: : call site in the previous frame
+-----------------+
| line 43 address | <--- %ebp == CFA - 4?
+-----------------+
大会:
1 .file "test_.c"
2 .text
3 .globl fn1
4 .type fn1, @function
5 fn1:
6 .LFB0:
7 .cfi_startproc
8 pushl %ebp
9 .cfi_def_cfa_offset 8
10 .cfi_offset 5, -8
11 movl %esp, %ebp
12 .cfi_def_cfa_register 5
13 subl $16, %esp
14 movl $1, -8(%ebp)
15 movl $2, -4(%ebp)
16 movl -4(%ebp), %eax
17 movl -8(%ebp), %edx
18 addl %edx, %eax
19 leave
20 .cfi_restore 5
21 .cfi_def_cfa 4, 4
22 ret
23 .cfi_endproc
24 .LFE0:
25 .size fn1, .-fn1
26 .section .rodata
27 .LC0:
28 .string "count1 = %d\n"
29 .text
30 .globl main
31 .type main, @function
32 main:
33 .LFB1:
34 .cfi_startproc
35 pushl %ebp
36 .cfi_def_cfa_offset 8
37 .cfi_offset 5, -8
38 movl %esp, %ebp
39 .cfi_def_cfa_register 5
40 andl $-16, %esp
41 subl $32, %esp
42 call fn1
43 movl %eax, 28(%esp)
44 movl $.LC0, %eax
45 movl 28(%esp), %edx
46 movl %edx, 4(%esp)
47 movl %eax, (%esp)
48 call printf
49 movl $0, (%esp)
50 call exit
51 .cfi_endproc
52 .LFE1:
53 .size main, .-main
54 .ident "GCC: (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3"
55 .section .note.GNU-stack,"",@progbits
C代码:
#include <stdio.h>
#include <stdlib.h>
int fn1()
{
int a, b;
a = 1;
b = 2;
return a + b;
}
int main()
{
int count;
count = fn1();
printf("count1 = %d\n", count);
exit(0);
}
问题2:我不知道为什么要在代码中插入.cfi_offset 5, -8 , .cfi_def_cfa_register 5 , .cfi_restore 5和.cfi_def_cfa 4, 4也是如此。我找到了如何使用这些指令:
- .cfi_offset 寄存器,偏移量
- 寄存器的先前值保存在偏移量,从 CFA 偏移量。
- .cfi_def_cfa_register 寄存器
- .cfi_def_cfa_register 修改计算 CFA 的规则。从现在开始,将使用寄存器代替旧的。偏移量保持不变。
- .cfi_restore 寄存器
- .cfi_restore 表示 register 的规则现在与函数开始时的规则相同,在 .cfi_startproc 添加的所有初始指令都已执行之后。
- .cfi_def_cfa 寄存器,偏移量
.cfi_def_cfa 定义了计算 CFA 的规则:从寄存器中获取地址并添加偏移量。
所以我想知道1#、2#、3#……这些数字分别代表哪个寄存器。