代码之家  ›  专栏  ›  技术社区  ›  Christian Bouwense

进程如何跟踪其局部变量

  •  5
  • Christian Bouwense  · 技术社区  · 6 年前

    据我所知,当进程分配局部变量时,它是通过将它们作为堆栈推送到内存中来实现的,但仍然通过使用堆栈指针的偏移量引用它们(从这个线程)来访问它们作为随机内存 What is the idea behind using a stack for local variables? ).

    然而,它如何知道哪些变量有什么偏移量?我想得对吗?

    3 回复  |  直到 6 年前
        1
  •  6
  •   Sergey Kalinichenko    6 年前

    局部变量的偏移量作为常量“烘焙”到机器代码中。在编译器完成时,程序中称为局部变量的内容将替换为编译器指定的固定内存偏移量。

    假设您声明了三个局部变量:

    char a[8];
    int b;
    short c;
    

    编译器将偏移量分配给这些变量: a 处于偏移位置 0 , b 处于偏移位置 8 c 处于偏移位置 12 . 假设您的代码 b += c . 编译器将其转换为如下代码块:

    LOAD    @(SP+8)
    ADD     @(SP+12)
    STORE   @(SP+8)
    

    此处唯一更改的值是 SP (堆栈指针)。所有偏移量都是数值常量。

        2
  •  2
  •   zx485    6 年前

    前言:以下文本使用x86体系结构作为示例。其他体系结构的处理方式确实不同。

    [...] 它是通过将它们作为堆栈推入内存来实现的,[…]

    很接近了。 它是通过将它们放入内存来实现的 堆栈[当前进程的] . 每一个 过程 有自己的堆栈。因此,对于每个上下文切换 堆叠框架 改变了吗?它也改变了 局部变量(堆栈上) .

    通常(!)本地定义的变量相对于 堆叠框架 已保存并存在于 EBP 登记这与 全局定义的 相对于 数据段库 . 所以每个进程都有自己的堆栈 局部变量 .

    较新的编译器可以节省寄存器 EBP公司 并引用与 ESP 登记这有两个后果:

    • 一个或多个寄存器可供使用
    • 调试的可能性较小(调试通常使用 EBP公司 值作为当前 堆叠框架 识别局部变量)。因此,如果没有单独的 调试信息文件 .

    所以要回答你的主要问题

    进程如何跟踪其局部变量

    流程跟踪其 堆叠框架 (其中包含 局部变量 ),但不是他们的 局部变量 他们自己以及 堆叠框架 每项更改 过程开关 . 这个 局部变量 仅相对于 堆栈帧指针 登记在册 EBP公司 (或相对于 堆栈指针 ESP ,这取决于编译器设置)。

        3
  •  1
  •   Michal Butterweck    6 年前

    编译器负责记忆偏移量。这些偏移量只是硬编码的。若要加载变量以注册(例如,到eax),编译器将生成以下内容 mov eax, [esp-4] ,其中esp是堆栈指针寄存器,4是偏移量。如果将新变量推送到下一个mov以获取/设置变量,则该变量的偏移量将更大。所有这些都是编译时分析。

    此外,某些平台上的堆栈可能会反转,因此偏移量将为正。