Нашли или выдавили из себя код, который нельзя назвать нормальным,
на который без улыбки не взглянешь?
Не торопитесь его удалять или рефакторить, — запостите его на
говнокод.ру, посмеёмся вместе!
Ага. Только из-за отсутствия виртуальной памяти в ДОСе в экзешниках были перемещаемые адреса (relocations a. k. a. fixups), которые загрузчик экзешника должен был фиксить.
В эпоху Windows 98 начали собирать экзешники без фиксапов. Для каждого загруженного экзешника VMM создавал своё адресное пространство, чтобы загрузить его по фиксированному адресу.
В Висте появилось ASLR, и снова стали собирать экзешники с фиксапами, чтобы их можно было «закинуть хрен знает куда».
Кстати, в 32-битных x86 rip-адресация была только для джампов и коллов, поэтому pic костылили таким кодом:
call @1
@1:
pop ebx
В ebx теперь лежит адрес @1. К адресам данных теперь можно добавить ebx-@1, тогда в экзешник они лягут без фиксапов. Возврата не будет, потому что адрес возврата из стека вытолкнули.
Да, колл без рета. Такое вирусы любили использовать, потому что их никто патчить не будет.
В Винде бывает ещё пиздец, когда 32- или 64-битное приложение в формате portable executable имеет расширение .com. Реальный пример — devenv.com (IDE от MS Visual Studio) или soffice.com (универсальный лаунчер от Open Office / Libre Office).
Винда их нормально запускает как приложение Win32, несмотря на расширение .com.
Это вроде как потому что единственный способ, чтобы один и тот же файл можно было запускать и из-под консоли, и из гуев. В экзешнике подсистема прописана, будет неудобно: гуевый экзешник от консоли сразу открепится, а консольный при вызове из проводника выдаст консоль.
Экзешники, собранные TP >= 4.0 (а также сишкой, если модель не tiny и не small или требуется отдельный сегмент стека), нельзя было конвертировать в .com.
Однако, для таких экзешников, если они влезают в 64К, был псевдоконвертор: он перед сигнатурой MZ прилеплял загрузчик в формате com-файла, который читал заголовок экзешника, рассовывал его секции по сегментам памяти и патчил фиксапы, а потом передавал управление. Я не помню, решали ли там задачу двойного потребления памяти.
Программы, сконвертированные псевдоконвертором, можно было восстановить в exe. Была программа com2exe, написанная... да, Фабрисом Белларом, кем же ещё.
Кстати, в ТП тип pointer и типизированные указатели (хоть на данные, хоть на функции) всегда far. Нельзя объявить переменную, чтобы она хранила near-указатель. Поэтому и к «ближним» процедурам и функциям нельзя применить операцию @ и их нельзя передать в другую процедуру или функцию как аргумент.
type
myfunc = function(x: real): real;
function integral(f: myfunc; a, b: real): real;
В качестве параметра f можно передать только far-функцию.
Ну вот в известных мне реализациях сишки для x86 у указателей были модификаторы far и near, а в ТП такого не было, там все указатели far.
Т. е. в сишке можно было так:
char far * petuh;
char near * kurochka;
Если модификатор far/near не указан, то размер указателя выбирался по текущей модели.
По умолчанию far-указатели и на код, и на данные были в модели large.
Получается, что модель ТП больше всего похожа на модель large, но с исключением: неэкспортируемые процедуры и функции по умолчанию были near (но они были неполноценными, потому что даже в пределах модуля на них нельзя было брать указатель).
Действительно. В сишном стандарте, например, нет никаких моделей.
В некоторых компиляторах отсутствовала модель тайни, для получения com-файла нужно было выбирать смолл и указывать дополнительные параметры, чтобы стек не создавался.
Начиная с четвёртой версии можно считать, что модель Large.
Каждый модуль, перечисляемый в uses, линкер клал в отдельный сегмент.
Можно было объявлять функции с директивой near, чтобы получить более оптимальный код (near- и short-джампы были rip-based и не требовали фиксапов), но поскольку все указатели были только far, то адреса near-функций нельзя было класть в указатели и куда-нибудь передавать, также их нельзя было экспортировать в другие модули.
Ещё про «среднее»: сегмент данных создавался один, поэтому глобальные переменные должны были влезть в 64К, но можно было использовать кучу «неограниченного» размера (640К минус ДОС и драйвера, минус другие запущенные программы, минус код и данные твоей программы).
В Борманд Паскале до четвёртой версии была модель тайни, т. е. только COM-файлы, а начиная с четвёртой версии только large, т. е. все указатели длинные, только EXE-файл (но можно было по желанию объявлять near-функции, на которые нельзя брать указатели и которые нельзя вызывать из других модулей).
Я ходил в некоторый аналог дворца пионеров, и там был turbo или borland паскаль (отличался набором либ, всяким OWL, вроде оверлеями и пр), на тот момент это было очень продвинуто.
Были, но были ли они в турбо, или в борланде?
Турбо влазил на дискету, а борманд -- нет.
Кстати, IDE сама была под дос (подозреваю турбо вижн) а писать можно было и под винду и OWL. Все помнят эти кнопочки с зеленой галочкой и красным крестиком, да?
Borland от Turbo отличался тем, что в пакете «Borland» были компиляторы и библиотеки сразу для DOS и для Windows, а в «Turbo» версия для DOS и версия для Windows были разложены в отдельные пакеты.
Были ещё пиратские сборки «на двух дискетах», которые я терпеть не мог. В конце 1990-х уже ни у кого не было 20-мегабайтных винчестеров, чтобы так экономить.
В пакете Борланд были те же самые компиляторы, которые были в раздельных пакетах Турбо, и даже те же самые библиотеки. Разница была только в том, что в Борланд это всё засунули в один установочный пакет.
Правда, в Борланд дополнительно положили ещё одну версию IDE и компилятора. Обычные turbo.exe и tpc.exe были под реальный режим, а bp.exe и bpc.exe (которые клали только в Борланд, но не клали в Турбо) работали в защищённом (через бормандовскую прослойку RTM+DPMI), так что могли использовать больше оперативки (это было важно при компиляции огромных программ). Эти компиляторы поддерживали одни и те же языковые конструкции и генерировали одинаковый код, и библиотеки были одинаковыми, разница была только в доступной компилятору и IDE оперативке.
В BP7.0 и в Delphi 1.0 были 16-битные rtm.exe и dpmi16bi.ovl. Можно было генерировать код под реальный режим и под защищённый режим с 16-битными сегментами, как в Windows 3.x. В этом же режиме работали консольные компиляторы bpc.exe и dcc.exe и IDE bp.exe.
Во вторые Дельфи и в Борманд C++ 4.x (в пятые Борманд C++ стопудово) уже клали консольные компиляторы, работающие в защищённом режиме с 32-битным flat-сегментом. К ним прилагался 32rtm.exe и dpmi32bi.ovl.
Консоль была, но только для досовских программ. Из-под неё можно было гонять даже программы для DPMI. Но, увы, у этой «консоли» не было доступа к WinAPI. Ну почти не было, с помощью VXD можно было пробросить в VDM доступ к некоторым функциям Windows. Например, из коробки была возможность менять заголовок окна. Ещё можно было подглядывать в буфер обмена.
Вот насчёт cmd.exe нужно проверить. Возможно, в Win95 его не клали, и вместо него использовали command.com.
Но Win32 console API точно было. Я точно помню программы в формате portable executable, которые в DOS не работали, а в Win95 работали. Помню, что в Win95 console API были реализованы все функции с суффиксом A (ANSI), а вот с функциями с суффиксом W (Wide, что означает поддержку UTF-16) была беда, были реализованы не все, поэтому некоторые консольные программы, предназначенные для NT, в Win95 могли не работать.
Не клали, но cmd.exe на самом деле имеет опосредованное отношение к консоли, и вместо него был command.com.
Но API было, хотя и урежанное (работало оно в v86, как я там выше дал ссылку). Иными словами, любая соснольная херня в win9x всегда порождала 16-ти битный процесс, как я понял.
И ты прав на счет "A": в 9x всё было "A", а в NT -- "W".
Отсюда у нас TEXT() и прочие хаки
Ядром системы был 32-битный VMM.vxd (virtual memory manager).
Часть функций WinAPI была реализована вызовом функций DOS и BIOS, сидящих в V86, посредством vxd-драйверов. Поэтому Win95 мог использовать досовские драйвера и резидентные программы, запущенные через autoexec.bat и config.sys.
К некоторому железу уже были прямые 32-битные драйвера в обход DOS и BIOS.
Win95 умел загружать и 32-битные drv, и 16-битные от Win 3.x.
WinAPI был в двух вариантах: 16-битный (на основе API Win 3.x) и 32-битный, как в NT (но функций с суффиксом W было мало).
Некоторые функции одного API вызывали из-под себя функции другого API, так что при работе любой программы использовались и 16-битные, и 32-битные сегменты.
В NT эти интерфейсы изолировали. Там придумали WOW (Windows on Windows). Win32 стал основным интерфейсом, а 16-битный API реализовали через него. И драйверов 16-битных не стало.
Отдельная тема — vxd-драйвера. Они появились ещё в Windows3.1 (тогда у файлов было расширение .386). Формат этих драйверов LE по сути был урезанным форматом LX, который использовался в OS/2 для 32-битных программ. Его особенностью была возможность в одном бинарнике держать 32-битные и 16-битные секции (какой ужас).
Да, в Windows 3.1 уже были 32-битные vxd-драйвера, хотя я не знаю, зачем, ведь ядро и API были 16-битными.
В Win95 консоль была реализована через жопу. В Win 3.x был vdm.exe (или как-то так), который умел рисовать чёрное окошко для досовских программ.
В Win95 решили для рисования консоли взять за основу этот код из Win 3.x, чтобы не писать с нуля. Поэтому в Win95 при запуске любого приложения win32 console API прицепом загружалась VDM, что создавало дополнительную нагрузку.
Я тебя понял. Оригинальный ANSI.SYS писался под голый ДОС и про сервисы, предоставляемые VXD, не знал. Но если его дописать, то такую функцию реализовать можно.
DPMI играл две роли:
1. Реализовывал переходники между программой защищённого режима и функциями DOS и BIOS.
2. Реализовывал собственный API (INT 31h), в котором были функции для управления виртуальной памятью вроде VirtualAlloc, функций для работы с линейными адресами и сегментами, управления защитой, работы с обработчиками прерываний и т. п., так что в прикладной программе можно было обходиться без низкоуровневого кода.
RTM же реализовывал дополнительную библиотеку.
16-битный RTM мумулировал API OS/2 для соснольных приложений: часть функций DOSCALLS.DLL, VIOCALLS.DLL, KBDCALLS.DLL.
32-битный RTM мумулировал Win32 для соснольных приложений: часть функций kernel32.dll, user32.dll, advapi32.dll.
Для запуска ФАРа из голого DOS посредством 32RTM этих функций было недостаточно. Рантайм, позволяющий запустить ФАР из DOS, появился позже: https://www.japheth.de/HX.html
Но даже тот рантайм, что был у Борланда, позволял собирать двойные приложения защищённого режима, которые могли работать и в голом DOS, и в винконсоли. К таким приложениям относились борландовские компиляторы и Турбо Дебагер. Даже IDA выпускалась в виде такого приложения.
Почему 16-битный RTM мумулирует функции OS/2, а не Windows? Да потому что у 16-битных Windows (Win 3.x) не было консольного API.
К слову, такой рантайм был не только у Борланда. Был Pharlap TNT DOS extender с похожим API. Его ещё использовали какие-то компиляторы (Metaware High C++ вроде).
У Pharlap было ещё одно извращение: можно было писать 32-битные программы для 16-битных Windows 3.x без Win32s. Создавался 32-битный сегмент с твоим кодом и линковался в одну программу с рантаймом Pharlap, который загружал этот сегмент, как положено, и создавал переходники для вызова функций 16-битного API. Твой код был полностью 32-битным, но 16-битный WinAPI был бутылочным горлышком.
Я не знаю реальные примеры программ, которые бы использовали расширитель Pharlap для Windows. Когда появился Win32s, стали писать программы под Win32 API и запускать через него. Например, древний 32-битный Фотошоп спокойно запускался не только в NT и в Win95, но и в Win 3.x через Win32s.
Для поддержки массивов более 64К в 16-битном коде нужно было крутить сегмент. В защищённом режиме для этого нужно плодить записи в LDT или крутить базу.
В Борманд Паскале сделали проще: не стали реализовывать модель Huge. Т. е. писали код так, чтобы массивы и объекты укладывались в 64К. Если нужно было больше 64К, использовали датастримы: в библиотеке Турбовижн были классы, предоставляющие интерфейс к памяти как к файлу. Или использовали связанные списки и деревья, у которых каждый узел аллоцировался отдельно.
Tiny. As you might guess, this is the smallest of the memory
models. All four segment registers (CS, DS, 55, ES) are set to the
same address, so you have a total of 64K for all of your code, data,
and stack. Near pointers are always used. Tiny model programs
can be converted to .COM format by linking with the It option.
Small. The code and data segments are different and don't overlap, so you have 64K of code and 64K of data and stack. Near
pointers are always used.
Medium. Far pointers are used for code, but not for data. As a
result, data plus stack are limited to 64K, but code can occupy up
to 1 MB.
Compact. The inverse of medium: Far pointers are used for data,
but not for code. Code is then limited to 64K, while data has a 1
MB range.
Large. Far pointers are used for both code and data, giving both a
1 MB range.
Huge. Far pointers are used for both code and data. Borland C++
normally limits the size of all static data to 64K; the huge memory
model sets aside that limit, allowing data to occupy more than
64K.
ASD__77 # 0
kcalbCube # 0 ⇈
j123123 # 0 ⇈
Hu3KoypoBHeBblunemyx # 0 ⇈
kcalbCube # 0 ⇈
j123123 # 0 ⇈
Kypumca # 0 ⇈
guest # 0 ⇈
OPAHrymaH # 0 ⇈
guest # 0 ⇈
ObeseYoung # 0 ⇈
Floating_cockerel # 0 ⇈
OMuKPOH # 0 ⇈
j123123 # 0 ⇈
Noodles # 0 ⇈
OPAHrymaH # 0 ⇈
bormand # 0 ⇈
Как-будто в винде и линуксе фиксапов нет...
Тем более после прихода ASLR, который закидывает экзешник хрен пойми куда.
З.Ы. В линуксе pic, ему можно не патчить.
OPAHrymaH # 0 ⇈
В Висте появилось ASLR, и снова стали собирать экзешники с фиксапами, чтобы их можно было «закинуть хрен знает куда».
OPAHrymaH # 0 ⇈
В ebx теперь лежит адрес @1. К адресам данных теперь можно добавить ebx-@1, тогда в экзешник они лягут без фиксапов. Возврата не будет, потому что адрес возврата из стека вытолкнули.
Да, колл без рета. Такое вирусы любили использовать, потому что их никто патчить не будет.
j123123 # 0 ⇈
ObeseYoung # 0 ⇈
guest # 0 ⇈
bormand # 0 ⇈
guest # 0 ⇈
bormand # 0 ⇈
З.Ы. Хотя не, там другие инварианты на старте, экзешник поди сам сегментные регистры выставляет.
guest # 0 ⇈
bormand # 0 ⇈
guest # 0 ⇈
Для EXE он должен сделать какую-то интеллектуальную работу, а COM просто загружает.
Но когда EXE только появился, он различал именно по расширению. А потом перестал.
Почему?
bormand # 0 ⇈
guest # 0 ⇈
COMMAND.COM и FORMAT.COM нельзя переименовывать не сломав к хуям примерно всё, хотя они уже и повылазили за 64K -- размер сегмента.
А вдруг COM файл начнется с MZ?
А не начнется, потому что MZ это
Прекрасный Реймонд Чен поясняет
kcalbCube # 0 ⇈
OPAHrymaH # 0 ⇈
kcalbCube # 0 ⇈
guest # 0 ⇈
OPAHrymaH # 0 ⇈
Винда их нормально запускает как приложение Win32, несмотря на расширение .com.
guest # 0 ⇈
Тупо, что оно 32 бита (майки наговнокодили и десятый год не могут перевестись в 64) но всё же оно .exe
OPAHrymaH # 0 ⇈
guest # 0 ⇈
но всё, что он делает, это запускет .exe. Этакий трамполин.
наверное для совместимости с visual studio 4.0
OPAHrymaH # 0 ⇈
ISO # 0 ⇈
guest # 0 ⇈
666_N33D135 # 0 ⇈
HE_OTBE4Au_YE6KY # 0 ⇈
Steve_Brown # 0 ⇈
Rooster # 0 ⇈
guest # 0 ⇈
guest # 0 ⇈
guest # 0 ⇈
OPAHrymaH # 0 ⇈
Однако, для таких экзешников, если они влезают в 64К, был псевдоконвертор: он перед сигнатурой MZ прилеплял загрузчик в формате com-файла, который читал заголовок экзешника, рассовывал его секции по сегментам памяти и патчил фиксапы, а потом передавал управление. Я не помню, решали ли там задачу двойного потребления памяти.
Программы, сконвертированные псевдоконвертором, можно было восстановить в exe. Была программа com2exe, написанная... да, Фабрисом Белларом, кем же ещё.
ObeseYoung # 0 ⇈
If Force Far Calls is off, the compiler uses the NEAR call models for any procedures or functions within the file being compiled.
тоесь нихуа не large
Ga_Dong_Tao # 0 ⇈
KaBauHblu_nemyx # 0 ⇈
OPAHrymaH # 0 ⇈
yet_another_one_shit # 0 ⇈
ObeseYoung # 0 ⇈
OPAHrymaH # 0 ⇈
Кстати, в ТП тип pointer и типизированные указатели (хоть на данные, хоть на функции) всегда far. Нельзя объявить переменную, чтобы она хранила near-указатель. Поэтому и к «ближним» процедурам и функциям нельзя применить операцию @ и их нельзя передать в другую процедуру или функцию как аргумент.
В качестве параметра f можно передать только far-функцию.
ObeseYoung # 0 ⇈
OPAHrymaH # 0 ⇈
Т. е. в сишке можно было так:
Если модификатор far/near не указан, то размер указателя выбирался по текущей модели.
По умолчанию far-указатели и на код, и на данные были в модели large.
Получается, что модель ТП больше всего похожа на модель large, но с исключением: неэкспортируемые процедуры и функции по умолчанию были near (но они были неполноценными, потому что даже в пределах модуля на них нельзя было брать указатель).
BOKCEJIbHblu_nemyx # 0 ⇈
OPAHrymaH # 0 ⇈
ObeseYoung # 0 ⇈
KaBauHblu_nemyx # 0 ⇈
guest # 0 ⇈
У каждого компилятора могут быть свои модели
OPAHrymaH # 0 ⇈
В некоторых компиляторах отсутствовала модель тайни, для получения com-файла нужно было выбирать смолл и указывать дополнительные параметры, чтобы стек не создавался.
Kypumca # 0 ⇈
ucnaHckuu_CTblD # 0 ⇈
deneg.net
raboty.net
schastya.net
mozgov.net
Ответить
guest # 0 ⇈
ObeseYoung # 0 ⇈
bormand # 0 ⇈
Думаешь я помню их названия?
Вроде что-то среднее, с far для данных и near для кода.
OPAHrymaH # 0 ⇈
Каждый модуль, перечисляемый в uses, линкер клал в отдельный сегмент.
Можно было объявлять функции с директивой near, чтобы получить более оптимальный код (near- и short-джампы были rip-based и не требовали фиксапов), но поскольку все указатели были только far, то адреса near-функций нельзя было класть в указатели и куда-нибудь передавать, также их нельзя было экспортировать в другие модули.
OPAHrymaH # 0 ⇈
OPAHrymaH # 0 ⇈
Вопрос: нафига?
Ответ: call near будет rip-based, поэтому фиксапа не будет. Такой заменой получается pic.
OPAHrymaH # 0 ⇈
guest # 0 ⇈
OPAHrymaH # 0 ⇈
В тройке не было модульной системы, поэтому для использования библиотек применяли чёрную магию:
https://govnokod.ru/19045
guest # 0 ⇈
Я ходил в некоторый аналог дворца пионеров, и там был turbo или borland паскаль (отличался набором либ, всяким OWL, вроде оверлеями и пр), на тот момент это было очень продвинуто.
OPAHrymaH # 0 ⇈
guest # 0 ⇈
Турбо влазил на дискету, а борманд -- нет.
Кстати, IDE сама была под дос (подозреваю турбо вижн) а писать можно было и под винду и OWL. Все помнят эти кнопочки с зеленой галочкой и красным крестиком, да?
OPAHrymaH # 0 ⇈
OPAHrymaH # 0 ⇈
Были ещё пиратские сборки «на двух дискетах», которые я терпеть не мог. В конце 1990-х уже ни у кого не было 20-мегабайтных винчестеров, чтобы так экономить.
guest # 0 ⇈
OPAHrymaH # 0 ⇈
В пакете Борланд были те же самые компиляторы, которые были в раздельных пакетах Турбо, и даже те же самые библиотеки. Разница была только в том, что в Борланд это всё засунули в один установочный пакет.
Правда, в Борланд дополнительно положили ещё одну версию IDE и компилятора. Обычные turbo.exe и tpc.exe были под реальный режим, а bp.exe и bpc.exe (которые клали только в Борланд, но не клали в Турбо) работали в защищённом (через бормандовскую прослойку RTM+DPMI), так что могли использовать больше оперативки (это было важно при компиляции огромных программ). Эти компиляторы поддерживали одни и те же языковые конструкции и генерировали одинаковый код, и библиотеки были одинаковыми, разница была только в доступной компилятору и IDE оперативке.
KaBauHblu_nemyx # 0 ⇈
guest # 0 ⇈
Если ты студень, то тебе хватит турбы для лаб.
Если ты пишешь коммерческий софт, то тебе уже не скомпилица турбой, и нужен борманд. Думаю, так.
OPAHrymaH # 0 ⇈
guest # 0 ⇈
OPAHrymaH # 0 ⇈
32-битными стали только вторые Дельфи.
В BP7.0 и в Delphi 1.0 были 16-битные rtm.exe и dpmi16bi.ovl. Можно было генерировать код под реальный режим и под защищённый режим с 16-битными сегментами, как в Windows 3.x. В этом же режиме работали консольные компиляторы bpc.exe и dcc.exe и IDE bp.exe.
Во вторые Дельфи и в Борманд C++ 4.x (в пятые Борманд C++ стопудово) уже клали консольные компиляторы, работающие в защищённом режиме с 32-битным flat-сегментом. К ним прилагался 32rtm.exe и dpmi32bi.ovl.
ObeseYoung # 0 ⇈
OPAHrymaH # 0 ⇈
guest # 0 ⇈
>менять заголо
помнишь ANSI.SYS? Поди, через него можно было?
Floating_cockerel # 0 ⇈
guest # 0 ⇈
Славилась доброй душой
(с)
OPAHrymaH # 0 ⇈
ANSI.SYS про другое. Он интерпретировал эскейп-последовательности в стандартном выходном потоке.
guest # 0 ⇈
Это, пардон, кокая? Там была только ``command.com`` же.
консоль (cmd.exe, Win32API Console API) были тока в NT.
Или я вру?
>ANSI.SYS про другое.
А знаешь, как в прыщах программы устанавливают тайтл у окна эмулятора терминала?
OPAHrymaH # 0 ⇈
FAR, который был чистым portable executable для win32 console API, в Win95 работал.
guest # 0 ⇈
https://en.wikipedia.org/wiki/Cmd.exe
моя память -- тоже. Но мы можем врать (четверть века прошла всё таки), так что я наверное и правда скачаю на досуге, да посмотрю.
Так что с тайтлами xterm, putty и пр? Знаешь, как их устанавливают?
>far
хм.. и пправда
ааа!!
вот как дело было
https://en.wikipedia.org/wiki/Windows_Console#Windows_9x
но cmd.exe там не было
OPAHrymaH # 0 ⇈
Но Win32 console API точно было. Я точно помню программы в формате portable executable, которые в DOS не работали, а в Win95 работали. Помню, что в Win95 console API были реализованы все функции с суффиксом A (ANSI), а вот с функциями с суффиксом W (Wide, что означает поддержку UTF-16) была беда, были реализованы не все, поэтому некоторые консольные программы, предназначенные для NT, в Win95 могли не работать.
guest # 0 ⇈
Но API было, хотя и урежанное (работало оно в v86, как я там выше дал ссылку). Иными словами, любая соснольная херня в win9x всегда порождала 16-ти битный процесс, как я понял.
И ты прав на счет "A": в 9x всё было "A", а в NT -- "W".
Отсюда у нас TEXT() и прочие хаки
ObeseYoung # 0 ⇈
OPAHrymaH # 0 ⇈
Ядром системы был 32-битный VMM.vxd (virtual memory manager).
Часть функций WinAPI была реализована вызовом функций DOS и BIOS, сидящих в V86, посредством vxd-драйверов. Поэтому Win95 мог использовать досовские драйвера и резидентные программы, запущенные через autoexec.bat и config.sys.
К некоторому железу уже были прямые 32-битные драйвера в обход DOS и BIOS.
Win95 умел загружать и 32-битные drv, и 16-битные от Win 3.x.
WinAPI был в двух вариантах: 16-битный (на основе API Win 3.x) и 32-битный, как в NT (но функций с суффиксом W было мало).
Некоторые функции одного API вызывали из-под себя функции другого API, так что при работе любой программы использовались и 16-битные, и 32-битные сегменты.
В NT эти интерфейсы изолировали. Там придумали WOW (Windows on Windows). Win32 стал основным интерфейсом, а 16-битный API реализовали через него. И драйверов 16-битных не стало.
OPAHrymaH # 0 ⇈
Да, в Windows 3.1 уже были 32-битные vxd-драйвера, хотя я не знаю, зачем, ведь ядро и API были 16-битными.
Kypumca # 0 ⇈
OPAHrymaH # 0 ⇈
В Win95 консоль была реализована через жопу. В Win 3.x был vdm.exe (или как-то так), который умел рисовать чёрное окошко для досовских программ.
В Win95 решили для рисования консоли взять за основу этот код из Win 3.x, чтобы не писать с нуля. Поэтому в Win95 при запуске любого приложения win32 console API прицепом загружалась VDM, что создавало дополнительную нагрузку.
cmd.exe действительно был только в NT и в OS/2.
ucnaHckuu_CTblD # 0 ⇈
guest # 0 ⇈
Правда, в ту пору консоль считалась устаревшей, легаси для старого говна, а светлое будущее должно было состоять примерно из MFC.
Иронично, что 90% софта у ту пору было как раз таки под дос
ObeseYoung # 0 ⇈
OPAHrymaH # 0 ⇈
Я тебя понял. Оригинальный ANSI.SYS писался под голый ДОС и про сервисы, предоставляемые VXD, не знал. Но если его дописать, то такую функцию реализовать можно.
OPAHrymaH # 0 ⇈
DPMI играл две роли:
1. Реализовывал переходники между программой защищённого режима и функциями DOS и BIOS.
2. Реализовывал собственный API (INT 31h), в котором были функции для управления виртуальной памятью вроде VirtualAlloc, функций для работы с линейными адресами и сегментами, управления защитой, работы с обработчиками прерываний и т. п., так что в прикладной программе можно было обходиться без низкоуровневого кода.
RTM же реализовывал дополнительную библиотеку.
16-битный RTM мумулировал API OS/2 для соснольных приложений: часть функций DOSCALLS.DLL, VIOCALLS.DLL, KBDCALLS.DLL.
32-битный RTM мумулировал Win32 для соснольных приложений: часть функций kernel32.dll, user32.dll, advapi32.dll.
Для запуска ФАРа из голого DOS посредством 32RTM этих функций было недостаточно. Рантайм, позволяющий запустить ФАР из DOS, появился позже:
https://www.japheth.de/HX.html
Но даже тот рантайм, что был у Борланда, позволял собирать двойные приложения защищённого режима, которые могли работать и в голом DOS, и в винконсоли. К таким приложениям относились борландовские компиляторы и Турбо Дебагер. Даже IDA выпускалась в виде такого приложения.
Почему 16-битный RTM мумулирует функции OS/2, а не Windows? Да потому что у 16-битных Windows (Win 3.x) не было консольного API.
К слову, такой рантайм был не только у Борланда. Был Pharlap TNT DOS extender с похожим API. Его ещё использовали какие-то компиляторы (Metaware High C++ вроде).
OPAHrymaH # 0 ⇈
Я не знаю реальные примеры программ, которые бы использовали расширитель Pharlap для Windows. Когда появился Win32s, стали писать программы под Win32 API и запускать через него. Например, древний 32-битный Фотошоп спокойно запускался не только в NT и в Win95, но и в Win 3.x через Win32s.
HE_OTBE4Au_YE6KY # 0 ⇈
yet_another_one_shit # 0 ⇈
OPAHrymaH # 0 ⇈
Для поддержки массивов более 64К в 16-битном коде нужно было крутить сегмент. В защищённом режиме для этого нужно плодить записи в LDT или крутить базу.
В Борманд Паскале сделали проще: не стали реализовывать модель Huge. Т. е. писали код так, чтобы массивы и объекты укладывались в 64К. Если нужно было больше 64К, использовали датастримы: в библиотеке Турбовижн были классы, предоставляющие интерфейс к памяти как к файлу. Или использовали связанные списки и деревья, у которых каждый узел аллоцировался отдельно.
ObeseYoung # 0 ⇈
bormand # 0 ⇈
guest # 0 ⇈
Tiny. As you might guess, this is the smallest of the memory
models. All four segment registers (CS, DS, 55, ES) are set to the
same address, so you have a total of 64K for all of your code, data,
and stack. Near pointers are always used. Tiny model programs
can be converted to .COM format by linking with the It option.
Small. The code and data segments are different and don't overlap, so you have 64K of code and 64K of data and stack. Near
pointers are always used.
Medium. Far pointers are used for code, but not for data. As a
result, data plus stack are limited to 64K, but code can occupy up
to 1 MB.
Compact. The inverse of medium: Far pointers are used for data,
but not for code. Code is then limited to 64K, while data has a 1
MB range.
Large. Far pointers are used for both code and data, giving both a
1 MB range.
Huge. Far pointers are used for both code and data. Borland C++
normally limits the size of all static data to 64K; the huge memory
model sets aside that limit, allowing data to occupy more than
64K.
ObeseYoung # 0 ⇈
> 1 MB range
ucnaHckuu_CTblD # 0 ⇈
JlAKOMKA # 0
kcalbCube # 0
ура, стандартная библиотека.
кстати при чётных y2 почему-то не рисует, интересно почему
ucnaHckuu_CTblD # 0 ⇈
guest # 0
digitalEugene # 0 ⇈
guest # 0 ⇈
kcalbCube # 0 ⇈
HE_OTBE4Au_YE6KY # 0 ⇈
Выбирай, что тебе ближе.
ObeseYoung # 0 ⇈
Rooster # 0 ⇈
ucnaHckuu_CTblD # 0 ⇈
ObeseYoung # 0 ⇈
guest # 0
https://www.youtube.com/watch?v=_dydTviK8gY