【发布时间】:2023-04-02 17:54:01
【问题描述】:
我试图了解堆栈的内存页面是如何分配/分配的。
我编写了以下概念验证 C 代码,显然会导致分段错误(在 x86_64 Linux 上):
#include <string.h>
int main()
{
char a;
memset( (&a - 4444444), 0, 3333333 );
return 0;
}
以下汇编代码片段(AT&T 语法)是由 gcc 从上面的 C 程序生成的:
subq $16, %rsp
leaq -1(%rbp), %rax
subq $4444444, %rax
movl $3333333, %edx
movl $0, %esi
movq %rax, %rdi
call memset
如果我在调用memset之前手动添加subq $5555555, %rsp:
subq $16, %rsp
leaq -1(%rbp), %rax
subq $4444444, %rax
movl $3333333, %edx
movl $0, %esi
movq %rax, %rdi
subq $5555555, %rsp /* added manually */
call memset
然后分段错误消失了,因为在减去rsp 寄存器后分配了堆栈的虚拟内存页面导致一些硬件异常并调用了分配的异常处理程序(当然,在内核空间中)。
我知道在这里调用memset 会导致“次要页面错误”异常。但这是另一回事(即分配物理内存页面)。
我的问题是:调用subq $5555555, %rsp 时产生了哪个异常?我建议这将是“堆栈错误”异常,但我没有找到确切的证据。
【问题讨论】:
-
x86 甚至没有这些寄存器......也许你使用了错误的架构标签?
-
@Ben Voigt 我有
Intel® Core™ i3-2328M CPU @ 2.20GHz × 4,所以它是 x86 寄存器。 -
RSP 不是 x86 寄存器...它仅在长模式下可用,而不是 x86。
-
@MartinRosenau:是的,有一个标签x86_64。
-
@glglgl 谢谢。我移动了“更新”部分来回答。
标签: linux assembly linux-kernel x86-64