Почему регистр rsp начинается с 0x7FFFFFFFFDFD0

я изучаю сборку x86, используя приведенный ниже код для тестирования, я вижу в консоли gdb, что регистр rsp, который указывает на вершину стека, начинается с 0x7FFFFFFFFDFD0, если я правильно понимаю, в коде я не использовал push или pop, который изменяет rsp, поэтому 0x7FFFFFFFDFD0 является значением по умолчанию, это означает, что у нас одинаковое количество байтов в стеке, но я использую Linux, где размер стека составляет 8 МБ.

section .text
global _start
_start:

mov rcx, 2
add rcx, 8

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

Когда ваша программа запускается, в стеке находится куча вещей (вспомогательные векторы ELF, аргументы командной строки, переменные среды). Это занимает место. Фактическая вершина стека, вероятно, 0x7FFFFFFFFFFFFFFF.

fuz 06.11.2022 23:22

Смотрите ASLR

dimich 06.11.2022 23:24

@dimich: GDB по умолчанию отключает ASLR; вот почему OP каждый раз видит одно и то же значение и почему оно так близко к верхней странице нижней канонической половины виртуального адресного пространства. ASLR изменит больше битов, чем то, где находится верхняя часть отображения 8M, а также сместит случайную величину на странице. (На самом деле не начинается с отображения 8M, но может расти до этого.)

Peter Cordes 06.11.2022 23:41

Пожалуйста, используйте заглавные буквы как обычно.

thb 07.11.2022 00:20
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
5
70
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Для 64-бит 80x86; обычно (см. примечание 1) можно использовать только 48 бит виртуального адреса. Чтобы упростить увеличение количества битов, которые можно использовать в будущих процессорах, не нарушая работу старого программного обеспечения; AMD решила, что неиспользуемые старшие 16 бит 64-битного виртуального адреса должны совпадать. Адреса, которые соответствуют этому, называются «каноническими адресами», а адреса, которые не соответствуют, называются «неканоническими адресами». Обычно (см. примечание 2) любая попытка доступа к чему-либо по неканоническому адресу вызывает исключение (общий сбой защиты).

Это дает виртуальное адресное пространство, например:

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

Это делает достаточно очевидным, что без рандомизации адресного пространства стек начального потока процесса (см. примечание 3) начинается с адреса, немного более низкого, чем самый высокий адрес, который может использовать процесс.

Разница между самым высоким адресом, который может использовать процесс, и адресом, который вы видите (0x7FFFFFFFDFD0), составляет всего 2030 байт; который (как упоминалось в комментарии Fuz) используется такими вещами, как вспомогательные векторы ELF, аргументы командной строки и переменные среды, которые потребляют часть стека до запуска вашего кода.

Примечание 1: Intel недавно (около 2 лет назад?) создала расширение, которое (если поддерживается ЦП и ОС) позволяет использовать 57 бит виртуального адреса. В этом случае «неканоническая дыра» сокращается, а самый высокий виртуальный адрес, который может использовать процесс, будет увеличен до 0x00FFFFFFFFFFFFFFFF.

Примечание 2. Совсем недавно (около 6 месяцев назад?) Intel создала расширение, которое (если оно поддерживается ЦП и ОС и включено для процесса) может игнорировать неиспользуемые старшие биты адреса ЦП; так что программное обеспечение может упаковывать другую информацию в эти биты (например, может быть «тип данных») без явного маскирования перед использованием.

Примечание 3. Поскольку операционные системы обычно не обеспечивают изоляцию между потоками (например, любой поток может повредить стек любого другого потока или «локальные данные потока» любого другого потока); если вы создадите больше потоков, они не смогут использовать один и тот же адрес «верхней части стека».

Другие вопросы по теме