@6y6eH4uk

Как низкоуровневый код использующий стек узнает откуда он начинается?

Когда операционная система запускает процесс, она выделяет ему память под стек, но как низкоуровневый код узнает начальный адрес стека?
9Fk3Z.png
Если взять за основу эту схему, то становится понятно, как код процесса может узнать адреса текста, инициализированных данных, неинициализированных данных и кучи (просто прибавлять кол-во выделенной с помощью системных вызовов памяти к концу BSS). Однако, не ясно, как становится известен адрес стека и аргументов командной строки.

Если немного пораскинуть мозгами, то самый логичный ответ на этот вопрос - при запуске процесса ОС сама настраивает (думаю, что в данном примере не важно какая именно ОС, но я отталкиваю от примера linux) регистры стека на нужные значения, однако у меня нет опыта программирования на ассемблере (только теория), а все источники, которые я читал явно на это не указывают, поэтому я не могу быть уверен в этом предположении. Ну и если следовать этому предположению, то и адреса аргументов командной строки можно узнать отсчитав их от адреса стека.

Если все мои догадки верны, то хотелось бы получить утвердительный ответ от точно знающих это людей, если же используется другой способ, то хотелось бы получить подробное его описание.
  • Вопрос задан
  • 453 просмотра
Решения вопроса 2
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
Если взять за основу эту схему, то становится понятно, как код процесса может узнать адреса текста, инициализированных данных, неинициализированных данных

Если мы говорим про обычные (не PIE) исполняемые ELF-файлы, то они слинкованы под конкретный адрес куда они будут загружены, и все адреса внутри одного исполняемого файла посчитаны заранее. Поэтому загрузка адреса функции или пременной в секции данных -- это просто загрузка константы в регистр.

и кучи

С кучей всё по-другому, потому что куча и объекты в ней полностью динамические. Выделение памяти для кучи -- это всегда системный вызов, который возвращает адрес выделенной памяти (и sbrk, и mmap).

не ясно, как становится известен адрес стека и аргументов командной строки

они инициализируются ядром ОС, согласно ABI, см. например, ABI x86_64, раздел 3.4.1.
Ответ написан
Комментировать
saboteur_kiev
@saboteur_kiev Куратор тега Linux
software engineer
Обычно для работы со стеком процессор использует регистр стека (Stack Pointer register).

Следовательно операционная система устанавливает этот регистр для процесса при его запуске и инициализации.
В современных процессорах регистров стека может быть несколько (я могу ошибаться, но возможно даже несколько на каждое ядро).
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
freeExec
@freeExec
Участник OpenStreetMap
Странно, что у вас возник вопрос по поводу стека, не не как процесс начинает свою работу именно с нужного адреса, а не абы откуда? Многое эти настройки хранятся в заголовках исполняемых файлов: и размер стека и адрес точки входа и какие библиотеки и куда их загрузить. И всеми этими подготовками занимается загрузчик в ОС.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы