Вывод символов на экран


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

Базовая система ввода-вывода


Иногда функции DOS не отвечают вашим потребностям. Тогда настал момент обратиться к базовой системе ввода-вывода IBM PC BIOS. В отличие от DOS и прикладных программ BIOS не загружается с диска и не занимает место в 640К доступной памяти. Вместо этого BIOS хранится в памяти, доступной только по чтению (ROM или ПЗУ), в той части адресного Читать далее

Выбор режима экрана


Наиболее решающей причиной использования BIOS является управление дисплеем, так как DOS практически не предусматривает поддержки широких возможностей дисплеев IBM PC. Только с помощью вызова функций BIOS вы можете установить режим экрана, управлять цветами, получить информацию о дисплейном адаптере и т.д. Например, следующий код вызывает BIOS и устанавливает экран графического адаптера CGA в четырехцветный графический режим:

Другие ресурсы


Для программиста, работающего на Ассемблере, в IBM PC предусмотрены также другие программные и аппаратные ресурсы. Мы не будем все их рассматривать, приведем только кратко некоторые из них (подробности вы можете найти в справочных материалах):

Основные элементы программы на языке Ассемблера


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

Зарезервированные слова


Зарезервированные или ключевые слова предназначены только для использования Турбо Ассемблером. Их нельзя использовать для определения присваиваний, меток или имен процедур. Ключевые слова следует рассматривать как элементы построения программы на Ассемблере. Эти слова приведены в Таблице 5.1 (включая операции +, *, , директивы .386, ASSUME, MASM, QUIRKS) и предопределенные идентификаторы ??time, ??version, @WordSize).

Формат строки


Строки исходного кода на языке Ассемблера имеют следующий формат: <метка> <инструкция/директива> <операнды> <;комментарий>

Метки


Метка не может совпадать с любым из используемых в выражениях встроенных символов, включая имена регистров (AX, BX и т.д.) и операторы, используемые в выражениях (PTR, BYTE, WORD и т.д.). В качестве меток нельзя также использовать любую из директив IFxxx или .ERRxxx. Несколько других зарезервированных в Турбо Ассемблере идентификаторов могут использоваться только в определенных контекстах. Эти Читать далее

Директива END


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

Операнды


Мнемоники инструкций и директивы сообщают Турбо Ассемблеру, что нужно делать. С другой стороны, операнды указывают Турбо Ассемблеру, какие регистры, параметры, ячейки памяти и т.д. нужно связать с каждым вхождением инструкции или директивы. Инструкция MOV (перемещение данных) сама по себе ничего не означает. Чтобы указать Турбо Ассемблеру, откуда нужно извлечь перемещаемое значение и где его сохранить, Читать далее

Регистровые операнды


Вероятно регистровые операнды являются наиболее часто используемыми в инструкциях операндами. Регистры могут использоваться в качестве источника (исходный операнд) или приемника (целевой операнд) и при некоторых обстоятельствах могут даже содержать адрес, на который нужно выполнить переход. С регистрами можно делать много того, чего нельзя делать с константами, метками или переменными в памяти. С другой стороны, имеются Читать далее

Выражения


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

Режимы адресации к памяти


Как при использовании операнда в памяти задать ту ячейку па-мяти, с которой вы хотите работать? Очевидный ответ состоит в том, чтобы присвоить нужной переменной в памяти имя (как мы это делали в последнем разделе). С помощью, например, следующих опе-раторов вы можете вычесть переменную памяти Debts (долги) из пе-ременной памяти Assets (имущество):

Фрагмент программы


Рассмотрим следующий фрагмент программы, где в регистр AL также загружается девятый символ CharString: mov bx,OFFSET CharString+8 mov al,[bx]

Комментарии


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

Директивы определения сегментов


И в данной главе, и в предыдущей, мы уже уделили много вре-мени для пояснения того, что собой представляют директивы опреде-ления сегментов и как они влияют на составляемую вами программу. Однако, имеется еще один момент, которого мы пока не касались. Суть его в следующем: откуда Турбо Ассемблер в точности знает, в каком сегменте или сегментах находятся Читать далее

Упрощенные директивы определения сегментов


Основными упрощенными директивами определения сегментов яв-ляются директивы .STACK, .CODE, .DATA, .MODEL и DOSSEG. Рассмот-рим эти директивы, разбив их на две группы. Первой будет группа директив .STACK, .CODE и .DATA.

Директивы .STACK, .CODE и .DATA


Директивы определения сегментов .STACK, .CODE и .DATA определяют, соответственно, сегмент стека, сегмент кода и сегмент данных. Например, директива: .STACK 200h определяет стек размером в 200h (512) байт. Что касается стека, то это все, что вы сможете сделать. Необходимо просто убедиться, что в вашей программе имеется директива .STACK, и Турбо Ассемблер выделит для вас стек. Для Читать далее

Директива .MODEL


Директива .MODEL определяет модель памяти в модуле Ассембле-ра, где используются упрощенные директивы определения сегментов. Заметим, что в «ближнем» коде переходы осуществляются с помощью загрузки одного регистра IP, а в «дальнем» коде — путем загрузки регистров CS и IP. Аналогично, к «ближним» данным обращение вы-полняется только по смещению, а к «дальним» — с помощью полного адреса Читать далее

Другие упрощенные директивы определения сегментов


Имеется еще несколько общеупотребительных директив определе-ния сегментов. Вам они потребуются только для больших или специ-альных программ, поэтому мы только кратко упомянем их. За более подробной информацией вы можете обратиться к Главе 9. Директива .DATA? используется аналогично директиве .DATA, но она определяет ту часть сегмента данных, которая содержит неини-циализированные данные. Она обычно используется в модулях Ассемб-лера, Читать далее

Стандартные директивы определения сегментов


Далее мы приведем такой же пример программы, как и в преды-дущем разделе, но на этот раз используем стандартные директивы определения сегментов SEGMENT, ENDS и ASSUME. DGROUP GROUP _DATA, STACK ASSUME CS:_TEXT, DS:_DATA, SS:STACK STACK SEGMENT PARA STACK ‘STACK’

Стандартные или упрощенные директивы определения сегментов


Теперь, когда вы познакомились и с упрощенными, и со стандартными директивами определения сегментов, возникает вопрос, ка-кой набор директив определения сегментов следует использовать? Ответ зависит от типа выполняемого программирования на Ассембле-ре.

Выделение данных


Теперь, когда вы знаете, как создавать сегменты, давайте рассмотрим, как можно заполнить эти сегменты осмысленными данны-ми. Сегмент стека проблемы не представляет: там находится стек, а к стеку вы можете обратиться с помощью инструкций PUSH и POP и адресоваться через регистр BP. Сегмент кода заполняется инструк-циями, которые генерируются в соответствии с мнемоникой инструк-ций вашей программы, поэтому Читать далее

Биты, байты и основания


Основной единицей памяти компьютера является бит. В бите мо-жет храниться значение 0 или 1. Бит сам по себе не особенно поле-зен. Процессор 8086 не работает непосредственно с битами, он ра-ботает с байтами, которые состоят из 8 бит. Так как бит на самом деле представляет собой цифру с основа-нием 3, байт содержит 8-разрядное число с основанием Читать далее

Представление числовых значений


Теперь, когда вы знаете о типах данных языка ассемблера, возникает вопрос, как можно представлять значения? Легче всего пользоваться десятичными значениями (то есть с основанием 10), поскольку мы привыкли к ним в повседневной жизни. Определенно, проще всего ввести: mov cx,100 ; установить счетчик в значение 100

Представление числовых значений


Теперь, когда вы знаете о типах данных языка ассемблера, возникает вопрос, как можно представлять значения? Легче всего пользоваться десятичными значениями (то есть с основанием 10), поскольку мы привыкли к ним в повседневной жизни. Определенно, проще всего ввести: mov cx,100 ; установить счетчик в значение 100

Выбор основания по умолчанию


Чаще всего вы, вероятно, захотите использовать по умолчанию десятичные значения, просто потому, что это наиболее знакомое представление. Однако, иногда удобно использовать числа без суф-фиксов, в которых по умолчанию используется другое основание. В этом случае необходима директива .RADIX. Директива .RADIX выбирает основание, которое будет по умол-чанию использоваться для спецификации чисел. Например, директива:

Инициализированные данные


Теперь мы готовы к тому, чтобы рассмотреть способы, с по-мощью которых в Турбо Ассемблере можно определять переменные. Да-вайте сначала рассмотрим определение инициализированных данных. Директивы определения данных DS, DW, DD, DF, DP, DQ и DT позволяют вам определить переменные в памяти различного размера: DW 1 байт DW 2 байта = 1 слово DD 4 байта = Читать далее

Инициализация массивов


В одной директиве определения данных может указываться нес-колько значений. Например, директива: SampleArray DW 0, 1, 2, 3, 4 создает массив из пяти элементов с именем SampleArray, элементы которого имеют размер в слово (см. Рис. 5.7). В директивах опре-деления данных можно использовать любое число значений, умещающе-еся на строке.

Инициализация строк символов


Рассмотрим теперь создание строк символов. Символы представ-ляют собой допустимые операнды директив определения данных, поэ-тому строку символов можно определить следующим образом: String DB ‘A’, ‘B’, ‘C’, ‘D’ В Турбо Ассемблере в этом случае предусмотрена также удобная сокращенная форма: String DB ‘ABCD’