我正在学习x86汇编,使用下面的代码进行测试,我在GDB控制台中看到指向堆栈顶部的RSP寄存器从0x7FFFFFFD0开始,如果我理解正确,在代码中我没有使用PUSH或POP来修改RSP,所以0x7FFFFFFFD0是默认值,这意味着我们在堆栈中有相同的字节数,但我使用的是Linux,其中堆栈大小为8MB

section .text
global _start
_start:

mov rcx, 2
add rcx, 8

mov rax, 0x1
mov rbx, 0xff
int 0x80

推荐答案

对于64位80x86;通常(见注1)只能使用48位的虚拟地址.为了在不 destruct 旧软件的情况下更容易地增加future 处理器中可以使用的位数,AMD决定64位虚拟地址中未使用的最高16位应该匹配.符合这一要求的地址被称为"规范地址",而不符合这一要求的地址被称为"非规范地址".正常情况下(见注2),任何访问非规范地址上的任何内容的try 都会导致异常(一般保护故障).

这提供了如下的虚拟地址空间:

0x0000000000000000 to 0x00007FFFFFFFFFFF = canonical (often "user space")
0x0000800000000000 to 0xFFFF7FFFFFFFFFFF = non-canonical hole
0xFFFF800000000000 to 0xFFFFFFFFFFFFFFFF = canonical (often "kernel space")

这使得很明显,在没有地址空间布局随机化的情况下,进程的初始线程堆栈(参见注释3)从略低于进程可以使用的最高地址的地址开始.

进程可以使用的最高地址和您看到的地址(0x7FFFFFFDFD0)之间的差异只有2030个字节;正如Fuz的注释所提到的那样,ELF AUX向量、命令行参数和环境变量等使用这些地址的东西在代码开始之前消耗了堆栈的一部分.

Note 1: Intel recently (about 2 years ago?) created an extension that (if supported by CPU and OS) makes 57 bits of a virtual address usable. In this case the "non-canonical hole" shrinks, and the highest virtual address a process can use would be increased to 0x00FFFFFFFFFFFFFF.

Note 2: More recently (about 6 months ago?) Intel created an extension that (if supported by CPU and OS and enabled for a process) can make the unused higher bits of an address ignored by the CPU; so that software can pack other information into those bits (e.g. maybe a "data type") without doing explicit masking before use.

Note 3: Because operating systems typically provide no isolation between threads (e.g. any thread can corrupt any other thread's stack or any other thread's "thread local data"); if you create more threads they can't use the same "top of stack" address.

Linux相关问答推荐

C++调试器如何知道如何在源代码和可执行文件之间映射行?

为什么waitpid(2)可以指定非子进程?

在 Bash 中使用 shell 脚本从文件中解析版本号

如何修复 script(1) 实用程序输出的换行符?

在 cURL 中使用的确切位置将字节分成一些范围部分

如何使用 ftrace 过滤查看函数上方的调用堆栈?

为什么`__vfprintf_internal`(`stdio.h`中的`printfn`)强制`$rbp`在我的x86-64机器上向前跳转6313864字节?

什么命令用于在linux中创建或修改具有指定文件大小的多个文件

如何判断 Linux 机器是否支持 AVX/AVX2 指令?

如何使用完整路径或文件名显示 grep 结果

在亚马逊 ec2 linux 微型实例上的 virtualenv 中安装 scipy 时遇到问题

使用单个命令打开 .tar.gz 文件

如何设置errno值?

Ant 找不到 javac,在 Ubuntu 上不会设置 JAVA_HOME

如何显示正在运行的进程列表 Python?

使用 C++ 代码在 Linux 中清除终端

什么是适用于 Linux 的好的 Prolog IDE?

Android - 找不到命令

如何使用终端打开-虚线文件名?

如何用逗号而不是空格分割列表