三个法宝
- 存储程序计算机
- 函数调用堆栈
- 中断机制
在C语言中,堆栈空间是指程序运行时用来存储局部变量、函数参数、函数返回地址等数据的一块内存区域。
堆栈空间由操作系统自动分配和管理,每个线程都有自己的堆栈空间。
堆栈空间的特点如下:
1. 堆栈空间是一种后进先出(LIFO)的数据结构,存储数据的方式类似于一摞书,
后压入的数据位于栈顶,先压入的数据位于栈底。
2. 堆栈空间的大小是有限的,一般在程序运行时就已经确定,不能随意扩展。
当堆栈空间不足时,程序会出现栈溢出(stack overflow)的错误。
3. 堆栈空间的分配和释放是由操作系统自动完成的,不需要程序员手动管理。
当函数调用结束时,函数的局部变量和参数会自动从堆栈中弹出。
4. 堆栈空间的访问速度比堆空间更快,因为堆栈空间是由CPU硬件实现的,访问速度更快。
需要注意的是,堆栈空间只能存储局部变量、函数参数、函数返回地址等数据,不能存储动态分配的内存。
动态分配的内存需要存储在堆空间中,由程序员手动管理。
同时,也需要注意堆栈空间的大小限制,如果程序中使用的局部变量和函数参数过多,可能会导致栈溢出的错误。
理解函数调用堆栈
堆栈相关寄存器
- esp 堆栈指针(栈顶指针)
- ebp 基址指针(栈基指针:堆栈的空间由高地址到低地址申请与释放)
堆栈操作
- PUSH
- esp 减少一个字长(32bit=4byte)
- POP
- esp 增加一个字长,相当于释放了一个字长的空间
cs:eip 寄存器
- 顺序执行 总是指向地址连续的下一条指令地址
- 执行跳转或分支指令时,cs:eip 的值会根据需要被修改
- call 指令,将当前 cs:eip 的值压入栈顶,cs:eip指向被调用函数的入口地址
- ret 指令,从栈顶弹出原来保存在这里的 cs:eip 值,放到 cs:eip 中去
函数堆栈框架
手绘图
关于 cs:eip 的解释:
在计算机系统中,CS是指32位的代码段寄存器(Code Segment Register),用于存储代码段的起始地址。
在x86架构的CPU中,CS寄存器是一个16位的寄存器,可以存储0x0000到0xFFFF之间的值。
CS寄存器在实模式下用于存储代码段的起始地址,而在保护模式下则用于存储代码段选择子的值。
代码段选择子是一个16位的值,用于指定代码段在全局描述符表(Global Descriptor Table,GDT)
或局部描述符表(Local Descriptor Table,LDT)中的位置。
在保护模式下,CS寄存器的值由代码段选择子的高13位和特权级(Privilege Level)组成。
EIP寄存器和CS寄存器一起用于确定下一条指令的地址。在执行程序时,CPU会根据CS寄存器中存储的代码段地址
和EIP寄存器中存储的指令偏移量,计算出下一条指令的地址并从内存中取出执行。
需要注意的是,CS寄存器和其他段寄存器(如DS、ES、SS等)一样,属于CPU的硬件寄存器,无法直接读取或修改。
程序可以通过汇编语言的指令或C语言的内嵌汇编语句来访问这些寄存器的值。
参数传递与局部变量
touch main.c
int p2(int x,int y){
return x+y;
}
int main(){
int sum = p2(2,3);
}
gcc -g main.c
objdump -S a.out > main.s
a.out: file format mach-o 64-bit x86-64
Disassembly of section __TEXT,__text:
0000000100003f70 <_p2>:
100003f70: 55 pushq %rbp
100003f71: 48 89 e5 movq %rsp, %rbp
100003f74: 89 7d fc movl %edi, -4(%rbp)
100003f77: 89 75 f8 movl %esi, -8(%rbp)
100003f7a: 8b 45 fc movl -4(%rbp), %eax
100003f7d: 03 45 f8 addl -8(%rbp), %eax
100003f80: 5d popq %rbp
100003f81: c3 retq
100003f82: 66 66 66 66 66 2e 0f 1f 84 00 00 00 00 00 nopw %cs:(%rax,%rax)
0000000100003f90 <_main>:
100003f90: 55 pushq %rbp
100003f91: 48 89 e5 movq %rsp, %rbp
100003f94: 48 83 ec 10 subq $16, %rsp
100003f98: bf 02 00 00 00 movl $2, %edi
100003f9d: be 03 00 00 00 movl $3, %esi
100003fa2: e8 c9 ff ff ff callq 0x100003f70 <_p2>
100003fa7: 89 45 fc movl %eax, -4(%rbp)
100003faa: 31 c0 xorl %eax, %eax
100003fac: 48 83 c4 10 addq $16, %rsp
100003fb0: 5d popq %rbp
100003fb1: c3 retq
嵌入式调用