Рассмотрим следующий фрагмент программы, где в регистр AL также загружается девятый символ CharString: mov bx,OFFSET CharString+8 mov al,[bx]
Category Archives for Основы алгоритмизации и программирования
Основы алгоритмизации и программирования
Комментарии
Расскажем наконец, что представляет собой поле комментария. Комментарии не выполняют никаких реальных действий в том смысле, что они не влияют на код выполняемого Турбо Ассемблером файла. Но это не означает, что они не являются существенными.
Директивы определения сегментов
И в данной главе, и в предыдущей, мы уже уделили много вре-мени для пояснения того, что собой представляют директивы опреде-ления сегментов и как они влияют на составляемую вами программу. Однако, имеется еще один момент, которого мы пока не касались. Суть его в следующем: откуда Турбо Ассемблер в точности знает, в каком сегменте или сегментах находятся Читать далее
Упрощенные директивы определения сегментов
Основными упрощенными директивами определения сегментов яв-ляются директивы .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’
Инициализация выражений и меток
Начальное значение инициализированной переменной должно представлять собой константу, но это не обязательно должно быть число. Можно также использовать выражения: TestVar DW ((924/2)+1) а также метки:
Именованные ячейки памяти
До сих пор мы видели только, как можно присваивать имена ячейкам памяти с помощью метки, предшествующей директиве опреде-ления данных (например, DB). Другой удобный способ присваивать имя ячейке памяти предоставляет директива LABEL.
Перемещение данных
Итак, вы уже получили довольно обширное представление о при-роде языка Ассемблера, основных его концепциях и структуре прог-рамм на Ассемблере. Теперь, когда вы усвоили основы, можно сосре-доточить внимание на инструкциях языка Ассемблера, образующих ту часть программы на Ассемблере, которая и указывает процессору 8086 на необходимость выполнения конкретных действий. Давайте начнем с самой основной операции Ассемблера — Читать далее
Выбор размера данных
В языке Ассемблера с помощью инструкции MOV можно копировать байты или значения размером в слово. Давайте рассмотрим, каким образом Турбо Ассемблер определяет, с каким размером данных нужно работать.
Данные со знаком и без знака
И числа со знаком, и беззнаковые числа состоят из последова-тельности двоичных цифр. Ответственность за различие этих двух видов чисел возлагается на программиста, который пишет программу на Ассемблере (то есть на вас), а не на процессор 8086. Например, значение 0FFFFh может представлять собой либо 65535, либо -1, в зависимости от того, как ваша программа его интерпретирует.
Доступ к сегментным регистрам
Хотя для перемещения значений в сегментные регистры и из них можно использовать инструкцию MOV, это особый случай, более огра-ниченный, чем другие случаи использования инструкции MOV. Если одним из операндов инструкции MOV является сегментный регистр, то другим операндом должен быть регистр общего назначения или ячейка памяти. Загрузить константу в сегментный регистр непосредственно невозможно, и невозможно непосредственно Читать далее
Перемещение данных в стек и из стека
Со стеком (областью памяти в сегменте стека, работающей по дисциплине FIFO — «первым-пришел-первым-ушел») вы уже встреча-лись. На вершину стека всегда указывает регистр SP. Для обращения к данным в стеке, с использованием режимов адресации памяти, при которых указателем базы является регистр BP, можно использовать инструкцию MOV. Например, инструкция:
Обмен данными
Выполнять обмен содержимого двух операндов позволяет инст-рукция XCHG. Это предоставляет удобный способ выполнять операцию, которая в противном случае потребовала бы трех инструкций.
Ввод-вывод
До сих пор мы обсуждали перемещение данных между константа-ми, регистрами и адресным пространством процессора 8086. Как вы можете вспомнить, в процессоре 8086 имеется также второе, незави-симое адресное пространство, которое называется пространством ад-ресов ввода-вывода. В общем случае в качестве каналов управления и обмена данными таких устройств, как дисководы, дисплейные адап-теры, принтеры и клавиатура, могут использоваться 65536 Читать далее
Операции
Перемещение данных — это, конечно, важная функция, поскольку компьютер тратит существенную часть своего времени на перемещение данных из одного места в другое. Однако в равной степени важно иметь возможность манипулировать данными, выполняя над ними ариф-метические и логические операции. Поэтому далее мы рассмотрим арифметические и логические операции, поддерживаемые процессором 8086.
Увеличение и уменьшение
Иногда в программе не Ассемблере требуется выполнить сложе-ние, которое состоит просто в прибавлении к операнду значения 1. Такая операция называется увеличением (инкрементацией). Аналогич-но, из содержимого регистров и переменных в памяти иногда нужно вычесть значение 1. Такая операция называется уменьшением (декре-ментацией). Для таких операций, как изменение содержимого счетчи-ка или продвижение регистров-указателей по памяти все операции сложения Читать далее
Умножение и деление
Процессор 8086 может выполнять отдельные типы операций умно-жения и деления. Эта одна из сильных сторон процессора 8086, пос-кольку во многих микропроцессорах вообще отсутствует непосредст-венная поддержка операций умножения и деления, а эти операции до-вольно сложно выполнить программным путем.
Изменение знака
Наконец, мы подошли к рассмотрению инструкции NEG, которая позволяет вам изменить (инвертировать) знак содержимого общего регистра или переменной в памяти. Например, после выполнения инс-трукций: