Форматы исполнимых файлов в dos на ассемблере
Введение
В начале было слово. Если точнее то было просто предложение от Kinder-а написать статью посвящённую макросам в FASM. Я согласился попробовать, но рассматривать макросы отдельно от синтаксиса как-то не очень правильно, а синтаксис без примеров разобрать сложно и в результате получилось сочинение о том как писать программы в FASM.
В этом сочинении будут рассмотрены основные моменты отличающие FASM от других компиляторов, правила по которым пишутся макросы и форматы выходных файлов создаваемые FASM-ом. Так же в рамках данного сочинения мы создадим несколько контролов в виде макросов.
Основы.
Данный раздел является вольным
пересказом соответствующего раздела
руководства, поставляемого с
компилятором.
Данная статья посвящена использованию макросов в компиляторе FASM. Для начала вопрос: "Что такое макрос?" (поскольку я не могу услышать Ваш ответ прямо сейчас, когда пишу эту статью, отправляйте свои ответы мне по электронной почте, если Ваше мнение отличается от моего мнения).
Макрос - это инструкция препроцессору компилятора развернуть, встретившееся в коде программы, имя макроса (возможно с параметрами) в последовательность строк кода ассемблера с использованием переданных параметров (если таковые заданы).
Далее предлагаю Вам ознакомиться с основными директивами, используемыми внутри определений макросов.
Внутри определений макросов можно использовать инструкции if и else при этом каждая инструкция if должна закрываться инструкцией end if. Пример из руководства, поставляемого вместе с компилятором:
Этот макрос является расширением инструкции процессора mov. В данном случае если оба операнда макроса являются сегментными регистрами используется связка "push - pop", в любом другом случае используется стандартная инструкция "mov op1,op2". Оператор in позволяет проверить соответствие операнда нескольким значениям в угловых скобках.
Можно ещё более расширить эту инструкцию для пересылки трёх значений второго в первый, а третьего во второй:
В данном случае нас интересует инструкция eq, которая позволяет проверить эквивалентен ли операнд какому либо значению, в нашем случае мы проверяем его отсутствие, и если он отсутствует, то подставляется ветвь if иначе подставляется ветвь else.
Директива purge позволяет отменить последнее определение макроса.
Кроме уже изложенного в определение макроса можно передавать заранее неизвестное количество операндов (пар операндов и т.д.), для этого необходимо заключить операнды, количество которых заранее неизвестно, в квадратные скобки. Например для вызова процедур написан макрос STDCALL:
Операндами этого макроса служат один обязательный (proc) и несколько необязательных параметров (arg). Директива reverse сообщает препроцессору, что следующие строки необходимо повторить столько раз, сколько параметров arg передано макросу начиная с последнего параметра. Директива common сообщает препроцессору, что следующие строки необходимо повторить только один раз. Директива forward сообщает препроцессору, что следующие строки необходимо повторить столько раз, сколько параметров arg передано макросу начиная с первого параметра. Действие директив common, forward и reverse заканчивается другой директивой common, forward или re-verse соответственно или закрывающейся фигурной скобкой. Если ни одна из этих директив не встречается в определении макроса, то макрос развернётся для всех параметров начиная с первого. Неизвестное количество параметров можно передать и другому макросу:При выполнении макроса jif ax,ae,10h,exit макрос будет развёрнут в следующую конструкцию:
Так же этот оператор можно использовать и для составления имён переменных или макросов внутри макроопределений:
Теперь при вызове данного макроса в секции данных
Мы будем иметь два массива из 10 байт каждый, с именами Chif.mas и Rab.mas.
Аналогично можно создать и переменные и макросы внутри определения макроса. Однако определить макрос внутри макроса обычным путём:
препроцессор не позволит использовать данную конструкцию, выход в использовании директивы fix она эквивалентна директиве equ, но препроцессор обрабатывает fix позже чем equ, что и позволяет использовать подобную конструкцию:
- PE формат исполняемых файлов Windows. Далее должно следовать уточнение GUI (графический интерфейс), console (консольное приложение) и native (если Вы знаете, что это такое сообщите мне). Если выбран графический интерфейс, то следует также указать версию графического интерфейса 4.0, а так же зарезервированное слово DLL, если собирается динамическая библиотека.
- MZ формат исполняемых файлов MS DOS.
- COFF или MS COFF (для линковки продуктами Microsoft)для создания объектного файла, который в дальнейшем будет линковаться к другому проекту или к ресурсам.
- ELF формат для создания исполняемых файлов UNIX подобных систем (Linux).
Директива «use 16» указывает на генерирование 16-битного кода. «org 100h» объявляет пропуск 256 байт (адреса 0000h – 00FFh). Указанные адреса зарезервированы под служебные данные (PSP).
Далее следуют команды. В регистр DX помещается адрес строки hello. Затем вызывается функция номер 9 прерывания 21h для вывода строки на экран.
Завершение работы программы осуществляется вызовом функции 4C с параметром того же прерывания 21h.
Строка hello завершается символом ‘$’, который в системе DOS обозначает конец строки.
Следует помнить, что программы типа COM не поддерживаются 64-разрядными ОС Windows. Для запуска таких программ под этими операционными системами следует использовать программу DOSBox, либо воспользоваться форматом PE, рассмотренном ниже.
Формат MZ
MZ — стандартный формат 16-битных исполнимых файлов с расширением .EXE для DOS. Назван так по сигнатуре — ASCII-символам MZ (4D 5A) в первых двух байтах.
Пример простой программы с использованием формата MZ:
Для создания нужно использовать директиву «format MZ». По умолчанию код для этого формата 16-битный.
«segment» определяет новый сегмент, за ним должна следовать метка, чьим значением будет номер определяемого сегмента. Опционально за этой директивой может следовать «use16» или «use32», чтобы указать разрядность кода в сегменте. Начало сегмента выровнено по параграфу (16 байт). Все метки, определенные далее, будут иметь значения относительно начала этого сегмента. В примере выше объявляются 2 сегмента: «data_seg» и «code_seg».
«entry» устанавливает точку входа для формата MZ, за ней должен следовать дальний адрес (имя сегмента, двоеточие и смещение в сегменте) желаемой точки входа. В нашем случае объявлена метка «start».
«stack» устанавливает стек для MZ. За директивой может следовать числовое выражение, указывающее размер стека для автоматического создания, либо дальний адрес начального стекового фрейма, если вы хотите установить стек вручную. Если стек не определен, он будет создан с размером по умолчанию в 4096 байт.
«heap» со следующим за ней значением определяет максимальный размер дополнительного места в параграфах (это место в добавление к стеку и для неопределенных данных). Используйте «heap 0», чтобы всегда отводить только память, которая программе действительно нужна.
Формат MZ, аналогично COM-программам, не поддерживается 64-рязрядными ОС Windows.
Формат PE
PE — это сокращение от Portable Executable, т.е. переносимый (универсальный) исполняемый файл. Этот формат появился еще в поздние времена Windows 3.11, но настоящее распространение получил с расцветом Windows 95. Можно сказать, что сейчас на компьютерах с Windows 9x/2K/XP/Vista/7 находится 95% исполняемых (exe, dll, драйверы(sys)) файлов — это PE файлы.
Чтобы выбрать формат PE, нужно использовать директиву «format PE», за ней могут следовать дополнительные настройки формата: «console», «GUI» или оператор «native», чтобы выбрать целевую подсистему (далее может следовать значение с плавающей точкой, указывающее версию подсистемы), «DLL» помечает файл вывода как динамическую связывающую библиотеку. Далее может следовать оператор «at» и числовое выражение, указывающее базу образа PE, и опционально оператор «on» со следующей за ним строкой в кавычках, содержащей имя файла, выбирающей заглушку MZ для PE программы (если указанный файл не в формате MZ, то он трактуется как простой двоичный исполняемый файл и конвертируется в формат MZ). По умолчанию код для этого формата 32-битный.
Пример объявления формата PE со всеми свойствами:
format PE GUI 4.0 DLL at 7000000h on 'stub.exe'
«section» определяет новую секцию, за ней должна следовать строка в кавычках, определяющая имя секции, и далее могут следовать один или больше флагов секций. Возможные флаги такие: «code», «data», «readable», «writeable», «executable», «shareable», «discardable», «notpageable». Начало секции выравнивается по странице (4096 байт).
Пример объявления секции PE:
section '.text' code readable executable
Вместе с флагами также может быть определен один из специальных идентификаторов данных PE, отмечающий всю секцию как специальные данные, возможные идентификаторы: «export», «import», «resource» и «fixups». Если секция помечена для содержания настроек адресов, они генерируются автоматически, и никаких данных определять больше не требуется. Также данные ресурсов могут быть сгенерированы автоматически из файлов ресурсов, этого можно добиться, написав после идентификатора «resourse» оператор «from» и имя файла в кавычках.
Ниже вы можете увидеть примеры секций, содержащих некоторые специальные данные:
section '.reloc' data discardable fixups
section '.rsrc' data readable resource from 'my.res'
«entry» создает точку входа для PE, далее должно следовать значение точки входа.
«stack» устанавливает размер стека для PE, далее должно следовать значение зарезервированного размера стека, опционально может следовать отделенное запятой значение начала стека. Если стек не определен, ему присваивается размер по умолчанию, равный 4096 байт.
«heap» выбирает размер дополнительного места для PE, далее должно следовать значение для зарезервированного для него места, опционально ещё может быть значение его начала, отделенное запятой. Если дополнительное место не определено, оно ставится по умолчанию равным 65536 байт, если не указано его начало, то оно устанавливается равным 0.
«data» начинает определение специальных данных PE, за директивой должен следовать один из идентификаторов данных («export», «import», «resource» или «fixups») или номер записи данных в заголовке PE. Данные должны быть определены на следующих строках и заканчиваться директивой «end data». Если выбрано определение настроек адресов, они генерируются автоматически, и никаких данных определять больше не требуется. То же самое относится к ресурсам, если за идентификатором «resourse» следует оператор «from» и имя файла в кавычках — в этом случае данные берутся из этого файла ресурсов.
Пример простой программы с использованием формата PE:
В данном примере для работы с консолью использованы функции WinAPI.
Вот такой получился краткий (надеюсь, для кого-то полезный) обзор использования форматов PE и MZ. За бортом данной статьи оказались ELF и COFF, за что прошу сильно не судить.
Человеку, занимающимся программированием на языке Ассемблера в операционной системе MS-DOS часто приходится использовать одни и те же конструкции для инициализации программы, использовать однотипные операции и функции. При этом код повторяется "один в один", и при его наборе можно сделать досадную ошибку. Чтобы это не делать, автор разработал несколько простых шаблонов для осуществления часто встречающихся однотипных операций, и предлагает к его использованию согласно лицензии GPL . Ниже приводится описание этих шаблонов.
1.9.1. Введение
Данные шаблоны предназначены для создания исходного кода на языке Ассемблер для операционной системе MS-DOS и совместимых с нею операционных системах, в том числе и для Microsoft Windows 95-7. В этих шаблонах есть повторяющиеся элементы, смысл которых будет объяснён ниже.
- Директива: page - указывает, сколько строк и позиций будет содержать листинг программы, генерируемый транслятором Ассемблера. Лучше оставить его значение, указанное в шаблоне: 60 строк и 132 позиции в строке, page 60,132;
- Директива: TITLE - указывает, как будет озаглавлен листинг программы, и какие колонтитулы будут печататься при выводе листинга. После этой директивы может идти любой текст, общий длиной до 60 символов. Автор рекомендует в качестве текста использовать имя и назначение программы;
- Директива: ASSUME - указывает, какой сегмент поставлен в соответствие определённому сегментному регистру. По-умолчанию сегменту кода соответствует регистр CS , сегментам данных - DS и ES , сегменту стека - SS . Эти сегменты должны быть определены оператором: SEGMENT перед вызовом этой директивы. Сам вызов этой директивы осуществляется в сегменте кода, обязательно перед вызовом других операторов программы. Если по каким-то причинам часть сегментных регистров не используется, вместо указания имени регистра используется слово: "NOTHING" , например: ES:NOTHING ;
- Оператор: SEGMENT - определяет имя и параметры сегмента, используемого в программе на языке Ассемблер. В качестве параметров используются:
- Имя сегмента - располагается перед именем оператора. Оно обозначает метку, под которой данный сегмент идентифицируется в программе на языке Ассемблер. Это имя фигурирует при объявлении сегмента директивой: ASSUME . Это имя используется также в операторах загрузки адреса сегмента;
- Параметр выравнивания сегмента по границе сегмента PARA . Автор рекомендует этот параметр к обязательному использованию;
- Параметр: STACK - используется только для сегментов стека. Указывает, что данный сегмент является сегментом стека;
- Параметр, заключённый в апострофы - указывает компилятору, как будут компоноваться сегменты и их содержимое при выводе листинга ассемблерного файла. Иными словами, он определяет необязательный "класс сегмента". Рекомендуется для сегментов с кодом указывать класс: 'Code' , для сегментов с данными - класс 'Data' , для сегментов стека - класс 'Stack' ;
Примечание. Несколько сегментов можно указывать только для программ с форматом файла: "EXE". Для файлов в формате "COM" возможен только один сегмент, и этот сегмент - кодовый.
Примечание: После оператора PROC следуют два параметра, определяющие, как будет производиться адресация памяти внутри процедуры. Параметр "FAR" указывает, что будут использоваться только "длинные указатели" - пара адресов: "Сегмент:Смещение". Параметр "NEAR" указывает, что будут при адресации использоваться только "короткие указатели" - "Смещение" адреса внутри текущего сегмента. В программе формата: "COM" допускаются только "короткие" указатели адресов.
Во избежание путаницы не желательно переопределять имена сегментов и процедур, приведённые в шаблонах.
Более подробное описание этих директив и операторов языка ассемблер смотри в книге Питера Абеля.
1.9.2. Формат "EXE". Шаблон для создания файла в формате "EXE" Simple001
Исполняемый MS-DOS файл формата EXE обязательно должен содержать в себе следующие сегменты:
- Сегмент кода (с кодом программы). Таких сегментов может быть несколько, если выполняемая программа содержит множество процедур;
- Сегмент стека. Этот сегмент нужен как для инициализации программы, так и для работы операторов PUSH и POP . В программе на языке Ассемблер указывается максимальный размер стека (это значение Вы должны поставить при объявлении этого сегмента).
- Сегменты данных. В-принципе, это не обязательный сегмент, тем не менее, часто используемый. В этом сегменте объявляются пользовательские переменные и константы языка Ассемблер, которые нужны для вычислений. Если в описании конструкций языка Ассемблер используется комментарий "в сегменте данных", то эти константы и переменные должны быть записаны в одном из сегментов данных.
При инициализации программы на языке Ассемблер для исполняемых файлов в формате "EXE" должны присутствовать следующие операторы:
- PUSH DS - сохранение в стеке содержимого регистра DS . Первоначально в этом регистре находился адрес загрузчика программ в командной оболочке MS-DOS;
- Далее в стек необходимо записать значение "0" . Это значение используется для инициализации загрузчика MS-DOS после выполнения программы;
- Затем в регистр DS заносится адрес сегмента с данными выполняемой программы;
- Только после этого пишется код программы на языке Ассемблер.
- Основная процедура программы (как и любая процедура на языке Ассемблер) заканчивается оператором "RET" . Этот оператор приводит сегментные регистры в первоначальное состояние и возвращает управление вызывающей программе или загрузчику командной оболочки .
Таким образом, зарезервированными словами шаблона программы на языке Ассемблер являются следующие слова:
Пример шаблона смотри ниже
1.9.3. Формат "COM". Шаблон для создания файла в формате "COM" Simple002
Исполняемый файл в формате "COM", написанный на языке Ассемблер, содержит только один сегмент - сегмент кода. Поэтому в директиве ASSUME все регистры инициализируются только одним значением: CODESG .
Для инициализации "COM" файла необходимо вначале вызвать оператор "ORG" , с помощью которого производится пропуск части кода системного загрузчика программы. Затем идёт определение переменных и констант, используемых в программе. Поскольку в файлах формата "COM" нет сегмента данных, то объявление переменных происходит в начале программы, сразу за адресом загрузчика оболочки. Поскольку, по логике MS-DOS, в первом адресе исполняемой программы в сегменте кода должен быть исполняемый оператор, а не директива определения констант, то первым оператором "COM" программы будет оператор безусловного перехода на метку JMP . В качестве метки выступает имя основной процедуры исполняемого файла "MAIN" . Между этими операторами будут располагаться описание констант и переменных программы, которое в файлах формата "EXE" располагались в сегменте данных.
Имена процедур в файле формата "COM" должны обязательно иметь параметр "NEAR" , поскольку в файлах этого формата допустимы лишь "короткие" адреса памяти (то есть только смещение относительно сегмента кода текущей программы). Заканчиваться процедура должна оператором: "RET" (последний выполняемый оператор ) и, затем, оператором: "метка программы" ENDP" . Собственно же программа должна заканчиваться директивой: "END "метка оператора JMP" .
Таким образом, зарезервированными словами шаблона программы на языке Ассемблер являются следующие слова:
Примечание. Рекомендуется писать небольшие программы для операционной системы MS-DOS именно в "COM" формате, где это возможно, поскольку двоичный код в формате "COM" в 3 - 10 раз более компактный, чем в формате "EXE". Соответственно выше и скорость загрузки, меньше время выполнения программы. Однако на размер программ в этом формате накладывается ограничение - не более 64 Кбайт.
Программы типа .exe и .com различаются не только форматом исходного текста и процедурой создания исполняемого файла при трансляции, но и форматом загрузочного файла на диске. Программы загружаются в память для выполнения с помощью функции DOS Exec (Int 21h, функция 4Bh), играющей роль системного загрузчика. При этом, если имя программы вводится в командную строку с клавиатуры, то функция Exec вызывается командным процессором Command.com.
В дальнейшем изложении для сравнительной оценки параметров программ, выполненных в разных форматах, взята одна и та же простая программа с минимально возможным набором команд (с целью экономии места, отводимого для иллюстраций).
¨ Загрузка и выполнение .COM-программы
Действия функции Exec при запуске программы типа .com выглядят следующим образом.
1. Запускаемой программе отводится вся свободная в данный момент оперативная память, в которой определяется начальный сегментный адрес программы.
2. По нулевому смещению в выделенном для программы сегменте памяти Exec создаёт специальную служебную структуру – префикс программного сегмента PSP, в котором содержится информация дляDOS об окружении программы. Впрочем, некоторые поля PSP используются и прикладными программистами, например, при разработке резидентных программ. Размер PSP всегда равен 100h или 256 байт.
а) Листинг prog_com. lst
Turbo Assembler Version 4.1
3 0000 Model tiny
6 AC A0 20 E2 A8 AF A0+
7 20 2E 63 6F 6D 0A 0D+
11 0100 proc main
13 0102 BA 0000r mov dx,offset mes
14 0105 CD 21 int 21h
15 0107 B8 4C 00 exit: mov ax,04C00h ;Функция DOS 4Сh
16 010A CD 21 int 21h ;Вызов DOS. Останов
17 010C endp main
18 end main ;Конец программы/точка входа
Groups & Segments Bit Size Align Combine Class
_Data 16 0016 Word Public Data
_Text 16 010C Word Public Code
00000: B4 09 BA 0C 01 CD 21 B8 00 4C CD 21 8F E0 AE A3 ┤○║♀☺=!╕ L=!Прог
Содержимое префикса программы PSP
Смещение
Число байтов
Описание
Инструкция INT 20h
Сегментный адрес первого свободного байта за пределами программы
Адрес перехода в Command после завершения программы (Int 22h)
Адрес обработчика Ctrl+C (Int 23h)
Адрес обработчика критической ошибки (Int 24h)
Сегмент PSP родителя
Таблица файлов задания (Job file Table – JFT)
Сегментный адрес блока окружения программы
SS:SP на входе в последний вызов int 21h
Количество байтов в JFT (по умолчанию 20)
Адресный указатель на JFT (по умолчанию PSP:0018h)
Длина командной строки в байтах
Параметры командной строки при запуске программы ) и 0Dh
3. Сразу вслед за PSP загружается сама com-программа со следующей настройкой регистров процессора: cs = ds = ss = es указывают на начальный сегмент программы, регистр ip инициализируется числом 100h (это размер PSP), а регистр sp – числом 0FFFEh. При этом образ программы в памяти после PSP в точности соответствует машинному коду программы на диске (рис. П.1.3_1, б). Таким образом, программный код, данные и стек com-программы размещаются в одном сегменте оперативной памяти объёмом 64 Кбайта, так как регистр указателя вершины стека инициализируется числом 0FFFEh.
4. Для исполнения загруженной com -программы Exec передает управление по адресу cs:100h (по этому адресу обязательно должна находиться первая исполняемая команда). После завершения программы управление передается обратно в Exec, а оттуда – родительской программе – "предку" (при запуске из командной строки – командному процессору Command.com).
¨ Загрузка и выполнение .exe-программы
В настоящее время существуют три формата .exe-программ:
– MZ-формат (разработан фирмой Microsoft для поддержки многосегментных программ в среде MS DOS);
MZ-формат, построенный компоновщиком и хранимый на диске, состоит из заголовка и собственно загрузочного модуля (рис. П.1.3_2).
В заголовке, состоящем из одного или нескольких блоков размером
512 байт, содержится информация для настройки значений сегментных регистров (в том числе регистров ip и sp) процессора, используемая при загрузке
программы в память для её исполнения. Формат заголовка приведён в
табл. П.1.3_2.
а) Листинг prog_exe.lst
Turbo Assembler Version 4.1
3 0000 MODEL small
4 0000 stack 32
; стека программой – оболочкой
8 AC A0 20 E2 A8 AF A0+
9 20 2E 65 78 65 0A 0D+
11 0016 CODESEG
12 0000 B8 0000s Start: mov ax,@data ;Установка в ds адреса
13 0003 8E D8 mov ds,ax ;сегмента данных
15 0007 BA 0000r mov dx,offset mes
16 000A CD 21 int 21h
17 000C B8 4C00 Exit: mov ax,04C00h
18 000F CD 21 int 21h ;Вызов DOS. Останов программы
19 END Start ;Конец программы/точка входа
Groups & Segments Bit Size Align Combine Class
Stack 16 0030 Para Stack Stack
_Data 16 0016 Word Public Data
_Text 16 011 Word Public Code
б) Машинный код исполняемого файла prog_exe.exe на диске объёмом 624 байта
Заголовок программы (512 байт)
00000: 4D 5A 70 00 02 00 01 00 20 00 00 00 FF FF 04 00 MZp ☻ ☺ ♦
00010: 30 00 00 00 00 00 00 00 3E 00 00 00 01 00 FB 71 0 > ☺ √q
00020: 6A 72 00 00 00 00 00 00 00 00 00 00 00 00 00 00 jr
00030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 ☺
00040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
001F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Загрузочный модуль: Сегмент кода (32 байта)
00200: B8 02 00 8E D8 B4 09 BA 00 00 CD 21 B8 00 4C CD ╕☻ o╪┤o║ ═!╕ L=
00210: 21 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 !
Сегмент данных (32 байта)
00220: 8F E0 AE A3 E0 A0 AC AC A0 20 E2 A8 AF A0 20 2E Программа типа .
00230: 65 78 65 0A 0D 24 00 00 00 00 00 00 00 00 00 00 exe◙♪$
Сегмент стека (48 байт)
00240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00250: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00260: 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F .
Рис. П.1.3_2. Листинг и машинный код программы типа .exe
Формат заголовка исполняемого .exe – файла на диске
Ещё мы знаем, что в указанном формате пишутся резидентные программы, драйверы и вирусы.
Для достижения нашей цели делаем следующее.
- Скачиваем с нашего сайта архив (DOS-1.rar) с предустановленными DOSBox и программами. Запускаем DOSBox. Стартует эмулятор MS-DOS и Norton Commander пятой версии.
- В папке D:\TASM.2_0\TASM\ находим текстовый файл PRG.ASM. Это обычный текстовый файл, который можно создать
с помощью любого текстового редактора, с расширением ASM вместо TXT. - В файл вносим код:
Чтобы посмотреть список всех возможных параметров с пояснениями для файлов tasm.exe и tlink.exe необходимо запустить эти программы без параметров. Если вы сделаете это, не выходя из оболочки NC, то, чтобы просмотреть чистое окно DOS нажмите Ctrl+O, чтобы вернуться в NC, нажмите сочетание клавиш повторно.
Батник COMPLEX.BAT предназначен для создания исполняемых файлов из двух файлов кода (названия обязательно должны быть prg.asm, prg1.asm).
Наша первая программа на ассемблере прекрасно работает!
Выше мы рассмотрели стандартный подход к программированию на TASM в системе MS-DOS. Указанным алгоритмом создания программ можно пользоваться и далее.
Можете попробывать TASMED в папке D:\UTILS\TASMED\. Программа уже настроена и готова к использованию.
Первая программа на ассемблере в среде разработки TASMED.
- подсветка ассемблерного синтаксиса;
- возможность сохранения проектов под любым именем и в любой директории;
- работа как с TASM, так и MASM.
Практические советы: группирование проектов, русский язык в MS-DOS.
Для того, чтобы в исходниках, которые вы будете просматривать в системе MS-DOS с использованием текстовых редакторов DOS и различных сред разработок нормально отображалась кириллица (например в комментариях к строкам кода) необходимо проделать следующие действия.
Конечно вопрос снимается сам собой, если комментарии писать на английском.
Читайте также: