内存与寄存器

函数栈帧

memory_and_register_1.png

常用寄存器

Name Description
ESP 指向栈帧的栈顶地址(内存较低位),会随着程序的执行向低位移动
EBP 指向栈帧的基地址(内存较高位)
EIP 指令指针寄存器,保存着 CPU 要执行的指令地址,永远指向 CPU 将要执行的下一条指令的地址
ESI 源变址寄存器,保存着要处理的数据的内存地址
EDI 目的变址寄存器,保存着处理后的数据的内存地址

程序执行过程中内存和寄存器的变化

给 a 赋值后

memory_and_register_3.png

程序运行到 fun 函数时,ESP 减少了 12,即往内存低位移动了 3 个内存单元,也就是有 3 * 4 字节数据被压入了栈帧,查看 ESP 指向的内存区域,0x12FF20 处 4 字节为主调函数 main 的返回地址,可以看到 8 字节为形参的值已经被压入了栈帧,形参的值先被寄存器 EAX,ECX 保存,再写入到内存中

memory_and_register_4.png

继续执行,进入了 fun 函数的栈帧,EBP,ESP 的值都改变了,新 EBP 指向原 ESP-4 的值,也就是 EBP 移动到了原 ESP 的上方,而新 EBP 指向的内存中储存的值是原 EBP 的值

memory_and_register_5.png

fun 函数最后的加法运算,值也是先保存到寄存器中,再写入到 fun 函数的栈帧中

memory_and_register_6.png

当 fun 函数执行完毕,fun 函数的栈帧将被 OS 回收,EBP 将重新指向原 EBP 指向的内存,而 ESP 指向了原 ESP+4 的内存地址,说明发生了 POP 操作,弹出了返回地址 0x401093,原 ESP 的值是当前 EIP 的值,这个地址被存入了 EIP 中,也就是被 CPU 执行了,以便继续执行 main 函数。 最后可看到 ESP 指向了 0x12FF2C,即程序一开始时 ESP 的值,说明传递给 fun 的形参都被弹出, 恢复到调用 fun 之前的栈帧状态。return 0 程序正常结束。

memory_and_register_7.png

源代码

一个简单的加法函数和主函数,主函数中调用 fun() 实现两个变量的加法运算

#include <stdio.h>

void fun(int _m, int _n) {
    int i_local;
    i_local = _m + _n;
}

int main(int argc, char const *argv[]) {
    int a = 0x1111;
    int b = 0x2222;
    fun(a, b);
    return 0;
}
湘ICP证019014083号