Каждая программа разделена на несколько сегментов, таких как:

  • сегмент кода
  • сегмент данных
  • сегмент стека
  • сегмент кучи

Но кто был ответственен за это развитие? Компилятор и компоновщик должны поддерживать этот диалог с этими сегментами.

  • была ли она впервые реализована разработчиками компилятора и компоновщика, а ранние операционные системы ее использовали?

или же

  • была ли она впервые реализована разработчиками операционной системы, а разработчикам компиляторов и компоновщиков требовалась корректировка?

1 ответ1

1

Это было частично основано на дизайне процессора.  В 1980-х годах большинство компьютеров имели 16-битную архитектуру, поэтому указатель мог обращаться к виртуальному адресному пространству размером 2 16 (65536) байтов.  Это, естественно, считалось слишком ограничительным.  Когда сегмент коды отделен от других, вы можете иметь 2 16 байт ценности коды (инструкция) и 2 16 байт данных, что меньше плохо.

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

  • Инициализированные данные, в том числе
    • Строки (например, printf("Hello, world\n");),
    • Инициализированные переменные (например, int i = 42;) и
    • В некоторых случаях константы, используемые в коде (например, y = x + 17;),
  • Неинициализированные переменные (например, int j; char mydata[80]; в статическом / глобальном контекстах),
  • Динамически выделяемая память (malloc , new) и
  • Стек (аргументы функций, информация о сохранении / восстановлении и локальные переменные).

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

Другая проблема заключается в том, что процессор Intel 8086 (прапрадедушка Pentium) требовал, чтобы каждый сегмент был одним большим непрерывным блоком памяти.  Ядро Unix состоит из одного большого блока кода и одного большого блока данных (инициализированных данных и неинициализированных переменных), но для каждого процесса он использует отдельный стек.  Поэтому для 8086 требовалась возможность иметь стек в другом сегменте, чем все остальные данные.

В интернете много информации об этом.  Например, в Википедии:

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .