Глава 1. Трансляция программ с языка ассемблера.

Исполнение предприятия при­ятно щекочет самолюбие.

Козьма Прутков.

Язык ассемблера фактически представляет собой машинный язык (язык процес­сора), где коды команд заменены именами. Человек лучше ориентируется в именах, чем вчислах, поэтомуязык ассемблера проще для понимания, чем машинный язык. Кроме того, сами имена могут быть говорящими, например, MOV(от MOVE - переме­щать) , ADD (прибавлять) и т.п., что дает дополнительные удобства. Другим упроще­нием языка ассемблера по отношению к машинному является использование меток вместо конкретных адресов. Это значительно упрощает работу, т.к. не нужно думать, по какому адресу расположена та или иная команда или данные.Вотдва основных момента, которые определяют язык ассемблера и отличают его от машинного языка. Дальнейшее развитие ассемблера шло по пути совершенствования макросредств. Ас­семблер, имеющий в своем распоряжении макросредства, называют макроассембле­ром. Я в своей книге почти не буду касаться макросредств, т.к. использование их, на мой взгляд, не слишком облегчает программирование на ассемблере, а, скорее, скры­вает некоторые важные моменты. Во всяком случае, я не советовал бы использовать их начинающим: детальное проникновение во все тонкости работы программы помо­жет Вам в будущем стать профессиональным программистом.

Для того чтобы начать работать на языке ассемблера, создадим в одном из разде-

ловжесткого диска подкаталог ASM. Скопируем в него следующие файлы: MASM.EXE

- транслятор с языка ассемблера, который преобразует исходный текст программы в объектный файл (PRIMER. ASM ->PRIMER.OBJ), LINK.EXE - компоновщик (редак­тор связей)1, преобразующий объектный файл в исполняемую программу, которая может быть запущена из операционной системы, редактор текста, с помощью которого мы будемподготавливатьтекстыпрограмм,что-нибудьпопроще,ЕХЕ2В1К.ЕХЕ-данная программа позволяет преобразовывать некоторые в

мы3 и может пригодиться, если у Вас старая версия программы LINK.EXE, DEBUG.EXE

- отладчик для просмотра и корректировки ЕХЕ и СОМ - программ. При работе с

- LINK в переводе с английского означает "связывать". Поэтому название "редактор связей" для программы LINK.EXE будет более правильным и более понятным. Слова "компонов­щик" и "компоновка" пришли из жаргона программистов.

1 В версиях DOS 6.00 и выше утилита EXE2BIN.EXE исчезла. Зато у программы LINK.EXE появился ключ /TINY (можно П), позволяющий делать СОМ-программы сразу из объектно­го модуля. Следует также заметить, что программа TLINK.EXE изначально имела такую возможность - ключ/Т. Т.о., чтобы получить СОМ-программуиз объектного модуля P.OBJ, достаточно набрать строку: LINK Р/TINY; или в сокращенном варианте LINKP/T;. Суще­ствуют, однако, программы заменители EXE2BIN, например, программа ЕХЕ2СОМ.информацией на диске нам также может оказаться полезным какой-нибудь дисковый редактор, например, программа DISKEDIT.EXEhs пакета Norton Utilites.

Вместо программ МА8М.ЕХЕиЕЕЧК.ЕХЕпроизводствафирмьіМісго8оЛможно с тем же успехом использовать турбо-ассемблер TASM.EXE и турбо-компоновщик TLINK.EXE производства фирмы Borland. Некоторые особенности этихутилит и их отличие от аналогичных программ фирмы MicroSoft пока для нас несущественны, однако, работа с командной строкой у Турбо-Ассемблера и Турбо-Компоновщика иная4, чем у Микрософтовских программ.

Итак, все готово. Не беда, что Вы еще не знаете языка. Первые шаги делайте вме­сте с нами. Наберите в редакторе следующий текст, который являет собой нашу пер­вую программу.

TITLE PRIMER11

; —вывод строки символов в текущую позицию курсора— CODSEG SEGMENT

ASSUME CS:CODSEG,   DS:CODSEG,   SS:CODSEG,   ES:CODSEG ORG 100H

BEGIN: • /метка

JMP BEG CODE /безусловный переход

/текст для вывода на экран

TEXT DB 'Это моя первая программа на языке ассемблера. $ ; $ - признак конца строки

BEGCODE: /метка начала основного входа

/две следующие строки необходимы для правильной работы /ЕХЕ-программы,  для СОМ-программы их можно опустить

MOVAX,CS /содержимое регистра CS

MOVDS,AX /пересылаем в регистр DS

/—вывод строки--

LEADX,TEXT /где находится строка

MOVAH,9 /номер функции DOS

INT 21Н '                    .; вызов функции ;-—теперь выходим в операционную систему-

MOVAH,4CH /номер функции DOS

INT21H /вызов функции

CODSEG   ENDS /конец сегмента

END BEGIN /конец программы и точка входа

Рис. 1.1. Вывод текста в текущее положение курсора. Программа будет работать, каквЕХЕ-, такиСОМ-варианте

4 . Поддержка синтаксиса, MASM в турбо-ассемблере осуществляется в так называемом режи­ме Ideal, в котором синтаксис MASM поддерживается в более простом варианте. По умолча­нию же турбо-ассемблер поддерживает полный стандартный синтаксис М ASM.

Программа мнойдовольно полно прокомментирована. Вы, наверное, ужедогада-лись, что комментарии в программах на языке ассемблера пишутся после -точка с запятой. раз призываю не пугаться, а принять программу как данное. Запишем ее на диск под именем PRIMER 11 .ASM.

Теперь запустим nporpaMMyMASM.EXE. На экране появится строка Source filename [.ASM]:, набираем в этой строке имя нашей программы, т.е. PRIMER 11 (расширение можно опустить) и нажмем клавишу ENTER. Далее все до предела просто - отвечаем нажатием на клавишу ENTER на следующихдва вопроса. Если программа набрана Вами без ошибок, то после выполнения трансляции в текущем каталоге появится файл PRIMER 11 .OBJ. Это объектный файл (или модуль). Следующий этап процесса трансля­ции—это компоновка. Запустим программу LINK.EXE. В ответ появится строка: Object Modules [.OBJ]:. В ответ мы опять набираем имя нашей программы, т.е. PRIMER 11 и нажимаем ENTER. Далее, как и в случае с MASM, на все вопросы отвечаем нажатием ENTER. В результате компоновки в текущем каталоге должна появиться программа PRIMER 11 .EXE - ЕХЕ-программа. Запуская ее, мы будем получать на экране строку: "Это Ваша первая программа на языке ассемблера". Конечная цель достигнута.

Трансляцию можно провести быстрее, если воспользоваться возможностями командной строкипрограмм MASM.EXEh LINK.EXE. Если записатькомандную строкув виде MASM В конце необходима). Аналогачнодлякомпоновкиможнотбратьстроку: LINKPRIMER11;. В

строкеможнонабиратьидругиекомандь1,нообэтомбудетсказанонесколькопозднее.

Конечно, Вы знаете, что в операционной системе MS DOS, кроме программ типа ЕХЕ, существуют программы с расширением СОМ (СОМ-программы). Вы еще не го­товы к тому, чтобы детально разобраться, в чем различие между ними, но кое-что Вы должны знать уже сейчас:

1. Длина СОМ-программне превышает 64 Кб, тогда какдля ЕХЕ-программтако-го ограничения не существует.

2. Загрузка СОМ-программ происходит несколько быстрее, чем ЕХЕ-программ

(впрочем, для быстрых компьютеров это практически незаметно).

3. Если Вы набрали в командной строке имя программы, скажем, АВ, то вначале операционная система ищет файл AB.COM. Если он будет найден, то операционная система его запустит. В противном случае операционная система начинает искать файл АВ.ЕХЕ. Помните об этом, когда создаете СОМ-программы. К слову будет сказано, ВАТСН-файлы ищутся операционной системой в третью очередь.

Некоторые ЕХЕ-программы могут быть преобразованы в СОМ-программы. Наша программа PRIMER 11 .ЕХЕ относится к их числу. Для этого воспользуемся утилитой EXE2BIN.EXE. Наберемотедующую строку: EXE2BIN PRIMER 11 .ЕХЕ PRIMER 11.С0М. В результате появится программа PRIMER 11.СОМ. Запустив ее, Вы получитетот же ре­зультат, что и для PRIMER 11 .ЕХЕ. Кстати, обратите внимание на длины этихдвух про­грамм. Другой способ получения СОМ-программ будетрассмотрен позднее. £сли в Ва­шем распоряжении имеется ЕШК.ЕХЕверсш}5.0ивы

бится. При компоновке СОМ-программ следует просто набрать UNK PRIMER 11 ЯГ; -тогда из объектного файла сразу получится СОМ-файл (если это возможно). Замечуеше. что тот факт, что вдша программа правильно работает и в ЕХЕ, и в СОМ-виде (чего прак­тическишшогдане бывает), резул^^ вернуться к ней и разобраться, в чем здесь дело.

Использование ВАТСН-файлов может значительно упростить процесс трансля­ции и отладки программ. Для тех, кто хорошо знаком с операционной системой MS DOS, приведем возможный и очень простой вариант такого ВАТСН-файла (Рис, 1.2.).

@ЕСНО OFF :2

WD %1.ASM

ECHO  НАЧИНАЕМ ТРАНСЛЯЦИЮ MASM %1;

IF  ERRORLEVEL   1   GOTO 1

ECHO  ВЫПОЛНЯЕМ  КОМПОНОВКУ ■

LINK %1.0ВJ;

IF  ERRORLEVEL   1 GOTO 3

ECHO   ЗАПУСКАЕМ ПРОГРАММУ

PAUSE

@ECHO ON

%1

@ECHO OFF

ECHO   ПРОГРАММА   ВЫПОЛНЕНА,    ПРОВЕРЬТЕ РЕЗУЛЬТАТ

PAUSE

GOTO   2 . :1

ECHO ВО ВРЕМЯ ТРАНСЛЯЦИИ БЫЛИ ОБНАРУЖЕНЫ ОШИБКИ

PAUSE

ECHO  ТРАНСЛИРУЕМ С  ОБРАЗОВАНИЕМ ЛИСТИНГА ECHO ДАЛЕЕ ЛИСТИНГ  БУДЕТ ЗАГРУЖЕН В РЕДАКТОР MASM %1,,; WD  %1.LST '

PAUSE GOTO 2

:3 ;

ECHO ВО ВРЕМЯ КОМПОНОВКИ БЫЛИ ОБНАРУЖЕНЫ ОШИБКИ

PAUSE GOTO 2 : END

Рис. 1.2. Вариант пакетного файла для трансляции программы с языка ассемблера.

Пусть имя пакетного файла будет GO.BAT, тогда, для того чтобы использовать его для траншягщи программ PRIMER11 .А8М,таберитешедуюшуюстрокуС10РК1МЕК11

и нажмите ENTER. Выйти из пакетного файла можно как обычно, т.е. посредством на­жатия CTRL-C. Асейчас несколько пояснений. В командной строке для MASM указы­вается исходный файл, затем имя объектного файла, Далее имя файлалистинга и, наконец,имяфайлаперекрестныхссылок(.СКР).Параметрыотделяютсядруготдругазапя-тыми. Например, строка MASM PRIMER 11,PI,PI ,PRI приведет к тому, что, кроме фай­ла PRIMER 11 .ASM, на диске появятся также Р1 .OBJ - объектный файл, P1.LST - файл листинга, PRI.CRF-файл перекрестных ссылок. Еслиже вместо соответствующего па­раметра стоят две запятые, то это означает, что соответствующий файлдолжен иметь то же имя, что и исходная программа, но соответствующее расширение.

Приведем теперь текст еще одной программы, на которой Вы сможете отработать то, что здесь узнали. Обращаю Ваше внимание нато, что получившаяся программа не может быть преобразована к СОМ-виду.

TITLE PRIMER13 ;сегмент данных DATSEG SEGMENT

ТЕХТ1   DB   'ПРИВЕТ,  ПРИВЕТ!',10,13, '$'■

DATSEG ENDS

;сегмент стека

STSEG      SEGMENT STACK

DB  60 DUP(?)

STSEG ENDS ;сегмент кода CODSEG SEGMENT

ASSUME CS-.CODSEG,   DS: DATSEG,   SS:STSEG, ES:CODSEG

BEGIN:

/следующие две  строки излишни,

;т.к .   у  сегмента   STSEG мы указали

;тип STACK

MOV АХ,STSEG ;SS должен  указывать   на   сегмент стека'

MOV MOV

должен указывать   на  тот сегмент ; где находятся данные

MOV

/теперь вывод  строки    (см.    Рис. 1.1.)

LEA DX,TEXT1

MOV АН,9

INT 21H /выходим в DOS

MOV АН,4СН

CODSEG ENDS

END   BEGIN ■ • '

Рис, 1,3, Пример еще одной программы, которая выводит на жран строку символов.

Программа всего лишь выводит на экран строку и заканчивает свою работу. В программе присутствуют три сегмента: кода, данных, стека. Замечу, что сегмент стека хоть и присутствует в программе, но, в общем, для порядка. Проделайте такой экспе­римент: уберите сегмент стека из программы, а также все, что на него ссылается. За­тем оттранслируйте программу, не обращая внимания на предупреждение, которое по этому поводу сделает Вам редактор связей LINK.EXE. Запустите программу и убеди­тесь, что она по-прежнему работает исправно. Суть здесь в том, что стек служит для временного хранения данных, а если Вы его в программе не используете, то присут­ствие или отсутствие его на работе программы никак сказаться не может.

В заключение хотелось бы поговорить об общей идеологии трансляции с языка ассемблера. Возникает законный вопрос: зачем нам нужны промежуточные (объект­ные) файлы? На первый взгляд это действительно несколько замедляет процесс разра­ботки программы. Но это только на первый взгляд. Дело в том, что из объектных фай­лов можно создавать объектные библиотеки (не перепутайте с библиотеками объек­тов) процедур, которые в готовом виде можно использовать затем для разработки дру­гих программ. Конечно, библиотеку можно иметь и в текстовом варианте5. Но, во-первых, она будет занимать гораздо больше места, а, во-вторых, подсоединение объек­тной библиотеки лишь на последнем этапе трансляции как раз и ускоряет этот про­цесс. Ну и, наконец, поскольку структура объектного файла является стандартом не только для ассемблера, но и для многих трансляторов с языков высокого уровня, появ­ляется удивительная возможность стыковки программ, написанных на разных языках. Становится возможным не только подсоединять процедуры, написанные на ассембле­ре к программам на таких языках, как Паскаль, Си, Фортран, Пролог и т.д., но и стыко­вать между собой, скажем, Паскаль и Си (см. Главу 15). На Рис. 1.4. представлена схема процесса трансляции программы, написанной на языке ассемблера.

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

И еще. Использование объектных библиотек удобно с точки зрения разработки

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

i  Текстовый модуль (библиотеку) можно подключить в нужное место программы при помощи

директивы INCLUDE. 6   Существуют одно- и многопроходные ассемблеры.

Ассемблер Компоновщик

 

 

 

 

 

 

 

 

 

 

на

ассемблера

 

О&ъевяяш коя

-►

Загружаешь мо­дулі. (ЕЩ

 

Другие

держанию фрагмента: на языке ассемблера

О&іекпіая биб-и

гие объеияше модуля

Рис. 1.4. Схема трансляции программы, написанной на языке ассемблера.

Отступление: об именах переменных, меток и другом.

В толстых и умных книжках Вы встретите утверждение о том, что имена, исполь­зуемые в программах, должны быть "говорящими". Т.е., встретив переменную, Вы или кто-то другой сразу должен понять, для чего она используется. Один из подходов в создании таких говорящих имен назьтается "венгерской нотацией". В ней предпола­гается включать в имя переменной и еетип. Сразу скажу, чтоя против использования подобных правил программистами. Изысканиями в этой области, намой взгляд, зани­маются люди, не слишком любящие программировать. Ничего не поделаешь, но пра­вила часто придумывают люди, которые данным делом не занимаются (уже, еще или вообще). Хотите совет: занимайтесь придумыванием имен, только если Вы четко по­нимаете, зачем Вам это нужно. Длинные имена, кстати, часто мешают программиро­вать. При написании длинного имени с большей вероятностью допускается ошибка. Тексты программ с венгерской нотацией вызывают у меня аллергию. Я совершенно не вижу смысла в использовании имени 1р8гС1а88№те вместо простого №те. Впрочем, дело вкуса: "Кому нравится поп, а кому - поповадочь". Мне лично нравится програм­мировать, а не выдумывать имена. В моих программах поэтому есть говорящие име­на, но много и неговорящих. Зато есть комментарии, которые помогут Вамразобрать-ся в алгоритме.