问题标签 [red-zone]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
2 回答
2394 浏览

c - 为什么这个函数序言中没有“sub rsp”指令,为什么函数参数存储在负 rbp 偏移处?

读了一些内存分割文档是这样理解的:函数调用的时候,有几条指令(叫做函数序言),把帧指针保存在栈上,把栈指针的值复制到基指针中,保存一些局部变量的内存。

这是我尝试使用 GDB 调试的简单代码:

调试此代码的目的是了解调用函数时堆栈中发生的情况:因此我必须在程序执行的各个步骤(在调用函数之前和执行期间)检查内存。虽然我通过检查基指针设法看到了返回地址和保存的帧指针之类的东西,但我真的无法理解在反汇编代码之后我要写什么。

拆卸:

我知道“将帧指针保存在堆栈上”是由“push rbp”完成的,“将堆栈指针的值复制到基指针”是由“mov rbp,rsp”完成的,但让我感到困惑的是缺少用于“为局部变量节省一些内存”的“sub rsp $n_bytes”。我在很多展品中都看到了这一点(甚至在 stackoverflow 上的某些主题中)。

我还读到参数应该与基指针有一个正偏移(在它被堆栈指针值填充之后),因为如果它们位于调用者函数中并且堆栈向较低地址增长,那么当基指针用堆栈指针值更新,编译器通过添加一些正数返回堆栈。但是我的代码似乎将它们存储在负偏移量中,就像局部变量一样。我也不明白为什么将它们放在那些寄存器中(主要)..它们不应该直接保存在 rsp“偏移量“?

也许这些差异是由于我使用的是 64 位系统,但我的研究并没有让我找到任何可以解释我所面临问题的东西。

0 投票
2 回答
319 浏览

assembly - 为什么要为局部变量保留堆栈空间?

我是汇编语言的新手,我想知道局部变量,为什么我们(或编译器)通常通过在过程的序言和过程结束时减少“ESP”寄存器来在堆栈上为它们保留一个空间我们再次分配“ESP”它的旧值。像这个代码示例:

如果我们删除 (sub esp,8) 行和 (mov esp,ebp) 行,最后一个代码片段将完全正确,就像这样

那么为什么我们(或编译器)会这样做!,我们为什么不直接使用堆栈内存来存储我们的局部变量,只要“ESP”指针不会受到堆栈上存储值的影响,代码如下:

0 投票
2 回答
6776 浏览

c++ - 在 C++ 内联 asm 中使用基指针寄存器

我希望能够%rbp在内联汇编中使用基指针寄存器 ()。一个玩具例子是这样的:

我希望,因为我使用的是通常的序言/尾声函数调用方法来推送和弹出 old %rbp,这样就可以了。但是,当我尝试在内x联汇编之后访问时,它会出现故障。

GCC 生成的汇编代码(略微精简)是:

谁能告诉我为什么这个段错误?似乎我以某种方式腐败%rbp,但我不明白如何。提前致谢。

我在 64 位 Ubuntu 14.04 上运行 GCC 4.8.4。

0 投票
2 回答
1695 浏览

assembly - 当我们有一个红色区域时,为什么我们需要堆栈分配?

我有以下疑问:

正如我们所知,System V x86-64 ABI 在堆栈帧中为我们提供了大约一个固定大小的区域(128 字节),即所谓的 redzone。因此,我们不需要使用例如sub rsp, 12. 只需制作mov [rsp-12], X,仅此而已。

但我无法理解这一点。为什么这有关系?有没有必要sub rsp, 12没有redzone?毕竟,堆栈大小在一开始是有限的,那么为什么sub rsp, 12重要呢?我知道这使我们能够跟随堆栈的顶部,但在那一刻让我们忽略它。

我知道某些指令使用rsp值(例如ret),但在那一刻并不关心它。

问题的症结在于:我们没有红区,我们已经做到了:

有区别吗?

0 投票
2 回答
5775 浏览

assembly - x86-64 上的红色区域到底在哪里?

来自维基百科

在计算中,红色区域是函数堆栈帧中的一个固定大小的区域,超出了该函数不保留的返回地址。被调用函数可以使用红色区域来存储局部变量,而无需修改堆栈指针的额外开销。这个内存区域不能被中断/异常/信号处理程序修改。System V 使用的 x86-64 ABI 要求有一个 128 字节的红色区域,它直接在返回地址之后开始,包括函数的参数。OpenRISC 工具链假设有一个 128 字节的红色区域。

System V x86-64 ABI

%rsp 指向的位置之外的 128 字节区域被认为是保留的,不应被信号或中断处理程序修改。因此,函数可以将此区域用于函数调用之间不需要的临时数据。特别是,叶函数可以将这个区域用于它们的整个堆栈帧,而不是在序言和尾声中调整堆栈指针。这个区域被称为红色区域。

  • 给定这两个引号,红色区域是堆叠返回地址 上方还是堆叠返回地址下方

  • 由于这个红色区域是相对于 的RSP,它是否随每个 向下移动,是否随每个push向上移动pop

0 投票
1 回答
55 浏览

c - 在 Aleph One 上工作时,在 64 位系统上没有堆栈分配

我一直在搞乱 Aleph One 的“Smash the Stack for Fun and Profit”,发现在为我的 64 位处理器编译代码时,没有使用通常的“sub $VALUE, %”分配堆栈内存注册。”

这是函数源代码:

这是编译后的版本

如果我将 -m32 选项与 gcc 一起使用,为什么没有标准堆栈分配?

0 投票
2 回答
1927 浏览

assembly - 我可以从堆栈中间弹出吗?

在 x86 汇编语言中:

我假设我有一个正常的功能序言,请阅读

我知道我可以通过访问内存目标操作数来读取或写入寄存器,假设我想要第一个参数。我会做

从堆栈中获取 fe 一个整数参数。

那么为什么我不直接使用堆栈指针呢?

这会导致错误吗?这在任何情况下都使用吗?

我当然知道第一个操作的大小更小,因为它只有一个操作码mov而不是三个,但这不是问题的重点。

(编者注:mov eax, [ebp+8]是x86机器码中的3字节指令 add。/esp,imm8sub是3字节,pop eax是1字节。
mov eax, [esp+8]是4字节指令:与16位寻址模式不同,ESP可以是基址寄存器。但它确实需要一个 SIB 字节来对其进行编码。
这些都是现代 CPU 上的单微指令,不包括额外的堆栈同步微指令。)

为什么这样做是不好的做法?

0 投票
1 回答
765 浏览

c - Compiler using local variables without adjusting RSP

In question Compilers: Understanding assembly code generated from small programs the compiler uses two local variables without adjusting the stack pointer.

Not adjusting RSP for the use of local variables seems not interrupt safe and so the compiler seems to rely on the hardware automatically switching to a system stack when interrupts occur. Otherwise, the first interrupt that came along would push the instruction pointer onto the stack and would overwrite the local variable.

The code from that question is:

The assembly code generated by that compiler is:

The local variables are i at [rbp-0x8] and k at [rbp-0x4].

Can anyone shine light on this interrupt problem? Does the hardware indeed switch to a system stack? How? Am I wrong in my understanding?

0 投票
0 回答
82 浏览

c++ - 局部变量的堆栈指针下内存区域的可疑使用

我最近发现了关于 g++ 代码生成的局部变量的内存保留的不清楚的事实:变量放置在堆栈指针下方的地址处。

例如,当这个程序(main.cpp)被编译时:

通过命令:

带编译器

然后创建这个程序集(main.s):

如您所见,函数“foo”的局部变量被放置在“-16(%rsp)”...“-4(%rsp)”地址。

但是,据我所知,这些地址(在堆栈指针寄存器下方)是为流中断事件保留的,例如,用于信号处理。因此,堆栈指针下的内存区域随时可能发生不可预测的变化。因此,它不能用于局部变量存储。

请问有人可以澄清这个问题吗?

0 投票
1 回答
288 浏览

assembly - 进入新功能时rsp不动

当输入一个 C 函数时,我希望在反汇编中看到堆栈指针如何被减去足以为变量腾出空间,但没有;我只看到变量的地址是如何通过ebp直接访问的,当esp仍然指向ebp时。

我必须创建很多变量并初始化它们以让计算机认真对待,看看是如何产生大量不需要的空间的。差异真的是使用的空间量还是其他?如果是这样,仅当我要求大量空间时才需要通过移动 rsp 腾出空间?