Ассемблер для процессоров Intel Pentium
Шрифт:
Представление двоичных чисел в виде последовательности нулей и единиц часто бывает не очень удобным из-за своей громоздкости и не очень хорошей читабельности. Во многих случаях используется так называемое шестнадцатеричное представление чисел. Такая система счисления включает символы от 0 до F и, поскольку таких символов 16, называется шестнадцатеричной. Шестнадцатеричный формат нашел широкое применение в языке ассемблера. В ассемблерных листингах программ в шестнадцатеричном формате показаны все адреса, машинные коды команд и содержимое констант. Отладочная информация также выдается в шестнадцатеричном формате.
В табл. 3.1
Если немного поработать с шестнадцатеричным форматом, то можно быстро к нему привыкнуть.
Таблица 3.1. Соответствие между десятичными, двоичными и шестнадцатеричными числами
Для того чтобы различать форматы чисел, в языке ассемблера приняты специальные обозначения: В, b – двоичные числа; H, h – шестнадцатеричные числа. Приведу несколько примеров чисел в разных форматах:
56 = 00111000b = 38h
– 13= 11110101 = F5h
Сложение и вычитание чисел в шестнадцатеричном формате осуществляется по тем же правилам, что и двоичных или десятичных чисел: операция выполняется для каждого разряда с учетом переноса из младшего разряда или заема из старшего. Рассмотрим несколько примеров.
Пусть требуется сложить два числа в шестнадцатеричном формате: 3Fh и 27h:
При сложении младших разрядов, равных F и 7, результирующее значение равно 22 (в десятичной системе), то есть младший разряд будет равен 22 – 16 = 6, при этом происходит перенос в старший разряд. При сложении старших разрядов результирующее значение вычисляется как 3 + 2 + бит переноса, то есть окончательный результат равен 66L
В следующем примере необходимо вычесть шестнадцатеричное значение 7Eh из AAh:
При вычитании младших разрядов, равных А (10 в десятичной системе) и Е (14 в десятичной системе), необходим заем из старших разрядов. Тогда значение младшего разряда будет равно 16 + 10 – 14 = 12 или в шестнадцатеричной форме – С. Результат вычитания старших разрядов будет равен 9-7 = 2. Окончательный результат вычитания равен 2CL
Двоичные числа используются не только в вычислениях, но и для другой функции – с их помощью можно выводить информацию в символьном представлении на экран дисплея или периферийное устройство печати. Для стандартного представления таких символов используется код ASCII (American National Standard Code for Information Interchange – Американский национальный стандартный код для обмена информацией).
Представление символа А в соответствии со стандартом ASCII выражается шестнадцатеричным значением 41h, представление символа В – значением 42h и т. д. Наличие стандартного кода облегчает обмен данными между различными устройствами компьютера. При этом 8-битовый расширенный код ASCII, используемый в компьютерах, обеспечивает представление 256 символов, включая символы национальных алфавитов.
3.2. Первичные элементы языка ассемблера
Все ассемблерные программы состоят из одного или более предложений и комментариев. Предложение и комментарий представляют собой комбинацию знаков, входящих в алфавит языка, а также чисел и идентификаторов, которые тоже формируются из знаков алфавита. Макроассемблер MASM распознает следующий набор знаков:
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
a b c d e f g h i j k l m n o p q r st u v w x y z
0 1 2 3 4 5 6 7 8 9
? @ _ $ : . [ ] < > { }
+ / * & % ! ' ~ | \ = # ^ ; , ` "
Конструкции
языка ассемблера формируются из идентификаторов и ограничителей. Идентификатор представляет собой набор букв, цифр и символов _, ?, $ или @, причем первый элемент не должен быть цифрой. Идентификатор должен полностью размещаться на одной строке и может содержать от 1 до 31 символа (если их больше чем 31, то остальные игнорируются).Друг от друга идентификаторы отделяются пробелом или ограничителем, которым считается любой недопустимый в идентификаторе символ. Посредством идентификаторов представляются объекты программы, такие, как переменные, метки и имена.
Переменные идентифицируют находящиеся в памяти данные и в общем случае характеризуются тремя атрибутами:
– сегментом, в котором определена переменная (действительно для 16-разрядных приложений, где полный адрес переменной формируется как сегмент: смещение; для 32-разрядных приложений этот атрибут не используется);
– смещением данного поля памяти относительно начала сегмента;
– типом, определяющим число, обрабатываемое при работе с переменной.
Метка (label) является частным случаем переменной, причем ссылка на нее указывается в командах условного или безусловного перехода. Для 16-разрядных приложений метка характеризуется атрибутами сегментхмещение, для 32-разрядных – только смещением. Метка также может быть определена через другую метку с использованием директивы EQU, как в этом примере:
Именами являются последовательности символов, определенные директивой EQU и принимающие значение символа или числа. Другое название имени – константа. Примеры имен:
namel EQU 'ABCD'
digit EQU 10
Некоторые идентификаторы, называемые ключевыми словами, имеют предопределенный смысл. К ним относятся директивы ассемблера, команды (инструкции) процессора, имена регистров, операторы выражений. К таким идентификаторам относится и указатель позиции (location counter), обозначаемый символом $.
Указатель позиции представляет собой текущую позицию в текущем сегменте и имеет те же атрибуты, что и метка типа NEAR. Далее приведен пример использования указателя позиции:
stringl BYTE «Test String»
level WORD 5
res BYTE 10 DUP (?)
len EQU $-stringl
Константа len в этом примере равна 22 (именно столько байтов памяти занимают переменные stringl, level и res).
Следует помнить, что обычно ассемблер не различает строчные и прописные буквы и идентификаторы могут включать в себя буквы обоих регистров. Например, идентификаторы Abs и abs считаются идентичными. Различие между строчными и прописными буквами может быть установлено параметрами /ML и /MX макроассемблера MASM.
Рассмотрим типы и формы представления данных, которые могут быть использованы в выражениях, директивах и инструкциях языка ассемблера. Начнем с целых чисел. Целые числа могут быть представлены набором цифр и/или символов, после которых задается тип кодировки (основание счисления). Тип кодировки определяется одной из литер: В – двоичная, О – восьмеричная, D или Т – десятичная, H – шестнадцатеричная. При этом шестнадцатеричные числа не должны начинаться с буквенных шестнадцатеричных цифр (например, вместо ABh следует использовать запись OABh). Шестнадцатеричные цифры от А до F могут кодироваться в обоих регистрах.