Как стать автором
Обновить

Комментарии 29

Видеокарта, судя по всему, за долгое время жизни успела побывать в ремонте. Вместо оригинальной микросхемы Video BIOS установлен аналог, изготовленный в СССР.

IMHO, более вероятно, присутствие советской ПЗУ вместо оригинальной "говорит" о наличии в карте "прошитых" кириллических шрифтов, т.е. изменение функционала, а не о ремонте.

Ровесник динозавров


Ну какие там динозавры — я хорошо помню рекламу этого девайса в советском переводном журнале, это было почти вчера :)
(в СССР для технических/научных библиотек выпускались специальные журналы, в которых публиковались репринты статей из зарубежных технических журналов — первоначально на языке оригинала, а в 80х — уже и с переводом. Минусом было отсутствие цвета у изначально цветных иллюстраций)

А к настоящим древним «мамонтам» можно отнести что-то вроде ЭВМ «Мир-1» («машина инженерных расчетов») — я ее еще застал в рабочем состоянии в ВЦ нашего ВУЗа…
и операционная система MS-DOS, которая, будучи 16-битной, была обратно совместима с наиболее популярной на рынке микрокомпьютеров 8-битной CP/M.


Разве ПО от CP/M можно запускать на MS-DOS?
Имеется в виду совместимый API набор системных функций, что позволяет использовать программы CP/M после простой перекомпиляции.
CP/M после простой перекомпиляции.


Так ведь программы для CP/M почти всегда писались на ассемблере. Простая перекомпиляция под другой процессор невозможна.
Так как MS-DOS использовала те же самые соглашения ABI и карту памяти, эта ОС была совместима на уровне исходных кодов с CP/M. На системах CP/M, имеющих доступ максимум к 64 кБайт памяти, диапазон адресов с 0x0000 по 0x0100 (нулевая страница) была зарезервирована под нужды ОС и содержала, кроме прочего, аргументы командной строки. Исполняемое приложение располагалось, начиная с адреса 0x0100 и выше, а ОС размещалась в верхней части памяти; стек приложения рос вниз, начинаясь чуть ниже начала ОС. Модель памяти 8086 разбивает память на (перекрывающиеся) непрерывные сегменты длиной в 64 кбайт, так что каждый из этих сегментов фактически достаточен для виртуальной машины 8080. Поэтому исполняемые файлы .COM MS-DOS имеют размер до 64 кбайт и загружаются в память, начиная с адреса 0x100. Диапазон 0x0 — 0x100 в MS-DOS именуется Program Segment Prefix и он очень похож на нулевую страницу CP/M. Из-за высокой степени совместимости этих процессоров и их ABI перенос программы с CP/M в DOS происходил относительно безболезненно. Однако, такой порт мог использовать максимум 64 кбайт памяти (примеры — Wordstar 3.0 1982 года). Но это позволяло иметь единую кодовую приложения базу для обеих ОС с помощью лишь нескольких макроопределений и двух различных программ-ассемблеров.

Взято отсюда.
Где здесь написано, что программы от CP/M запускались под MS-DOS, как вы там сказали — «после простой перекомпиляции» (с ассемблера, да — как ниже написали, там замена команд выполнялась)?

перенос программы с CP/M в DOS происходил относительно безболезненно.


Не считая того, что CP/M работала на разных процессорах. I8086, I8080 и Z80 несколько отличаются для «относительно безболезненного» переноса программ.

Тогда же софт не настолько от функций ОС зависел. Главное, чтобы ОС поняла, что вот этот файл - исполняемый, закинула код в нужное место в памяти и установила указатель на первую команду. А формат исполняемых файлов .com как раз в CP/M появился.

А вы когда-нибудь запускали программу для Z80 (под который CP/M тоже была) на PDP или на x86? :) Ну так вот, ПО для CP/M написано под 8 битный процессор. На ассемблере. Запуск его на 16 битном процессоре другой архитектуры, это как бы странно.
Была, конечно, CP/M-86, но речь в статье про 8 битную CP/M.
Ну так вот, ПО для CP/M написано под 8 битный процессор. На ассемблере. Запуск его на 16 битном процессоре другой архитектуры, это как бы странно.

Зато i8086/8088 имели хорошую обратную совместимость с 8-битными процессорами i8080, и для преобразования 8-битных программ в 16-битные было достаточно прогнать их через автоматический кросс-ассемблер. Отличия, требующие ручной правки программистом, лежат сугубо в вызовах API ОС, ну и в адресах/командах обращений к внешним устройствам компьютера. MS DOS действительно несколько упрощала такой перенос с СР/М. А сам 8-битный код действительно легко переносился на 16-битную архитектуру путём перекомпиляции. Это, кстати, и было киллер-фичей 8086, которая позволила ему превзойти более мощных конкурентов. Хотя, справедливости ради, более мощные конкуренты играли совсем на другом рынке. Например, вот это не правда:
Вышедший в 1981 году IBM Personal Computer (5150) не был самым производительным или функциональным, не был он и самым доступным

IBM PC был самым производительным профессиональным компьютером в классе персоналок/микроЭВМ. Быстрее — только рабочие станции и мини-ЭВМ вроде Xerox Alto, которые стоили вообще космических денег.
Пишут так:
И в любом случае, совместимость как с 8080, так и с 8085 на 8086 достижима только с использованием макропроцессора, заменяя иногда одну команду 8080/8085 (POP/PUSH PSW, Jcc, Ccc, Rcc, XTHL) на несколько своих. Причем две опубликованные новые инструкции 8085 (SIM, RIM) в 8086 не реализуемы вообще.


А так, с таким же успехом можно вообще эмулятор процессора i8080 запускать — почему нет? Вот только это нифига не обратная совместимость, о которой идёт речь в статье.
XTHL на 8086 заменяется на
MOV BP,SP
XCHG BX,[BP]
Да, там ещё есть несколько команд, которые тоже менялись на группу операторов при трансляции.
Но ключевое слово тут «менялись». Вам не нужно было делать никакой умственной работы, это простейшая таблица подстановки — пройтись скриптом (хм, раньше не было этого слова) по операторам и заменить их на другие строчки. Так что не перегибайте насчёт эмуляторов, это действительно неплохая обратная совместимость. Не идеальная, когда надо просто запустить, и оно сразу будет работать, но на миграцию кода требовались минуты, а не месяцы (естественно, не считая времени на перенос кода, работающего с дисплеем, ОС и периферией).
Что касается 8085, то это вообще отдельная тема. Это своего рода SoC образца 1970-х, команды SIM/RIM относятся к архитектурно-зависимой части процессора, и их миграция на 8086 находится в сфере
Отличия, требующие ручной правки программистом, лежат сугубо в вызовах API ОС, ну и в адресах/командах обращений к внешним устройствам компьютера.
пройтись скриптом (хм, раньше не было этого слова) по операторам и заменить их на другие строчки.


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

Это не сработает, т.к. некая область памяти может быть использована софтом, а кросс-ассемблер про это ничего знать не может.
Да нет, можно. Было бы нельзя, не работали бы виртуальные машины. Эмуляция и есть такая замена одних команд на другие ( протранслируйте все инструкции одного процессора в выполняемые эмулятором инструкции на другом процессоре — примерно как Transmeta работал). И адресация тоже точно так же заменяется.

а кросс-ассемблер про это ничего знать не может.


Это CP/M с её распределением памяти:
image

Займите для регистрового файла память на x86 чуть выше 0xffff и всё.
Да нет, можно. Было бы нельзя, не работали бы виртуальные машины. Эмуляция и есть такая замена одних команд на другие

Нет, стоп. Эмуляция, виртуальные машины — это не «замена одних команд на другие», это на порядки более сложная задача, которая ничего общего с кросс-ассемблером не имеет.
Это CP/M с её распределением памяти:

Да, и такую же имеет программный сегмент в MS DOS, для простой переносимости кода.
Займите для регистрового файла память на x86 чуть выше 0xffff и всё.

А вот не смогу так просто взять и занять. Не смогу, даже если закрыть глаза на то, что использовать память вместо регистра — это катастрофическая деградация производительности, и такие вещи недопустимы при портировании (по крайней мере, если мы говорим про 1980-е, а не про 2020-е, где на производительность почти всем плевать), хотя и в какой-то мере работоспособны.
Но главная проблема в том, что это будет память в другом сегменте, а у меня приложение имеет неизвестные на этапе компиляции значения сегментных регистров, которые установит DOS при его загрузке, а вся адресация в нём ближняя. И мой кросс-ассемблер нифига не знает, в какой сегмент можно положить данные. Поэтому граница между «простым кросс-ассемблером» и «эмуляцией» чётко прослеживается. И первый как раз и может существовать благодаря тому, что программы 8080 могут быть уложены в один сегмент 8086, а DOS под них выделяет такую же карту памяти, как выделяла CP/M.
Нет, стоп. Эмуляция, виртуальные машины — это не «замена одних команд на другие», это на порядки более сложная задача, которая ничего общего с кросс-ассемблером не имеет.


А мы по сложности и не сравниваем. Мы сравниваем по возможностям. Возможно ли преобразование одного ассемблера в другой с сохранением работоспособности программы? Да, возможно для любых целевых систем с достаточным количеством ресурсов. Полученный исполняемый файл будет построен преобразованием кодов исходного процессора в последовательность кодов целевого. Функционально исходная и целевая программы будут работать одинаково. Значит ли это, что обеспечивается совместимость одной системы с другой? Нет, не значит. Мы делали преобразование кода.

Да, и такую же имеет программный сегмент в MS DOS, для простой переносимости кода.


Я её с этим поздравляю, но исполняемый файл с CP/M всё равно не заработает без преобразования под другой процессор. Это обратной совместимостью не называется. Просто архитектура работы с системой такая же, как у CP/M.

это катастрофическая деградация


Мы говорим о возможности работы с регистрами, когда целевая система не может включить в себя регистры исходной.

Но главная проблема в том, что это будет память в другом сегменте, а у меня приложение имеет неизвестные на этапе компиляции значения сегментных регистров, которые установит DOS при его загрузке, а вся адресация в нём ближняя.


Вы транслируете команды i8080 или Z80 в x86. Зачем вы сохраняете все ограничения 8 битных процессоров при таком переносе? ;) Переключайте сегменты, не стесняйтесь.

И мой кросс-ассемблер нифига не знает, в какой сегмент можно положить данные. Поэтому граница между «простым кросс-ассемблером» и «эмуляцией» чётко прослеживается.


Ваш кросс-ассемблер просто слишком примитивен и не умеет так распределять программу, чтобы она могла использовать другой сегмент. Вы зачем-то ограничиваете себя com-форматом. Преобразовывайте в exe! Чего стесняться? Будет у вас и сегмент стека, и программы и данных. Как переключать, есть, например, у Рудакова и Финогенова «Программируем на языке ассемблера IBM PC», 1997 года, страница 132 и далее.
Кстати, а где гарантия, что после преобразования (где одна инструкция в несколько идёт) ваша программа влезет в отведённое пространство? Тем более нечего держаться за com.
А мы по сложности и не сравниваем. Мы сравниваем по возможностям.

Почему не сравниваем? Как раз по сложности и сравниваем. Нас же при портировании софта интересует в первую очередь целесообразность сего действия в реальных условиях, а не теоретическая возможность создания алгоритма трансляции на машине Тьюринга с бесконечной лентой.
Возможно ли преобразование одного ассемблера в другой с сохранением работоспособности программы? Да, возможно для любых целевых систем с достаточным количеством ресурсов.

Вы подменяете контекст беседы. Мы говорили про переносимость кода с 8080 на 8086, в тот период, когда это было актуально. И ответы будут соответствующими:
Вы транслируете команды i8080 или Z80 в x86. Зачем вы сохраняете все ограничения 8 битных процессоров при таком переносе? ;) Переключайте сегменты, не стесняйтесь.

Не могу, мой транслятор, состоящий всего из двух циклов, такое не умеет. А писать тот, который умеет, в разы сложнее, чем всю программу вручную портировать. И не факт, что он вообще влезет в память моего компьютера, у моего IBM PC всего 64К памяти, а плата на 256К стоит две моих месячных зарплаты.
Ваш кросс-ассемблер просто слишком примитивен

Именно так. И другого у меня не будет этак до середины 1990-х. Более того, даже сам EXE-формат появится через пару лет после того. как я начал портирование на 16-битную платформу в 1981-м :)
Кстати, а где гарантия, что после преобразования (где одна инструкция в несколько идёт) ваша программа влезет в отведённое пространство?

С вероятностью 99% влезет, т.к. у программы на CP/M верхнюю часть памяти занимает собственно CP/M, да и в 64К адресного пространства ещё и дисплейная область 8-битной машинки сидит скорее всего, а в DOS сегмент программы весь свободен, кроме первых 256 байт.

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


Я бы не сказал, что второй преобразователь сильно уж сложнее первого. Не сильно сложнее, чем транслировать команды программы CP/M для Z80 в x86. И, к слову сказать, как раз перенос между любыми процессорами и сводится к простой замене одних команд на блоки других. Встретили ldir — заменяем циклом-имитацией. Встретили ld — заменяем хоть записью в память, где у нас там регистр будет лежать, хоть записью в свой какой-то регистр по таблице. Встретили проверку флагов — заменяем на блок проверки с выставкой в заранее определённом флаговом регистре нужных флагов. Так можно хоть с PDP и IBM 360 на x86 переносить.
Да я ж уже выше писал условия — должна быть одинаковая схема работы с памятью и регистры процессора, на который переносим код, должны или совпадать, или быть надмножеством регистров процессора, на который переносим. Потому что если это условие не выполняется, без смыслового анализа кода трансляцию не выполнить. Вы там заменили какой-то регистр на ячейку памяти, а этот регистр, он в соседней подпрограмме для косвенной адресации используется. А другой регистр сравнивается сам с собой, чтобы zero-флаг выставить, если 0, и т.д.
В общем, эта работа сравнима с написанием достаточно умного компилятора, и на счёт «не сильно сложнее» вы ошибаетесь. Транслятор 8080 в 8086 пишется за час на языке высокого уровня, а вот такой пишется и отлаживается месяцами.
Нет такого условия. Вся система команд исходного процессора заменяется на блоки команд другого процессора.

а этот регистр, он в соседней подпрограмме для косвенной адресации используется


И? Используем так же, с учётом переноса схемы памяти на нашу память. Нужно умножить на 16 адрес для линейного у нашего МП? Умножаем. Нужно перевести в сегмент/смещение — делим и переводим тут же в блоке команд.

А другой регистр сравнивается сам с собой, чтобы zero-флаг выставить, если 0, и т.д.


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

В общем, эта работа сравнима с написанием достаточно умного компилятора, и на счёт «не сильно сложнее» вы ошибаетесь. Транслятор 8080 в 8086 пишется за час на языке высокого уровня, а вот такой пишется и отлаживается месяцами.


Пока я вижу такую же таблицу соответствия и не более. И, полагаю, я не ошибаюсь в сложности данного мероприятия.Примерно вот так заменяется. (здесь, правда, не совсем такая программа, но суть та же).
И? Используем так же, с учётом переноса схемы памяти на нашу память. Нужно умножить на 16 адрес для линейного у нашего МП? Умножаем. Нужно перевести в сегмент/смещение — делим и переводим тут же в блоке команд.

И ничего не выйдет :) Нельзя рассчитать адрес перехода из памяти без анализа предыдущего и последующего кода. Вам же для этого нужно будет другие регистры использовать. А подстрочник понятия не имеет, какие регистры можно использовать, а какие нельзя. Так что нет, таблица соответствия без собссно соответствия не взлетит :)
Нельзя рассчитать адрес перехода из памяти без анализа предыдущего и последующего кода.


А кто ж его запрещает делать в процессе трансляции? Вы когда кроссассемблером будете заменять исходные команды на другие вы что же, адресацию не двигаете? Двигаете, конечно — у вас все адреса смещаются. Не выйдет простая подстановка без контроля адресов. А когда вы такой контроль делаете, вы вольны адреса преобразовывать как захотите — главное, чтобы ваши элементарные блоки для замены с ними корректно работали.
А кто ж его запрещает делать в процессе трансляции?

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

Ну так в исходниках же нет абсолютной адресации (как правило). Там ничего не надо двигать/контролировать. Ну появится там вместо одной команды три других, метки переходов все равно ведь актуальны останутся.
А, так вы обработку исходного ассемблерного текста говорите?! Нет, так не пойдёт. Я об обработке бинарника в другой бинарник, поскольку речь идёт о «Разве ПО от CP/M можно запускать на MS-DOS?» — именно это я и спросил. Нет у пользователя исходника, но есть бинарник программы от CP/M.
Я думал, это очевидно. Портирование программ в начале 1980-х осуществлялось именно так, а не обработкой бинарника. Мы ведь говорим про инструментарий, облегчавший жизнь разработчиков, которые тогда переносили свой софт на новую платформу, а не про некий никогда не существовавший мэджик тул для пользователей, который позволял запускать восьмибитные бинарники на 16-битных платформах. Подобного в те годы не могло быть в принципе.
И тут проблема не в переносе кода, а в работе с железом. Я уже говорил про это выше. Основная работа по переносу была не в модификации инструкций под новый процессор (это как раз успешно делал тот самый скрипт-подстрочник), а в адаптации кода, работающего с дисплеем, клавиатурой, внешними устройствами. Всё это на IBM PC радикально отличалось от реализации на 8-битных машинах.
Спасибо всем участникам за великолепный технический спор! Это было классно! И простите меня за неточность формулировки)
Судя по всему, он изначально разрабатывался с учетом возможного применения в системах со встроенным экраном — на плате есть коннектор аналогового выхода, к которому подключен монитор.

По изначальной задумке внутренний разъем использовался для подключения модулятора ТВ-сигнала.
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.