C/C++

Знатоки ассемблера и си, плюсов прошу помочь

Я не понимаю. Мы пишем любой код на c/c++. Компилим его. Запускаем. Операционная система выдаёт нам сколько то байтов начиная с определённого адреса. Все хорошо. Мы в том коде объявили переменную. Как бинарник узнает по какому адресу нужно создавать переменную? Мало ли тот адрес уже занят? Как наш бинарник узнает какое ему место выделила oc? И получается что бинарник может обращаться не по "абсолютному" адресу, а по "частичном" (ну к байтам памяти). И если да, то как это делается?
Grafinya Grafinya
Grafinya Grafinya
261
> Мало ли тот адрес уже занят
и чем же, интересно?
каждый процесс работает в своём собственном виртуальном адресном пространстве, отделённом от ядра и остальных процессов
в момент запуска программы в этом пространстве есть только то, что ОСь подготовила, типа стека, загруженного ядром с диска исполняемого кода и всяких других полезных маппингов
почитай про виртуальную память и страничную организацию памяти
Александр Саватеев
Александр Саватеев
36 956
Лучший ответ
Grafinya Grafinya То есть если у каждой программы свой виртуальный адрес, что тогда будет показано, если я с двух программ записал бы что нибудь в память 0xb8000(адрес видео буфера (условимся что винда дала нам к нему доступ))?
Ну э... код, который генерирует компилятор, там в основном относительные адреса.

Исключение составляют вызовы библиотечных функций и глобальные переменные. Чтобы разрулить это, код на самом деле не совсем честный. Функция main() / WinMain() - на самом деле не точка входа. Сначала выполняется "загрузчик", который выделяет память malloc() или LocalAlloc() для глобальных переменных и для стека, подрубает библиотеки LoadLibrary() и даёт правильные адреса функциям GetProcAddress(). Это для Си, в плюсах там ещё более толстая прокладка для обработчиков исключений, сборщиков мусора и прочей магии++..

У тебя может быть своя точка входа и свой нестандартный "загрузчик". Так поступает, например, драйвер OpenCL, который загружает правильные библиотеки в зависимости от того, какая видеокарта у тебя установлена (nVidia или AMD).

https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getprocaddress
Для всех статических объектов память выделяется в момент запуска программы, вне зависимости от того где и в каком порядке они объявлены в коде. Для динамических объектов также выделяется область памяти (т. н. stack), если программа превысит ее объем произойдет критическая ошибка.
>> Как бинарник узнает по какому адресу нужно создавать переменную?

Зависит от кода созданного компилятором. Обычно код делится на отдельные блоки (обычно такие же как область видимости у кода) и выполняется по этим блокам.
Перед выполнением каждого отдельного блока код созданный компилятором совершает работу со стеком и регистрами процессора. Вот в этом стеке обычно и размещаются все локальные данные и каждый блок кода уже заранее знает в каком порядке размещены необходимые переменные и константы. Большие объемы данных обычно размещаются в так называемой куче и доступны через указатели на адреса памяти которые возвращает менеджер памяти операционной системы. т. е. в стеке есть место для указателей и смещений а сами данные в куче лежат.

>> Как бинарник узнает по какому адресу нужно создавать переменную?
Создавать переменную "бинарник" по попросту не может потому что он программа он просто по шагам исполняет точные инструкции где указаны или логически вычисляются необходимые адреса памяти над данными из которых нужно проводить операции и в какие адреса записать результат.

И понятие "создавать переменную" абстрактное и нужно только человекам что бы упрощать понимание алгоритма исполнения кода.
Vladimirov Vlad
Vladimirov Vlad
12 592