Вступление
Небольшое предупреждение! Субъективно, эта статья содержанием немного не удовлетворяет смыслу переданному в заголовке. Я буду говорить не просто о том "Как запускаются команды?", а покажу часть внутреннего мира операционных систем и покажу принципиальную разницу в их работе.
Это моя первая статья, вырванная из моего дневника, который я веду пока что закрыто, особо не выкладывая заметки в публичный доступ.
Взгляд на CP/M
Начну очень издалека, поскольку
считаю важным немного заранее обозначить моменты, которые будут нужны.
Во времена 1970-ых годов, когда для процессоров Intel 8080 появилась на свет операционная система CP/M (полн. "Computer Program/Monitor").

Процессор i8080 (полн. "Intel 8080") был 8-разрядным,
соответственно объемы обрабатываемой памяти были не такими уж и большими. Все написанные под эту ОС программы помещались в один файл команды и весили не больше чем 64Кб.
Раз глава про управление памятью, сразу вижу необходимым обозначить структуру оперативной памяти после загрузки CP/M.
+----------------------------+ <-- 0xFFFF
| BIOS |
| Аппаратные драйвера BDOS |
+----------------------------+ <-- 0xF200
| BDOS |
| CP/M двоичный интерфейс |
+----------------------------+ <-- 0xE400
| Интерпретатор комманд |
+----------------------------+ <-- 0xDC00
| TPA |
|Область запущенной программы|
+----------------------------+ <-- 0x0100
| LowMem Storage |
| То, что нас интересует |
+----------------------------+ <-- 0x0000
Объясняю по-порядку все, что может вогнать в тупик:
BDOS
(полн. "Basic Disk Operating System") - это лишь часть CP/M, а не второе название системы.
Компонент BDOS
действительно для первого раза лучше принять за двоичный интерфейс, так как команды CLOSE
, READ
, SELECT
, и др, это "именно в эту дверь".
BIOS
(полн. " Basic Input/Output System") это буквально то, о чём могут подумать практически все, кто это читает. Но сразу обозначусь, в понимании CP/M это её часть, а не отдельное "нечто" и POST.
Выглядит немного необычно, не так ли?
Интересно в организации ОЗУ самое первое (или последнее) пространство -- "Low Memory Storage".
Низкоуровневая память или "Low Memory Storage"
бьется на разделы тоже.
На самом деле, эту часть лучше пропустить, поскольку много кого это загонит в тупик.
Я оставлю информацию, которую я нашел в архивах, но лучше пропустить это мимо глаз.
+----------------------------+ <-- 0xFF
| Файловый буфер | <-- 0x80 длинна
| | 0x81-0xFF
| | Список ASCII строк
+----------------------------+
| FCB (File Control Block) |
+----------------------------+
| ??? |
+----------------------------+
| BIOS рабочее пространство |
+----------------------------+
| Вектор перезагрузки #7 | <-- Использовался
| Вектор перезагрузки #6 | отладчиком
| . |
| . |
| Вектор перезагрузки #1 |
+--------+------+----+-------+
| F200 | Disk | IO | E400 |
+--------+------+----+-------+ <-- 0x00
Взгляд CP/M на Программы
И так, программа для CP/M
это файл с расширением ".COM
".
Файл "
.COM
" (сокр. "Command") - это монолит кода. Внутри он никак не разграничен и не имеет опознавательных знаков или подписей. В CP/M может занимать адреса до верней границы TPA (полн. "Transistent Program Area").
Напишем простой пример команды, чтобы показать структуру:
.z80 ; <-- Требуется Z80;
WRITE equ 9h ; <-- CP/M функционал;
_BDOS equ 5h ; <-- "Системное прерывание";
org 100h ; <-- Отступ в ОЗУ на 255 байт;
ld C, WRITE
ld DE, hello
call _BDOS ; syscall;
rst 0h ; Выход.
hello:
db "Hello World!$"
end
На всякий случай, команда ld
(полн. "LOAD") выполняется как mov
из IA-32, а не как lea
или push
. Команда rst
(полн. "RESET") переходит по адресу и запоминает предыдущее значение в стэке.
Стрелочками в комментариях я обозначил, что здесь определенно "делает погоду".
Для CP/M
в структуре программы есть три
немало важные детали.
требование к архитектуре;
двоичный интерфейс (англ. "Application Binary Interface") системы;
смещение программы (
ORG 100h
) и установка входной точки.
Начало TPA -->|
|
<-- Low Memstr -->|
+------------------+-----------------+
| ... | ... | ... | Код программы |
+------------------+-----------------+
|<-- 255 байт -->| |
Сама программа должна будет лежать в области TPA, как из таблицы видно, а выделенная область оказывается лежит в Low Memry Storage.
Эта таблица называется ZPCB
(полн. "Zero Page Control Block") или PPA
(полн. "Program Prefix Area") для поздних релизов этой системы.
Представьте себе почтовый ящик в подъезде по таковому адресу (адрес 0x0000-0x00FF
это Low Memory Storage)... Когда приходит жилец (загружается комманда), почтальон (Операционная Система CP/M
) кладет в этот ящик конверт с важной информацией именно для этого жильца. Конверт лежит в ящике. Жилец приходит "домой" (загружается по 0x0100 смещению) и первым делом заглядывает в свой ящик за конвертом (Содержит области памяти ещё и ZPCB
).
Загрузка и регистрация .COMманды в CP/M
Когда CP/M загружает .COM файл
ОС инициализирует PPA/ZPCB в Low Storage. Она заполняет поля, относящиеся к запуску программы. Это могут быть текущий диск, FCB1
, FCB2
, хвост командной строки, системные векторы BDOS
и BIOS
для этого запуска.
ОС загружает бинарный образ .COM файла начиная с адреса 0x0100. Именно благодаря ORG 100h
комманде процессору.
Код программы ожидает, что по 0x0000-0x00FF уже лежит корректно заполненная PPA.
ОС устанавливает регистры процессора: PC
(полн. "Program Counter") становится по адресу точки входа, SP
(полн. "Stack Pointer") - обычно глядит в конец доступной программе памяти (или в другое место, указанное в BDOS
).
Zero Page Control Block или Program Prefix Area (CP/M)
Теперь более детально опишу структуру ZPCB/PPA. В документации к CP/M
её действительно называют "нулевой страницей", поэтому непобоюсь написать так же.
Данную структуру в более полном виде (описания и типы данных) можно найти в архивах или на сайте с документацией.
Название поля |
Размерность |
Описание |
---|---|---|
|
|
|
|
|
Адрес сегмента кодовой группы |
|
|
Установлен, если программа в одном сегменте |
|
|
|
|
|
|
|
||
|
|
Дескриптор группы |
|
|
Дескриптор группы |
|
|
Дескриптор группы |
|
|
Дескриптор группы |
|
|
|
|
|
Диск с которого запущена программа |
|
|
Адрес ключевого слова для |
|
|
Длинна ключевого слова |
|
|
|
|
|
|
|
|
|
|
|
Количество аргументов |
|
|
Аргументы командного интерпретатора |
Теперь укажу условные обозначениям:
Префикс
b...
- этоBYTE
или машинное слово, размером в 8 бит.Префикс
h...
- это дескриптор (указатель) инкапсулирущий настоящий адрес данных.Нотация
[type; n]
взята из Rust, так как нахожу это правило универсальными и более понятными глазу, чем типы данных Windows. Это массивtype
-ячеек вn
-ом колличестве.Префикс
dw...
- этоDWORD
, а неdefine WORD
! Другими словами - машинное слово размером в 32-бит (на момент IA-32e).Тип данных
size
тоже взят из Rust. Путь Этот тип будет для всех, как максимально возможное машинное слово для процессоров тех времен и самой ОС. (имеется ввидуIntel 8080
иIntel 8086
). Все зависит только от того "Где работает ОС и какая ОС".
Как видно, тот самый "конверт" с письмом на самом деле содержит вот такие поля данных.
Очень важно запомнить, что таблица PPA
в CP/M
только одна. Она располагается в определенном месте,
имеет очень большой смысл в жизненном цикле программы.
Только в CP/M-86, ZPCB
(или PPA
) начинает поведением быть похожа на PSP таблицу из xx-DOS
.
Взгляд на xx-DOS
Сейчас речь пойдет в основном про PC-DOS
и MS-DOS 2.0
,
так как тема разговора и подопытные совпадают.

В предыдущей главе было описано более-менее подробно, как же понимает CP/M файлы комманд. Раз уж выделена отдельная глава для DOS, логично предположить, что поведение COM
файлов в DOS и CP/M разное.
Внимание, здесь не будет описан механизм чтения OVERLAY
частей программ, потому что рассматриваются немного другие времена
и лишние объяснения про страницы памяти будет избыточно.
К сожалению опять собираются грозовые тучи теории и истории, и придется их переждать, ведь без них всё высохнет и потеряет смысл.
Очень важная отличительная черта от предыдущего "подопытного" в организации процессов. Положим, MS-DOS
пусть и является однозадачной, по определению, но каким-то образом же может удерживать драйверы и DOS-extender'ы? Ведь да?
В оперативной памяти DOS
держится приблизительно таким образом:

Здесь логика местами похожа на CP/M
, но в глаза бросается строгое разграничение программной памяти. Отныне все нулевые страницы ~управляемой~ памяти пренадлежат области "Program Memory".
Писать про жизненно необходимые MSDOS.SYS
, CONFIG.SYS
, COMMAND.COM
не буду. Они как раз видны на схеме вооруженным глазом.
...и Взгляд xx-DOS на программы
Для 16-разрядных DOS при выполнении файла код,
данные и стек находятся в одном и том же 16-битном сегменте.
Поэтому размер файла не может превышать 65280 байт (что на 256 байт меньше размера сегмента — или 216 байт).
Простейшая программа для DOS на Flat Assembly (сокр. "FASM")
диалекте выглядит приблизительно так:
use16
DosWrite equ 9h ;<-- Функционал DOS/2.0
org 100h ;<-- Точка входа 0x100
mov dx, hello
mov ah, DosWrite;DOS call.
int 21h ;syscall. (вызов DOS функции)
mov ax, 4C00h ;AH = 4Ch, AL = 00h.
int 21h ;syscall (вызов DOS функции)
hello db 'Hello, world!$'
Стрелочками я обозначил практически те же самые места, такие как смещение и обозначение точки входа (не смещение точки входа), и ABI системы. С виду структурно это похоже на предыдущий образец. Разница только в архитектуре и в системном BI.
Впринципе, отличить .COM
ы можно только при детальном анализе сырого содержимого, так как дисковых операционных систем успело
появиться достаточно, и скорее всего системный интерфейс у всех отличается. Можно ловить их по опкодам прерываний, как делал это я, можно придумать более умную стратегию.
Загрузка регистрация .COMманд в MS-DOS 2
И так, идея комманды не меняется. .COM
это все еще PIE-монолит (исполняемый файл независящий от точки входа).
При загрузке файла .COM
в свободной области ОЗУ, операционная система
создает несколько структур.
Структура "перед" кодом программы - это PSP
(полн. "Program Segment Prefix"), что отвечает за состояния
выполняемого файла и предоставляет список аргументов командной строки.
A:\> COMMAND.COM /A /B /C
argv[ 0 ][1][2][3]
В области ОЗУ будет приблизительно такая схема ячеек:
+-----+-----+----------+----------------------------------+-----+
| ... | ... | PSP | [Программа] [STACK] | ... |
+-----+-----+----------+----------------------------------+-----+
| 256 байт | Размер Программы |
| |
| |
Начало -->| Конец области программы -->|
Как видно из таблицы, именно поэтому образец программы начинался с org 100h
.
Сама программа в ОЗУ разбивается по области кода, данных и стэка.
Ещё раз: здесь не рассматривается OVERLAY
части, потому что это здесь избыточно.
Но в следующий раз, возможно про .EXE
файлы и MS-DOS 2.0
я это обязательно возьмусь показательно разбирать.
В документации DOS
я не встретил упоминания "нулевой страницы", поэтому назову структуру "как есть".
Program Segment Prefix (PSP)
Теперь спускаемся ещё дальше в специфику DOS и CP/M семейств.
С первых интернет ресурсов буквально представляется полная информация о PSP
секции. Представлена ниже:
Название |
Размер |
Описание |
---|---|---|
|
|
|
|
|
Сегмент расположенный после выделенной памяти |
|
|
|
|
|
Содержит |
|
|
Адрес |
|
|
Адрес |
|
|
Адрес обработчика ошибок |
|
|
Сегмент PSP процесса-родителя |
|
|
Общее расположение пространства памяти |
|
|
Сегмент переменных среды |
|
|
Маска вида |
|
|
Максимальное количество открытых файлов |
|
|
Адрес обработчика ручных записей |
|
|
|
|
|
Опкод прерывания ( |
|
|
Номер прерывания. |
|
||
|
|
Первый закрытый |
|
|
Перезаписывается, если открыт |
|
|
Колличество аргументов коммандной строки |
|
|
Аргументы коммандной строки. Всегда заканчивается на |
В CP/M и DOS главах упомянались FileControl
-блоки, но почему-то ни слуху - ни духу, о них в разборе... Исправляюсь.
Специально выделю два подраздела для неизвестных структур.
File Control Block (FCB)
FCB (File Control Block) в DOS — структура, в которой поддерживается состояние открытого файла. Она находится внутри памяти программы, которая использует файл, а не в памяти операционной системы.
Такое решение позволяет процессу иметь одновременно несколько файлов, если он может выделить достаточно памяти для FCB на каждый файл
В зависимости от версии MS-DOS
сама структура потерпела изменения:
Я показываю структуру FCB такой, какая она есть в MS-DOS 2.0
, поскольку там присутствуют поля случайного доступа.
#pragma pack(push, 1)
struct FCB_STANDARD {
unsigned char drive; // 00: 0 = default, 1=A, 2=B, ...
char filename[8]; // 01-08: имя файла (лево выровнено, пробелы в конце)
char extension[3]; // 09-0B: расширение (лево выровнено, пробелы)
unsigned short current_block; // 0C-0D: текущий блок (начиная с 0)
unsigned short record_size; // 0E-0F: размер логической записи в байтах
unsigned long file_size; // 10-13: размер файла в байтах
unsigned short date; // 14-15: дата (формат: см. выше)
unsigned short time; // 16-17: время (формат: см. выше)
unsigned char reserved[8]; // 18-1F: зарезервировано (зависит от версии)
unsigned char current_record; // 20: текущая запись в блоке (0-127)
// MS-DOS 1.25 не имеет поля случайных записей
unsigned long random_record; // 21-24: случайная запись (относительно начала файла)
}
#pragma pack(pop)
У блока управления файлом в DOS 2.0
есть расширенный (мне кажется лучше расширяющий) подраздел.
#pragma pack(push, 1)
struct FCB {
unsigned char signature; // -7: 0xFF
unsigned char reserved[5]; // -6 - -2: зарезервировано
unsigned char attribute; // -1: атрибут файла
FCB_STANDARD fcb; // 00-24: стандартный FCB
}
#pragma pack(pop)
Советую думать, что FCB
это своеобразная карточка книги в библиотеке,
а расширенный FCB это пометка [СЕКРЕТНО]. Увы, подробнее об этом в другой раз.
Таблицы процесса (JFT и SFT)
Изначально этот материал я долго не мог уложить в голове, и взял его практически "как есть", без обработки. Но со временем дополнения появились.
Для обеспечения доступа к открытым файлам MS-DOS
использует системные таблицы двух типов.
Таблица SFT
(полн. "System File Table") содержит записи о всех файлах, в данный момент открытых программами пользователя и самой ОС.
Эта таблица хранится в системной памяти, число записей в ней определяется параметром FILES
в файле конфигурации CONFIG.SYS
, но не может превышать 255
.
Если один и тот же файл был открыт несколько раз (неважно, одной и той же программой или разными), то для него будет несколько записей в SFT
.
Каждая запись содержит подробную информацию о файле, достаточную для выполнения операций с ним. В частности, в записи SFT содержатся:
копия информации о файле;
адрес записи (сектор и номер записи в секторе);
текущее положение указателя чтения/записи;
номер последнего записанного или прочитанного кластера файла;
адрес в памяти программы, открывшей файл;
режим доступа, заданный при открытии.
Кроме того, в записи SFT
содержится значение счетчика ссылок на данную запись из всех таблиц JFT
, речь о которых пойдет позже. Когда этот счетчик становится равным нулю, запись SFT
становится свободной, поскольку файл закрыт.
В отличие от единственной SFT
, таблицы JFT
(полн. "Job File Table")
создаются для каждой запускаемой программы,
поэтому одновременно может существовать несколько таких таблиц.
Теперь к одному из главных вопросов: "Откуда в однозадачной MS-DOS
могут взяться одновременно
несколько программ?"
Ответ прост: когда одна программа запускает другую,
то в памяти присутствуют обе.
Таблица JFT
имеет простейшую структуру: она состоит из однобайтовых
записей, причем значение каждой записи представляет
собой индекс (номер записи) в таблице SFT
.
Неиспользуемые записи содержат значение 0xFF
.
Размер таблицы по умолчанию составляет 20 записей (байт),
но может быть увеличен до 255.
Сама JFT находится в PSP
области. Если рассматривать поближе
часть ОЗУ где находится процесс, его структура будет такова:
+-----+-----------------------------------------+-----------+-----+
| ... | [argv]; argc.....[1; 6; 2; FF; FF;].... | Программа | ... |
+-----|------------------|----------------|-----|-----------+-----+
| | <-- JFT --> | | |
| 20 байт | |
| | |
| <-- Начало PSP Конец PSP -->| |
| <-- Начало Конец управляемой памяти --> |
Что происходит с файлами при завершении программы,
которая их открыла? Это не важно.
В любом случае ОС должна при завершении программы закрыть
все её файлы. Как ОС узнает, какие файлы следует закрыть?
Достаточно просмотреть таблицу JFT завершаемой программы и
найти там все записи, отличные от 0xFF
.
Вывод
Это было большое и насыщенное для меня путешествие в NTVDM (полн. "Windows NT Virtual DOS Machine"), тонкости MS-DOS и её предков, но то, что я нашел на просторах интернета, возможно скоро канет в Лету. Пытаться найти мелочи жизни и как-то уложить их в голову, а потом и сюда.
Я приведу таблицу итогов для .COMманд, и это самая последняя таблица в этом документе.
Характеристики COM |
CP/M |
DOS |
---|---|---|
Подпись |
нет |
нет |
Точка входа |
везде |
везде |
Секции |
нет |
нет |
Нулевая страница |
|
|
Ареал обитания |
|
|
В целом, и так понятно, что загрузить программу из MS-DOS 2.0
в чужеродной среде не получится, поскольку нет слоя совместимости системного интерфейса.
Если бы даже архитектуры программ были одинаковы (например сборщик для Intel 8086
), то разногласия в вызовах уже бы помешали злодеянию.
Обратная совместимость для CP/M
комманд в DOS была, и некоторые поля PSP
структуры существуют только для её обеспечения.
Со временем ZPCB/PPA
таблица в CP/M-86 станет похожа на .PSP
раздел, а сам формат таблицы .PSP
станет родителем таблицы релокаций и первых файлов .EXE
- MZ-исполняемых файлов.
DOS
системы продолжут существовать и станут самостоятельнее, появится BW-DOS
с новым форматом исполняемых файлов, а Microsoft и IBM придумают NE-сегментные файлы.
Источники
CP/M ZeroPage control block;
Комментарии (11)
blueboar2
19.08.2025 14:18Как-то странно, автор пишет про CP/M, потом про DOS, а в выводе - погружение в NTVDM. Это, конечно, слой совместимости со старыми системами, но о нем вообще раньше ни слова не было, откуда оно взялось?
Jijiki
19.08.2025 14:18а как же устройство терминала, оно там было? комманды и вся обвязка на минимальной ОС может (по моему мнению должна быть обвязана вокруг терминала)
тоесть можно изучать ОС начиная с терминала например PTY(примитивный VT convention - escape sequences ANSI - шрифт/стили, положение курсора, очистка) - цель получить сессию с привилегиями пользователя, чтобы получить доступ к stdin/stdout/stderr - тоесть системные потоки этого родителя с привилегиями пользователя через командную оболочку
а уже терминал запускает оболочку - sh, csh и тд
чтобы видеть привествие )
PTY Slave: /dev/pts/2 You can install extra packages for FreeBSD by using the ports system. If you have installed it, you can download, compile, and install software by just typing # cd /usr/ports/<category>/<portname> # make install && make clean as root. The ports infrastructure will download the software, change it so it works on FreeBSD, compile it, install it, register the installation so it will be possible to automatically uninstall it, and clean out the temporary working space it used. You can remove an installed port you decide you do not want after all by typing # cd /usr/ports/<category>/<portname> # make deinstall as root. например )
SIISII
19.08.2025 14:18В минимальной ОС терминала может не быть вообще -- он не всегда нужен (да и не только в минимальной). Во всяком случае, терминал в привычном понимании.
И уж точно изучать ОС с терминала -- путь неверный. Хотя б потому, что терминал "стоит сверху" многих фундаментальных вещей типа управления памятью, управления процессами/потоками, управления вводом-выводом... А "оболочка" -- просто прикладная (по своему месту в системе, хотя и не по функциям) программа
Jijiki
19.08.2025 14:18начал изучать сам с устройства передачи команд через терминал, сделал прототип(pty-+sh получил всё что хотел и сессию и историю и всё что даёт терминал с вводом пароля ) и понял что это хороший путь для изучения полной ОС, потомучто минимальная ОС, если запустит приглашение и в ней будет уже всё обвязано по привилегиям и сигналам/потокам, начиная от старта биоса оптимальный путь - запускать терминал после инициализации оборудования, и дать возможность видео ускорения, тоесть запуска видео драйверов(я просто так для себя понял, если ошибся - понял)
например на OpenIndiana сегодня до сих пор есть терминал тоже
kmatveev
19.08.2025 14:18Отличная статья. Надеюсь, что автор простит меня, если я немного подушню.
На всякий случай, команда
ld
(полн. "LOAD") выполняется какmov
из IA-32, а не какlea
Для синтаксиса с меткой
ld reg, label
она выполняется именно какlea
, то есть загружает именно адрес, а не значение. MASM-синтаксис дляmov reg, label
загружал значение, хранящееся в памяти по метке.ОС загружает бинарный образ .COM файла начиная с адреса 0x0100. Именно благодаря
ORG 100h
комманде процессору.Нет. Директива ORG указывает ассемблеру, что метки нужно пересчитывать в адреса таким способом, будто код, располагающийся после директивы ORG, размещён по адресу, указанному в этой директиве. А CP/M загружает бинарный образ .COM файла просто всегда с адреса 0x100. И, что очень важно, этот адрес и является точкой входа (не увидел упоминания этого факта).
И так, идея комманды не меняется.
.COM
это все еще PIE-монолит (исполняемый файл независящий от точки входа).Эээ, вообще PIE означает "position-independent executable" (исполняемый код, не привязанный к адресу загрузки) и к COM-файлам никакого отношения не имеет ни в CP/M, ни в MSDOS. Для CP/M файл будет загружен в абсолютный адрес 0x0100, так что нет никакой независимости от адреса загрузки. Для MS-DOS файл будет загружен в какой-то сегмент и тоже по абсолютному смещению 0x0100, сегмент же не важен, за него COM-программа не вылезает. Из-за независимости от сегмента с большой натяжкой COM-файл для MSDOS может считаться PIE. А насчёт "независимости от точки входа" тоже хрень, точка входа всегда по адресу 0x0100.
Насколько я знаю, идея .COM файлов для MSDOS состояла в том, что бинарным транслятором машинный код для 8080/Z80 превращается в код для 8086, а DOS эмулирует в PSP функционал CP/M, предоставляя переносимость программ без исходников.
art2021 Автор
19.08.2025 14:18очень рад видеть такие комментарии. Это не является духотой. Я учту это и буду разбираться дальше
bolk
19.08.2025 14:18Можно наверное ещё и про TSR рассказать. В них PSP можно было «отдать системе». Это мало пригождалось правда, только сегментацию порождало.
Плюс выйти из .com можно было и через INT 20h или даже через RET, если мне память не изменяет (на стеке лежал адрес начала PSP, а там записан тот же INT 20h).Ещё очень рекомендую разыскать и скачать «Ralf Brown's Interrupt List», библию всех, кто писал под DOS. Он обновлялся, надо искать версию как можно свежее.
SIISII
В целом статья написана, с точки зрения русского языка, грамотно (что является весьма редким явлением), но вот в её "предисловии" команды почему-то с двумя м :)
Пара замечаний. Во-первых, "у них", когда имеются в виду килобайты, принято сокращать их до KB, ну а Kb означают килобиты. Понятно, что в данном случае проблемы с пониманием вряд ли возникнут, но в других ситуациях такое может произойти (скажем, когда указывают ёмкость микросхемы памяти).
Ну а во-вторых, разрядность процессоров и размеры программ не имеют совсем уж прямой связи. Как, например, транслятор ассемблера в OS/360 мог выполняться в разделе памяти размером порядка 16 килобайт, если он сам суммарно имел куда больший объём и мог транслировать программы, чей размер, по большому счёту, ограничивался только доступным местом на дисках? (Система 360 -- 32-разрядная машина, адрес там был 24-битным, занимая три младших байта слова, т.е. теоретически адресуемый объём памяти достигал 16 Мбайт, но сами машины имели весьма небольшой объём физической памяти; у самой младшей модели 30 он составлял от 8 до 64 Кбайт -- всё ж середина 1960-х).
Так что "помещались в один файл" -- это именно особенности CP/M, а не безусловная необходимость для 8-разрядного процессора.
И, кстати, были же оверлейные программы, суммарный размер кода которых мог существенно превосходить 64 Кбайта. Это сейчас про оверлеи, наверное, мало кто помнит :)
art2021 Автор
Спасибо, буду разбираться дальше. Про оверлеи в следующий раз будет написано однозначно.