Глава 2. Начало работы с Turbo Assembler.


Если ранее вы никогда не писали программ на ассемблере, то на
этом этапе следует начать работать с ним. Наверное, вы слышали о
том, что программирование на языке ассемблера сродни черной магии
и доступно лишь магам и чародеям. Не верьте этому! Язык ассемблера
это не что иное, как доступная человеку форма собственно языка
компьютера, а как вы понимаете, собственный язык компьютера в
высшей степени логичен. Кроме того, очевидно, что язык ассемблера
очень мощный язык — это единственное средство полностью
использовать всю мощь семейства процессоров Intel 80×86, которые
представляют собой сердце компьютеров семейства IBM PC и
совместимых с ними.

На языке ассемблера можно писать как целые программы, так и
комбинировать части на ассемблере с частями на Turbo C, Turbo
Pascal, Turbo Prolog, Turbo Basic и на других языках. Так или
иначе, с помощью языка ассемблера можно создавать небольшие и
исключительно быстро работающие программы. Столь же важным
свойством, что и быстродействие, является возможность управлять на
языке ассемблера любым аспектом работы компьютера, вплоть до
отдельных тактов системы.

В данной главе вам дается введение в язык ассемблера и
описание работы с уникальными средствами программ на этом языке.
Вы введете и выполните на компьютере несколько работающих программ
на языке ассемблера, как для того, чтобы «почувствовать» язык, так
и для приобретения навыка работы с ассемблером.

Глава 5, «Элементы программы на языке ассемблера», продолжает
рассмотрение этого вопроса с того места, на котором оно
заканчивается в данной главе, включая структуру программы на языке
ассемблера и фундаментальные элементы программы, а все изученное в
двух этих главах суммируется в примере программы с полным набором
приемов программирования.

Глава 6, «Дополнительные сведения о программировании на Turbo
Assembler», продолжает исследование вопросов программирования на
языке ассемблера, а глава 9, «Расширенные средства
программирования на Turbo Assembler», касается более сложных
вопросов моделей памяти, макросов и прочих вопросов для
углубленного изучения.

Разумеется, мы не сможем при помощи этих нескольких глав
сделать вас крупным специалистом по программированию на языке
ассемблера; мы просто дадим вам введение в язык ассемблера и
поможем написать первые программы. Мы очень надеемся, что у вас
есть хотя бы одна из множества замечательных книг, полностью
посвященных программированию на языке ассемблера и архитектуре PC
(см. ссылки на литературу в конце данной книги). Кроме того,
полезные справочные материалы содержатся в Техническом справочнике
по IBM DOS, Техническом справочнике по интерфейсу BIOS и
Техническом справочнике по персональным компьютерам XT; в этих
руководствах документируется интерфейс при программировании на
языке ассемблера с программным и аппаратным обеспечением системы
персональных компьютеров IBM.

Прежде чем приступить к дальнейшему чтению, вам, возможно,
понадобится прочесть главу 3, «Справочник по командной строке»,
чтобы ознакомиться с опциями командной строки. Вам также следует
инсталлировать Turbo Assembler (сделать рабочие копии с
дистрибутивных дискет Turbo Assembler, либо скопировать с них
файлы на жесткий диск), как описано в главе 1, «Установка Turbo
Assembleer», если вы этого еще не сделали.

И наконец: язык ассемблера это сложный предмет, и для
написания даже относительно простой программы вам потребуется
знание множества вещей. Иногда в приводимых примерах программ
будут использоваться средства языка, которые еще не были
рассмотрены выше, просто поскольку с чего-либо все равно надо
начать. Потерпите; все будет объяснено в свое время. Если в
какой-либо момент вас заинтересует конкретный вопрос, обратитесь к
главе 3, «Директивы» Справочного руководства.

Итак, пользуясь настоящим руководством и имея под рукой главу
3 второго тома, вы можете приступить к созданию вашей первой
программы на языке ассемблера.

Вы можете следовать данному руководству поэтапно, вводя все
примеры программ по мере их изучения, либо вы можете распаковать
находящийся на диске файл с примерами (во время установки Turbo
Assembler) и иметь все эти программы под рукой. (Независимо от
вашего решения, имена программ приводятся для вашего удобства в
самом начале примеров этих программ).

Создание вашей первой программы на Turbo Assembler
——————————————————————

В мире программирования первой программой традиционно бывает
программа, выдающая на дисплей сообщение «Hello, world»
(«Здравствуй, мир»), и мы начнем с этого сообщения.

Войдите в любой выбранный вами редактор (создающий
ASCII-файлы) и введите следующие строки, образующие программу
HELLO.ASM:

.MODEL SMALL
.STACK 100h
.DATA
HelloMessage DB ‘Hello, world’,13,10,’$’
.CODE
mov ax,@data
mov ds,ax ;DS указывает на сегмент данных
mov ah,9 ;функция печати строки DOS
mov dx,OFFSET HelloMessage ;указывает на «Hello, world»
int 21h ;вывод на дисплей «Hello, world»
mov ah,4ch ;функция конца программы DOS
int 21 h ;конец программы
END

Введя HELLO.ASM, нужно записать ее на диск.

Если вы знакомы с Си или Паскалем, ассемблерный вариант
вывода на дисплей «Hello, world» может показаться вам несколько
длинным. Действительно, программы на ассемблере всегда имеют
длинную запись, поскольку каждая отдельна команда ассемблера
выполняет меньше действий, чем команда Си или Паскаля. С другой
стороны, вы имеете полную свободу комбинирования этих команд
любыми удобными вам способами. Это означает, что в отличие от Си и
Паскаля, ассемблер позволяет вам написать программу, которая
заставит компьютер сделать все, что находится в пределах его
возможностей — иногда ради этого можно пойти на то, чтобы набить
несколько лишних строк.

Ассемблирование вашей первой программы
——————————————————————

Теперь, записав HELLO.ASM на диск, вы можете ее выполннить.
Однако перед этим вы должны преобразовать ее в выполняемый
(позволяющий загрузку и выполнение) вид. Для этого требуется два
дополнительных шага, ассемблирование и компоновка, которые
показаны на рис.2.1, где изображен полный цикл разработки
программы, состоящий из редактирования, ассемблирования,
компоновки и выполнения.

Создание новой программы
———————————>?
? ?
? ?
? —————————————
? ?Исходный файл программы на ассемблере?
? ? HELLO.ASM ?
? —————————————
? ?
? Ассемблирование
? ?
? —————————————
? ? Объектный файл ?
? ? HELLO.OBJ ?
? —————————————
? ?
? Компоновка
? ?
? —————————————
? ? Выполняемый файл ?
? ? HELLO.EXE ?
? —————————————
? ?
? Выполнение
? ?
—(При необходимости изменений)—

Рис.2.1 Цикл редактирования, ассемблирования, компоновки и
выполнения

На шаге ассемблирования исходный текст вашей программы
преобразуется в промежуточную форму, которая называется объектным
модулем, а на шаге компоновки один или несколько модулей
компонуются в загрузочную программу. Ассемблирование и компоновку
можно запускать из командной строки.

Для ассемблирования HELLO.ASM введите:

TASM hello

Если не задано другое имя файла, то HELLO.ASM будет
ассемблирован в объектный файл HELLO.OBJ. (Отметим, что расширение
имени файла вводить не требуется; Turbo Assembler в таком случае
принимает расширение .ASM по умолчанию). На экране появится
следующее:

Turbo Assembler Version 2.0 Copyright (C) 1988, 1990 by Borland
International, Inc

Assembling file: HELLO.ASM (ассемблирован файл: HELLO.ASM)

Error messages: None (Сообщения об ошибках: нет)

Warning messages: None (Сообщения уровня предупреждения: нет)

Passes: 1 (Число проходов: 1)

Remaining memory 266K (Оставшаяся память: 266К)

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

Компоновка вашей первой программы
——————————————————————

После того, как вы успешно ассемблировали HELLO.ASM, до
выполнения вашей первой программы на ассемблере останется еще один
шаг. Вы сможете запустить программу только после шага компоновки.

Для выполнения компоновки используется компоновщик TLINK,
поставляемый с Turbo Assembler. Введите в командной строке:

TLINK hello

Как и раньше, вводить расширение не требуется; TLINK по
умолчанию предполагает расширение .OBJ. По завершении компоновки
(как и раньше, максимум через несколько секунд), компоновщик
автоматически дает файлу .EXE то же самое имя, что и у объектного
файла, если явно не было задано другое имя. При успешном
завершении компоновки на экране появится следующее сообщение:

Turbo Link Version 3.0 Copyright (C) 1987, 1990 by Borland
International, Inc

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

Запуск вашей первой программы
——————————————————————

Теперь вы готовы к запуску вашей программы. По прглашению DOS
введите hello. На экране появится сообщение:

Hello, world

На этом процесс заканчивается — итак, вы только что создали и
выполнили вашу первую программу на Turbo Assembler.

Что происходило?
——————————————————————

Теперь, когда вы получили работающую программу HELLO.ASM,
вернемся назад и точно выясним, что собственно происходило от
ввода текста и до запуска программы.

Когда вы впервые ввели текст исходной программы на
ассемблере, этот текст находился в текстовом редакторе в
оперативной памяти компьютера. Если бы в этот момент выключилось
питание, независимо от причины этого выключения, исходная
программа была бы потеряна; следовательно, чтобы предотвратить
такого рода неприятность, желательно время от времени записывать
текст на диск, начиная с раннего этапа ее ввода. Если вы записали
исходный текст на диск, то в файле HELLO.ASM будет находиться
постоянная копия вашего текста, которая сохранится независимо от
возможного выключения питания компьютера. (Однако в случае
повреждения жесткого диска файл HELLO.ASM может пропасть, поэтому
рекомендуется регулярно делать запасные копии файлов). HELLO.ASM
представляет собой стандартный текстовый ASCII-файл; его можно
вывести на дисплей по подсказке DOS командой:

type hello.asm

и кроме того, такой файл можно редактировать в любом
текстовом редакторе.

При ассемблировании HELLO.ASM Turbo Assembler преобразовал
текстовые команды, находящиеся в HELLO.ASM, в их двоичные
эквиваленты объектного файла HELLO.OBJ. HELLO.OBJ это
промежуточный файл, не являющийся уже текстовым исходным файлом,
но и не ставший еще выполняемым файлом. HELLO.OBJ содержит всю
информацию, необходимую для получения из команд, находящихся в
HELLO.ASM, загрузочного кода, но имеет форму представления, в
которой он может быть объединен с другими объектными файлами в
одну общую программу. В главе 6, «Дополнительные сведения о
программировании на Turbo Assembler» вы узнаете, насколько
полезным может быть это средство при разработке больших программ.

Далее, при компоновке HELLO.OBJ, TLINK преобразовывает его в
загрузочный файл HELLO.EXE. И наконец, введя на подсказку hello,
вы тем самым запустили программу.

Теперь введите

dir hello.*

и вы получите список всех файлов HELLO на диске. Там будут
файлы HELLO.ASM, HELLO.OBJ, HELLO.EXE и HELLO.MAP.

Модифицирование вашей первой программы на Turbo Assembler
——————————————————————

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

.MODEL small
.STACK 100h
.DATA
TimePrompt DB ‘Is it after 12 noon (Y/N)?$’
;(уже за полдень (Да/Нет)?)
GoodMorningMessage LABEL BYTE
DB 13,10,’Good morning, world!’,13,10,’$’
;Доброе утро, мир)
GoodAfternoonMessage LABEL BYTE
DB 13,10,’Good afternoon, world!’,13,10,’$’
;Добрый день, мир)
.CODE
mov ax,@data
mov ds,ax ;DS указывает на сегмент данных
mov dx,OFFSET TimePrompt ;указывает на приглашение ввода
;времени
mov ah,9 ;функция печати строки DOS
int 21h ;вывод на дисплей приглашения
;ввода времени
mov ah,1 ;функция приема символа DOS
int 21h ;прием в ответ одного символа
cmp a1,’y’ ;введен символ y нижнего регистра,
;подтверждающий, что время за
;полдень
jz IsAfternoon ;да, время за полдень
cmp a1,’Y’ ;введен символ Y верхнего регистра,
;подтверждающий, что время за
;полдень
jnz IsMorning ;нет, время до полудня
IsAfternoon:
mov dx,OFFSET GoodAfternoonMessage ;указывает на дневное
;приветствие
jmp DisplayGreeting

IsMorning:
mov dx,OFFSET GoodMorningMessage ;указывает на утреннее
;приветствие

DisplayGreeting:
mov ah,9 ;функция печати строки DOS
int 21h ;вывод на дисплей соответствен-
;ного приветствия
mov ah,4ch ;функция конца программы DOS
int 21h ;конец программы
END

В этой программе добавлены два новых важных свойства: ввод и
принятие программой решения. Эта программа спрашивает, время за
полдень или нет, и принимает с клавиатуры ответ длиной в один
символ. Если введенный ответ представляет собой буквы Y нижнего
или верхнего регистров («Да»), то программа выводит на дисплей
приветствие, соответствующее дневному времени; в противном случае
выдается «утреннее» приветствие. В приведенном примере программы
присутствуют все существенные элементы, делающие программу
полезной — ввод из внешнего мира, обработка данных и принятие
решения.

Запишите модифицированную программу на диск. (При этом
исходная версия HELLO.ASM будет замещена модифицированной, а
первоначальная версия будет потеряна. Затем нужно
переассемблировать и перекомпоновать программу точно так же, как
вы делали в предыдущих примерах. Запустите программу, введя на
подсказку DOS слово hello. На дисплее появится сообщение:

It is after 12 noon (Y/N)?

с мигающим курсором, установленным после вопросительного
знака; программа ожидает ввод ответа. Нажмите Y. Программа
ответит:

Good afternoon, world!

Теперь HELLO.ASM стала интерактивной программой с принятием
решения.

В ходе программирования на ассемблере вы наверняка сделаете
множество разнообразных ошибок, как опечаток, так и в синтаксисе
программы. При ассемблировании исходного текста Turbo Assembler
может обнаруживать многие из них и выдает соответствующие
сообщения об ошибках. Вообще сообщения об ошибках делятся на две
категории: уровня предупреждения (warning) и уровня ошибки
(error). Turbo Assembler выводит сообщение уровня предупреждения
при обнаружении в тексте программы чеголибо вызывающего
подозрения, но не обязательно ошибочного; иногда предупреждение
может быть проигнорировано, но тем не менее лучше всякий раз
разобраться в причине появления этого предупреждения и убедиться,
что вы понимаете, в чем его смысл. Если же Turbo Assembler
встречает что-нибудь явно неверное, в результате чего завершить
ассемблирование и создать объектный файл невозможно, он выводит
сообщение уровня ошибки.

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

Как и любой другой язык программирования, Turbo Assembler не
может выявлять за вас ошибки в логике программы. Turbo As- sembler
сообщит вам, может ли та или иная исходная программа быть
ассемблирована вообще, но не в состоянии определить, будет ли
ассемблированная программа выполнять именно то, что вы от нее
ожидали — судить о правильности ее работы можете только вы сами.

Если приведенный пример программы вам не ясен, не
беспокойтесь. Даже имеющие опыт работы с другими языками
программисты не сразу приобретают навык свободного
программирования на языке ассемблера для 8086; действительно, нет
под солнцем ему подобного. на данном этапе вы просто получили
представление о том, как выглядит программа на этом языке. Далее в
этой главе и в главе 5, «Элементы программы на языке ассемблера»
будут рассмотрены все элементы приведенной программы.

Для получения листинга программы на дисплее или на принтере
обратитесь к руководству соответствующего текстового редактора.
Исходные файлы Turbo Assembler представляют собой обычные
текстовые ASCII-файлы, так что распечатать любой файл исходного
текста программы на языке ассемблера можно также и при помощи
команды PRINT по приглашению DOS.

Передача вывода на принтер
——————————————————————

Принтер представляет собой удобное устройство вывода; при
этом иногда требуется не только послать на принтер сам файл с
программой, но и назначить на принтер выход работающей программы.
Ниже приводится версия программы «Hello, world», в которой
приветствие выводится не на дисплей, а на принтер:

.MODEL small
.STACK 100h
.DATA
HelloMessage DB ‘Hello, world’,13,10,12
HELLO_MESSAGE_LENGTH EQU $ — HelloMessage
.CODE
mov ax,@data
mov ds,ax ;DS указывает на сегмент данных
mov ah,40h ;функция вывода на устройство DOS
mov bx,4 ;логический номер принтера
mov cx,HELLO_MESSAGE_LENGTH;число печатаемых символов
mov dx,OFFSET HelloMessage ;печатаемая строка символов
int 21h ;вывод на печать «Hello, world»
mov ah,4ch ;функция конца программы в DOS
int 21 h ;конец программы
END

В данной версии программы «Hello, world» вы заменили функцию
DOS вывода строки на экран на функцию DOS, которая посылает строку
на выбранное устройство или в файл — в данном случае на принтер.
Введя и запустив программу, вы увидите, что на принтере будет
напечатано знакомое сообщение «Hello, world». (Перед запуском
программы не забудьте, находясь в редакторе, записать ее на диск.
При этом, как и ранее, в файл HELLO.ASM попадет модифицированный
текст, а предыдущая версия программы будет потеряна.)

Можно опять модифицировать эту программу так, чтобы она
посылала сообщение «Hello, world» вместо принтера на экран, просто
заменив

mov bx,4 ;логический номер принтера

на

mov bx,1 ;логический номер стан-
;дартного устройства вывода

Внесите это исправление, затем повторите ассемблирование и
компоновку программы и запустите ее. При этом вы увидите, что при
выводе сообщения на дисплей последним будет выведен символ
«женского пола» (?). Фактически этот символ является символом
переыода бланка, который программа посылает на принтер, чтобы
последний выполнил прогон листа, на котором было напечатано
сообщение «Hello, world». поскольку экран не имеет «листов» и
ничего не знает о прогоне бланка, то при получении для вывода
символа прогона бланка на него будет выведен соответствующий
символ из набора символов PC.

Создание вашей второй программы на Turbo Assembler
——————————————————————

Теперь вы готовы к тому, чтобы ввести и выполнить программу,
которая действительно выполняет какие-то действия. Вернитесь в
текстовый редактор и введите следующую программу, которая
называется REVERSE.ASM:

.MODEL small
.STACK 100h
.DATA
MAXIMUM_STRING_LENGTH EQU 1000
StringToReverse DB MAXIMUM_STRING_LENGTH DUP(?)
ReverseString DB MAXIMUM_STRING_LENGTH DUP(?)
.CODE
mov ax,@data
mov ds,ax ;DS указывает на сегмент данных
mov ds,ax ;функция DOS считывания с логичес-
;кого устройства
mov bx,0 ;логический номер стандартного
;устройства ввода
mov cx,MAXIMUM_STRING_LENGTH ;считывание до максимального
;числа символов
mov dx,OFFSET StringToReverse ;сюда записывается строка
int 21h ;прием строки
and ax,ax ;были ли считаны какие-либо
;символы?
jz Done ;нет, поэтому конец работы
mov cx,ax ;поместить длину строки в CX,
;где она может быть использована
;как счетчик
push cx ;сохранить длину строки в стеке
mov bx,OFFSET StringToReverse
mov si,OFFSET ReverseString
add si,cx
dec si ;указывает на конец
;буфера реверсированной строки

ReverseLoop:
mov al,[bx] ;прием следующего символа
mov [si],al ;запись символов в обратном
;порядке
inc bx ;указывает на следующий символ
dec si ;указывает на предыдущий символ
;в буфере реверсированной строки

loop ReverseLoop ;перенос следующего символа,
;если он есть
pop cx ;извлечь длину строки из стека
mov ah,40h ;функция DOS записи в соот-
;ветствии с логическим номером
mov bx,1 ;логический номер стандарт;ного
;устройства ввода
mov dx,OFFSET ReverseString ;печать этой строки
int 21h ;печать реверсированной строки
Done:
mov ah,4ch ;функция конца программы DOS
int 21h ;конец программы
END

Вы убедитесь, что программа действительно работает
мнгновенно; как всегда, не забудьте сохранить ее на диске.

Запуск программы REVERSE.ASM
——————————————————————

Для запуска программы REVERSE.ASM вы должны сначала
ассемблировать ее; введите

TASM reverse

затем введите

TLINK reverse

после чего будет создан загрузочный файл.

Для запуска программы на приглашение DOS введите слово
reverse. Если Turbo Assembler выдаст вам какие-либо сообщения об
ошибках или предупреждения, тщательно проверьте текст программы и
установите его соответствие приведенному выше, после чего снова
запустите программу.

После запуска на экране появится мигающий курсор. Это
означает, что программа ожидает от вас ввод. Наберите

ABCDEFG

и нажмите Enter. Программа выведет на дисплей реверсированную
строку

GFEDCBA

и закончит работу. Снова введите в командной строке имя reverse.
На этот раз наберите строку

0123456789

и нажмите Enter. Программа выведет на дисплей реверсированную
строку

9876543210

Теперь вам стало понятно, что делает программа REVERSE. ASM:
она реверсирует любую вводимую вами строку. Быстрое
манипулирование символами и строками символов это одна из
областей, где язык ассемблера вне конкуренции, что и будет видно
из следующих нескольких глав.

Поздравляем вас! Вы ввели, ассемблировали, скомпоновали и
выполнили уже несколько программ на языке ассемблера и видели
фундаментальные основы программирования на этом языке — ввод,
обработку и вывод — в действии.

Если вам не нужен объектный файл, но вам требуется файл
листинга, либо если вам требуется файл перекрестных ссылок, а
файлы листинга или объектный файл не нужны, то в качестве имени
файла следует задать фиктивное устройство (NUL). Например:

TASM FILE1,,NUL,

ассемблирует файл FILE1.ASM в объектный файл FILE1.OBJ, не
создавая файл листинга программы, но создаст файл перекрестных
ссылок FILE1.XRF.

Теперь вы готовы к изучению основных элементов програм-
мирования на ассемблере, рассматриваемых в Главе 5, «Элементы
программы на языке ассемблера».