Графические устройства

         

Раздел для начинающих



Раздел для начинающих

В данной главе приведены первые примеры программ, поэтому имеет смысл поговорить о принятом в книге оформлении текстов примеров, об описании используемых в них переменных и о некоторых общих вопросах, связанных с оформлением программ на языке ассемблера. Если вы владеете ассемблером и имеете опыт программирования на этом языке, то данный раздел можно пропустить без ущерба для понимания излагаемого в последующих главах материала. Начинающим рекомендуем обратиться к специальной литературе, а при наличии доступа к Internet посетите сайт www.assembier.ru. Данная книга не является руководством по программированию на языке ассемблера, она содержит лишь минимум сведений, необходимый для понимания действий, выполняемых в примерах.

Ассемблер — это язык команд семейства компьютеров, в котором коды инструкций и операндов заменены мнемоническими обозначениями, т. е. именами. Используемые в ассемблерных программах имена делятся на две категории — зарезервированные и выбираемые по усмотрению разработчика.

К зарезервированным относятся имена регистров, операций, директив, операторов и некоторые другие. Их нельзя изменять или использовать не по назначению, в противном случае при компиляции программы будет выдано сообщение об ошибке.
По усмотрению программиста выбираются имена меток, констант, переменных, структур данных, макросов, сегментов программ и некоторые другие. Желательно, чтобы имена несли смысловую нагрузку, т. е. указывали назначение величин, к которым они относятся, и легко читались.

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

Для большей наглядности текста отдельные части составных имен могут выделяться заглавными буквами, например oidMode, или отделяться друг от друга нижней чертой, например cur_win. He следует увлекаться слишком длинными именами, поскольку теряется наглядность и повышается вероятность ошибки при их наборе.

Команда — это элементарная единица любой ассемблерной программы, исполняемая процессором ПК. Нас интересует язык ассемблера для микропроцессоров Intel, поскольку на их основе собираются компьютеры семейства IBM PC. В записи на этом языке команда состоит из условного обозначения операции и операндов, количество которых изменяется от 0 до 3 (чаще всего 1 или 2). Операнды отделяются от операции пробелами, а друг от друга запятой и пробелами. Наличие запятой обязательно, а количество пробелов не ограничивается, поэтому вы можете оформлять текст своей программы так, как сочтете нужным.

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

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

Вернемся к командам. Операции имеют зарезервированные имена и их изменения недопустимы. Ассемблер формирует код машинной инструкции исходя из имени операции и результатов анализа операндов. Поэтому одной операции может соответствовать несколько разных кодов машинных инструкций. Например, имя mov обозначает операцию пересылки, которую выполняют 8 разных инструкций микропроцессора Intel 80386.

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

Регистры являются внутренними устройствами микропроцессора, т. е. они входят в его состав, поэтому обращение к ним происходит быстрее, чем к оперативной памяти. Начиная с Intel 8086, все модели микропроцессоров содержат 16-разрядные регистры, имеющие следующие имена:



/1/

АХ, ВХ, СХ, DX, DI, SI, ВР, SP, CS, DS, ES, SS.

Первые четыре имени списка /1/ относятся к регистрам общего назначения. При выполнении задач в них обычно находятся сами операнды, а не их адреса. Исключением является регистр вх, в котором может храниться адрес операнда. Каждый из регистров общего назначения делится на два независимых байта. Старшим байтам соответствуют имена АН, вн, сн, он, а младшим байтам — AL, BL, CL, DL.

Имена DI, SI, BP, SP относятся к регистрам-указателям. Обычно они содержат адреса оперативной памяти, в которых хранятся операнды. В таких случаях при записи команды имя регистра заключается в квадратные скобки. Регистры-указатели не делятся на байты, поскольку адрес не может быть 8-разрядным. DI и SI обычно используются при работе с данными, поэтому по умолчанию в качестве сегментного регистра процессор выбирает DS. Специально для работы со стеком предназначены ВР и SP, поэтому по умолчанию в качестве сегментного регистра используется ss.
Существует специальный регистр, содержащий адрес очередной выполняемой команды. В русскоязычной литературе его называют счетчиком команд, а в англоязычной — указателем инструкций (IP). В явном виде он не указывается ни в одной команде, поэтому его имя отсутствует в списке /1/. Тем Не менее, все команды передачи управления изменяют содержимое IP.

Последняя четверка имен списка /1/ соответствует сегментным регистрам. Они предназначены для хранения старшей части адресов операндов или команд. Содержимое сз (сегмент кодов) процессор использует при выборке очередной команды. Содержимое DS (сегмент данных) — при чтении и записи операндов. В ss хранится сегмент оперативной памяти, отведенный для стека. Регистр ES используется строковыми командами при записи результата, в остальных случаях программист может распоряжаться им по своему усмотрению. Во всех примерах, приводимых в данной книге, регистр ES используется при обращениях к видеопамяти, поэтому в нем должно находиться значение сегмента видеопамяти (видеосегмента).

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

Начиная с модели Intel 386, регистры общего назначения и указатели расширены до 32-х разрядов. Размеры сегментных регистров не изменились, но добавились два новых. Новые имена перечислены в списке /2/.

/2/

ЕАХ, ЕВХ, ЕСХ, EDX, EDI, ESI, EBP, ESP, FS, GS.

Расширение регистров и введение новых имен никак рне отразилось на назначении и возможности использования старых. Просто 16-разрядные регистры стали младшими словами 32-разрядных регистров. Однако старшие слова 32-разрядных регистров самостоятельно не существуют и поэтому не имеют собственных имен.

Одновременно с введением новых регистров был расширен набор способов адресации операндов. Адрес может находиться в любом из 32-разрядных регистров, а ЕАХ, ЕВХ, ЕСХ и EDX могут использоваться в индексных выражениях.

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

Кроме регистров, перечисленных в списках /1/ и /2/, существуют еще специальные регистры, используемые в системных задачах, программирование которых не рассматривается в данной книге.

Константы — это постоянные величины, которым присвоены определенные имена. Они описываются (или определяются) с помощью операторов присваивания, имеющих следующую структуру:

<имя константы> = арифметическое или логическое выражение>

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

При программировании на ассемблере константы могут быть только целыми числами, поэтому операторы типа PI = 3.14 вызовут сообщение об ошибке. Не все операции допускают использование констант, например, константу нельзя записать в сегментный регистр с помощью операции пересылки (mov).

Более общей формой описания констант является использование директивы EQU вместо знака равенства. Если справа (после директивы) указано арифметическое или логическое выражение, то обе директивы (EQU и =) равноценны. Однако после EQU можно записать символьное выражение, которое Макроассемблер будет подставлять вместо имени константы при каждом ее использовании в программе. Кроме того, после EQU можно указать произвольный текст, заключенный в угловые скобки. В таком случае имя константы будет соответствовать указанному тексту (за исключением угловых скобок).

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



Содержание раздела