c - x86 程序集(英特尔风格)中的相对寻址,是相对于 "slot"的顶部还是底部给出的偏移量?

标签 c assembly gdb stack offset

我在 GDB 调试器中工作,目的是使用来自汇编指令和源代码的信息以及参数输入的知识为我的可执行文件构建调用堆栈模型。我知道堆栈上数据的位置通常是相对于 x86 体系结构 (i386) 的 $EBP 或 $ESP 寄存器引用的。比如来自源码

if argc != 2
{
    //do something
}

尽管我是汇编新手,但我可以推断出这一点

<main+9>    cmp    DWORD PTR  [ebp+0x8],0x2

构成汇编指令的一部分,旨在将静态值 2 与 argc 进行比较,这些指令是根据上面给出的源代码片段编译而来的。此外,我知道 argc 位于插入堆栈并构成堆栈基础的 $EBP 寄存器值上方 8 个字节(两个 32 位字——因为这是一个 32 位 VM)。不幸的是,我对相对引用的起源/基线是什么感到困惑。它是相对于内存中 $EBP “插槽”的顶部地址还是底部地址。以另一种方式询问,当我输入时

print $ebp

在GDB中获取

(void *) 0xbaffe020

作为答复,该十六进制地址是位于 4 字节宽的 $EBP“槽”的顶部还是底部?这很重要,因为当我找到两个地址之间的距离时,我需要知道是否需要额外添加 4 个字节。

-- 关于术语的注释:我经常将 32 位(4 字节)字标记为内存中的“插槽”,因为我发现它更符合我的扁平内存心智模型 [本质上是固定宽度的大数组可寻址的“插槽”/频带] --

此外,我怎样才能使这种相对寻址方案与 DWARF 语法协调一致?不幸打字

info address VARIABLE

进入 GDB 会产生 DWARF 语法中的相对寻址,就像这样

DW_OP_breg4 24

我知道 breg4 引用 $EBP 和 fbreg 引用 $ESP 并且正数在内存地址中偏移较高,而负数在内存地址中偏移较低但仅此而已。 DWARF 语法的相对基础是什么?我可以在 GDB 中使用其他方案并完全避免 DWARF 吗? 非常感谢。

最佳答案

在函数入口处使用 push ebp/mov ebp, esp 制作传统堆栈框架后,EBP 指向 bottom保存的来电者 EBP 值。

因此 EBP 指向返回地址下方 4 个字节,第一个堆栈 arg 下方 8 个字节(这就是为什么您在 [ebp+8] 处找到 argc 的原因。

一般来说,地址指向对象字节的底部/开始。指向对象的指针与指向对象第一个字节的指针相同。 (x86 是小端字节序,这是最低有效字节。)

关于c - x86 程序集(英特尔风格)中的相对寻址,是相对于 "slot"的顶部还是底部给出的偏移量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52324304/

相关文章:

assembly - 英特尔 x86 操作码引用?

检查 Stackable 文件系统是否以编程方式安装

c - C中main方法中参数的使用

assembly - 自动检测违反程序集调用约定的情况

c++ new运算符通过libstdc++占用大量内存(67MB)

multithreading - 将线程 ID 从顶部映射到 gdb

c - 使用 GDB 调试 C 项目

c - Objective-c:为什么在我继承的这段代码中使用了 strtol 方法?

c - C中 volatile 非静态局部变量的原因

assembly - 为什么在 x86 汇编中 left 会执行 "mov esp,ebp"?