逆向教程 堆栈详解

程序在运行的时候通常会使用堆栈来存储数据,所以了解堆栈对逆向是很有帮助的.我们常说的堆栈,实际是栈.栈和堆是两个不同的概念.在绝大多数主流架构(包括 ARM、x86 和 x86-64)中,堆栈(stack)默认都是从高地址向低地址生长的,也就是说,每次压栈(push)操作会使栈指针(stack pointer)减小,而弹栈(pop)操作会使栈指针增大

这是由操作系统和 ABI(Application Binary Interface)约定的,而不是 CPU 架构强制规定的。不过,这些架构的设计通常都支持这种向下增长的堆栈,并且主流操作系统(如 Linux、Windows、Android 等)都采用这种约定。

具体说明如下:

  • x86 / x86-64
    栈指针寄存器是 ESP(32 位)或 RSP(64 位)。执行 push 指令时,先减小栈指针,再写入数据;pop 则相反。堆栈从高地址向低地址增长。

  • ARM(包括 AArch32 和 AArch64)
    在标准的 AAPCS(ARM Architecture Procedure Call Standard)和 AAPCS64 中,栈也是满递减(Full Descending)的,即栈指针指向最后一个有效数据,并且向低地址增长。这是默认且广泛采用的模式。

注意:理论上,堆栈也可以设计为从低地址向高地址增长(比如某些嵌入式系统或特殊用途的运行时环境),但这在通用操作系统和主流 ABI 中极为罕见。

下面我用文字“画图”来直观地说明 堆栈从高地址向低地址生长 的过程,并配合简要解释。


🧠 内存地址布局(简化版)

在典型的程序内存空间中(以 Linux 或 Android 为例):

高地址(例如 0xFFFF0000)
┌───────────────────────┐
│        内核空间        │
├───────────────────────┤
│        栈(Stack)     │ ← 栈顶(初始时靠近高地址)
│          ...          │
├───────────────────────┤
│        空闲内存        │
├───────────────────────┤
│        堆(Heap)      │ → 堆向高地址增长
├───────────────────────┤
│       数据段(.data)  │
│       代码段(.text)  │
└───────────────────────┘
低地址(例如 0x00000000)

注意:栈在高地址区域,堆在低地址区域,两者相向增长。


📌 堆栈生长方向详解(以 x86-64 / ARM 为例)

假设初始栈指针 SP 指向 0x7FFFFFF0(高地址)。

初始状态:
地址         内容
0x7FFFFFFC   [未使用]
0x7FFFFFF8   [未使用]
0x7FFFFFF4   [未使用]
0x7FFFFFF0 ← SP(栈顶,空栈)
0x7FFFFFEC   [已用/不可用]
...
执行 push A(压入一个 4 字节数据 A):
  • SP 先减 4 → 变成 0x7FFFFFEC
  • 把 A 存到 0x7FFFFFEC
地址         内容
0x7FFFFFFC   [未使用]
0x7FFFFFF8   [未使用]
0x7FFFFFF4   [未使用]
0x7FFFFFF0   [未使用]
0x7FFFFFEC ← SP → A
0x7FFFFFE8   [...]
再执行 push B
  • SP 减 4 → 0x7FFFFFE8
  • 存入 B
地址         内容
0x7FFFFFF0   [未使用]
0x7FFFFFEC   A
0x7FFFFFE8 ← SP → B
0x7FFFFFE4   [...]

✅ 可见:每次压栈,地址变小 → 堆栈向低地址生长


🔄 对比:堆(Heap)的生长方向

堆通常通过 malloc()new 分配,由低地址向高地址扩展:

堆起始:0x10000000
malloc(16) → 分配到 0x10000000~0x1000000F
malloc(8)  → 分配到 0x10000010~0x10000017

→ 堆指针 向上增长(低 → 高)


📝 总结图(方向对比)

高地址
  ↑
  │    栈(Stack) ↓ 向下生长(高 → 低)
  │    ...
  │    堆(Heap) ↑ 向上生长(低 → 高)
  ↓
低地址

所有主流架构(ARM、x86、x86-64)在标准操作系统(如 Android、Linux、Windows)中都采用这种约定。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值