关于栈——不针对特定实现的分析
-
区分硬件栈和堆栈
- 堆栈是C语言编译器以及OS上程序内存结构的抽象概念,在CPU上只有寄存器、内存、数据(包括地址数据)。
- 硬件栈: 一般CPU会有一个到多个的栈指针寄存器和特殊的栈操作汇编指令,是用于过程调用以及中断切换的时候保存上下文的(特别是返回地址)。
- Intel x86 IA32 等好像都是 FD,ARM 虽然说可以调整方式(不确定细节),但是他的 ATPCS 还是要求用 FD。
-
区分堆栈中的堆和栈
一般说堆是动态分配内存的管理结构;
一般说栈是指函数调用栈,是以“栈帧”(stack frame)为单位的;
每个栈帧是一个函数调用,包含了返回地址(ARM-LR & x86-CS:IP),上下文环境(寄存器),函数参数,以及 C 编译器自动管理的局部 auto 变量;
PS0: 栈帧的相对位置,栈帧的结构,局部变量的相对位置,以及实际参数的相对位置是由实现决定的,不同的 OS & CPU 甚至是 Complier 可以有不同的实现;
PS1: 这里其实忽略了寄存器的存在,栈帧上的值可能不会存放在栈而是直接放在寄存器里;
PS2: 据我所知 ARM 有自己的过程调用标准 ATPCS,他传递参数以及返回值就是放在寄存器的;
PS3: C标准只要求,C对象是连续且对齐的内存块,以及指向 C对象的指针是组成对象的字节的连续地址中的最低那个;C对象都可以取地址(包括struct返回值?不确定),但是不知道标准有没有说,允许被优化到寄存器中。 -
虚拟进程地址空间
NT & linux 的每一个进程都有自己的进程空间,是虚拟的分页的。
在这个进程空间中的每一个线程都有自己的函数调用栈。
这个进程空间结构是操作系统决定的。
在和yyf的辩论中,发现:如果想要分析某一个实现下的程序的内存布局,可能要先明确下面的概念
- 表述中严格区分堆栈中的堆和栈,否则很容易说混;
- 区分地址空间的 上下 和 高地址端和低地址端;
- 严格区分大小端
要不很难分析清楚并表述出来。
请指正。