ТЕОРИЯ ЯЗЫКОВ И ТРАНСЛЯЦИЙ

advertisement
ТЕОРИЯ ЯЗЫКОВ И ТРАНСЛЯЦИЙ
МЕТОДИЧЕСКИЕ УКАЗАНИЯ
ПО ВЫПОЛНЕНИЮ КОНТРОЛЬНОЙ РАБОТЫ
ВВЕДЕНИЕ
Изучение дисциплины «Теория языков и трансляций» предусмотрено Федеральным
государственным образовательным стандартом высшего профессионального образования,
регламентирующим процесс подготовки бакалавров по направлению 010500.62
«Математическое обеспечение и администрирование информационных систем». В
соответствии с этими же стандартами данная дисциплина должна быть обеспечена
практикумом.
Представляется целесообразным в рамках контрольной работы по дисциплине «Теория
языков и трансляций» изучить основы программирования на языке низкого уровня Assembler.
Задания контрольной работы будут способствовать закреплению знаний по соответствующим
разделам теоретической части курса, более глубокому пониманию студентами основных
вопросов компиляции и трансляции программ, а также генерации машинного исполняемого
кода.
Задания носят теоретический и практический характер, и заключается в
программировании задач на языке Assembler и ответах на вопросы.
Задания выполняются в строгой последовательности: сначала указывается условие,
затем ответ. Контрольная работа выполняется в письменном виде в виде распечаток всех
созданных документов. Объем контрольной работы не должен превышать 25 страниц
ученической тетради или 15 печатных страниц. Работа должна быть грамотно написана,
правильно оформлена. Страницы нумеруются, ставится номер варианта, подпись и дата
выполнения. В конце работы указывается список используемой литературы.
Контрольную работу необходимо представить в сроки, указанные в учебном графике.
Работы, не отвечающие требованиям методических указаний, не засчитываются.
ОБЩИЕ МЕТОДИЧЕСКИЕ УКАЗАНИЯ
Контрольная работа состоит из трех заданий – первое задание состоит в ответе на
теоретический вопрос, второе и третье задание состоит в разработке собственных программ на
языке Assembler в эмуляторе микропроцессора - emu8086.
Стартовое окно эмулятора выглядит следующим образом (рис. 1). При запуске выбирается
пункт new. Далее в следующем окне (рис. 2) нажимаем cancel. Далее в открывшемся окне
набирается программа на языке Assembler (рис.3). После запуска программы появляется
эмулятор микропроцессора, где видны регистры и их значения. Значения в регистры заносятся
в шестнадцатеричной системе счисления. Управляя значениями в регистрах микропроцессора,
поучаем необходимый результат также в регистре микропроцессора. Следует иметь в виду что
результат всегда получается в регистре AX, поэтому нужно вовремя сохранять промежуточный
результат в других регистрах BX, CX, DX.
1. Регистры
Помимо ячеек в оперативной памяти для хранения (кратковременного) данных можно
использовать регистры – ячейки, расположенные в центральном процессоре. Доступ к
регистрам осуществляется намного быстрее, чем доступ к ячейкам памяти, следовательно,
используя регистры, возможно существенно увеличить скорость работы программы.
Все регистры имеют размер слова (16 разрядов); за каждым из них закреплено
определенное имя. По назначению и способу использования регистры можно разбить на
следующие группы:
1
1.
2.
3.
4.
регистры общего назначения
сегментные регистры (CS, DS, SS, ES)
указатель команд (IP)
регистры флагов (Flags)
(AX, BX, CX, DX, SI, DI, BP, SP)
Рис. 1
Рис. 2
2
Рис. 3
1.2. Регистры общего назначения
К этой группе относятся 8 регистров:
AX
AH
AL
SI
BX
BH
BL
DI
CX
CH
CL
BP
DX
DH
DL
SP
Accumulator, аккумулятор
AX
BX
CX
DX
Base, база
Counter, счетчик
Data, данные
(буква X – eXtended, расширенный)
SI
Source index, индекс источника
DI
Destination index, индекс приемника
BP
Base pointer, указатель базы
SP
Stack pointer, указатель стека
Особенностью всех этих регистров является то, что их можно использовать в любых
арифметических, логических и других машинных операциях. В то же время каждый из этих
регистров имеет определенную специализацию: некоторые команды требуют, чтобы их операнд
или операнды обязательно находились в определенных регистрах.
В регистрах AX, BX, CX и DX возможен независимый доступ к их старший (High – выше,
старший) и младший (Low – ниже, младший) половинам. Можно сказать, что каждый из этих
регистров состоит из двух байтовых регистров. Например, с регистром AX можно работать так:
записать в него слово
(16 битов), затем считать только левую половину этого слова (байт
3
из AH), не считывая правую половину, далее можно сделать запись только в AL, не меняя AH.
1.3. Сегментные регистры
Всего 4 регистра:
CS
SS
DS
ES
Ни в каких арифметических, логических и других операциях эти регистры не могут
участвовать. Можно только записывать в них и считывать из них, да и то здесь есть
определенные ограничения.
Эти регистры используются для сегментирования адресов, которое является
разновидностью модификации адресов и которое используется для сокращения размера команд.
1.4. Регистр флагов
В ПК имеется регистр флагов. Флаг – это бит, принимающий значение 1 («флаг
установлен»), если выполнено некоторое условие, и значение 0 («флаг сброшен») в противном
случае. В ПК используется 9 флагов, причем инструктивно они собраны в один 16 – разрядный
регистр. Каждый флаг – это один из разрядов данного регистра:
IFD T
O
A
PF
CF
S
Z
F F
F
F
F F
15 14 13 12 11 10 9 8 7 6 5
4 3 2
1 0
Некоторые флаги принято называть флагами условий; они автоматически меняются при
выполнении команд и фиксируют те или иные свойства их результата; проверка этих флагов
позволяет проанализировать результаты команд. Другие флаги называются флагами
состояний; сами по себе они не меняются, и менять их должна программа; состояние этих
флагов оказывает влияние на дальнейшее поведение процессора.
Флаги условии:
CF - Флаг переноса. Он наиболее полезен в арифметических операциях над числами без знака.
Например, если результат арифметической операции не помещается в отведенную ячейку,
CF=1, иначе CF=0.
OF - Флаг переполнения. Этот флаг наиболее полезен в арифметических операциях со знаком.
Получает значение 1, если в результате операции произошло переполнение мантиссы.
ZF - Флаг нуля. ZF=1, если результат команды оказался нулевым.
SF - Флаг знака. Устанавливается в 1, если в операции над знаковыми числами получился
определенный результат.
PF - Флаг четности. Он равен 1, если в 8 младших битах результата очередной команды
содержится четное количество двоичных единиц. Учитывается обычно только в операциях
ввода- вывода.
AF - Флаг дополнительного переноса. Фиксирует особенности выполнения операции над
двоично-десятичными числами.
Флаги состояний:
DF - Флаг направления. Устанавливает направление просмотра строк в строковых
командах; при DF=0 строки просматриваются «вперед» (от начала к концу), при DF=1 – в
обратном направлении.
IF – Флаг прерываний. При IF=0 процессор перестает реагировать на поступающие к нему
прерывания, а при IF=1 блокировка прерывании снимается.
TF – Флаг трассировки. При TF=1 после выполнения каждой команды процессор делает
прерывание, чем можно воспользоваться при отладке программы – для ее трассировки.
1.5. Представление данных
В общем случае под целое число можно отвести любое число соседних байтов памяти,
однако, система команд ПК поддерживает работу с числами только размером в байт и слово и
частично поддерживает работу с числами размером в двойное слово. Если числа занимают иное
4
количество байтов, то все операции над ними надо реализовать самому программисту.
В ПК делается различие между целыми числами без знака (неотрицательными) и со
знаком. Это связано с тем, что в ячейках одного и того же размера можно представить больший
диапазон беззнаковых чисел, чем неотрицательных знаковых чисел.
1.6. Целые числа без знака
Беззнаковые числа могут быть представлены в виде байта, слова или двойного слова – в
зависимости от их размеров. Такие числа записываются в ячейки в двоичной системе
счисления, занимая все разряды ячейки. Например, если для целого числа 98 отведен байт, то
содержимым байта будет двоичное число 01100010 (62h), а если слово, то 0062h.
Поскольку в ячейке из К разрядов можно записать 2К различных комбинаций из нулей и
единиц, то в виде байта можно представить целые от 0 до 255 (=28 –1), в виде слова – целые от 0
до 65535 (=216-1), в виде двойного слова – целые от 0 до 4294967295 (=232-1).
Особенности хранения чисел в ПК. Числа размером со слово и двойное слово хранятся в
памяти в «перевернутом» виде. Например, число 98 =0062h хранится в памяти так:
А
А+1
62
00
Двойное слово 1345678h хранится так:
A
A+1
78
56
A+2
34
A+3
12
Следует отметить, в регистрах числа, размером в слово хранится в нормальном, не
перевернутом виде – за этим следят команды пересылки.
1.7. Целые числа со знаком
Эти числа можно представить в виде байта (от - 128 до +128) , слова (от – 32 768 до +32
767) и двойного слова (от – 2 147 483 648 до +2 147 483 647).
В ПК знаковые числа записываются в дополнительном коде: не отрицательное число
записывается так же, как и беззнаковое число, а отрицательное Х представляется беззнаковым
числом 2К - /Х/, где К – количество разрядов в ячейке, отведенной под число:
доп
X, если X  0
X   
k
2  X , если X  0
Например, дополнительным кодом числа +98 будет
байт 62h или слово 0062h, а
дополнительным кодом числа –98 – байт 9Eh (=158=256-98) или слово FF9Eh (=216-98=10000h62h).
Еще примеры (при ячейке в байт)
доп(0)=0=00000000
доп(1)=1=00000001
доп(-1)=256-1=255=11111111
доп(2)=2=00000010
доп(-2)=256-2=254=11111110
доп(3)=3=00000011
доп(-3)=256-3=253=11111101
доп(+126)=126=01111110
доп(-126)=256-126=130=10000010
доп(+127)=127=01111111
доп(-127)=256-127=129=10000001
доп(+128)=128=10000000
доп(-128)=256-128=128=10000000
На этих примерах видно, что в дополнительном коде самый левый бит играет роль
знакового; 0 для неотрицательных чисел, а для отрицательных –1.
Как и беззнаковые, знаковые числа размером в слово и двойное слово записываются в
памяти в перевернутом виде. При этом знаковый бит оказывается во втором (правом) байте
слова.
1.8. Представление символьных переменных
Вместо символа в памяти ПК хранится его код, записанный в двоичной системе. Под код
символа отводится один байт (можно закодировать 256 различных символов).
5
Что касается машинного представления строк (последовательности символов), то под
каждую стоку отводят нужное число соседних байтов памяти, в которые записываются коды
символов, образующих строку. Адрес первого из них считается адресом строки. Эта
последовательность записываются в нормальном «не перевернутом» виде.
1.9. Лексемы
Лексемы – это простейшие конструкции, такие как имена, числа и строки.
Идентификаторы применяются для обозначения объектов программы (переменных, меток,
и т.п.).
В языке ассемблера (ЯА) идентификатор – это последовательность из латинских букв
(больших и малых) и цифр.
Ограничения:
a) длина идентификатора может быть любой, но значащими являются только первые 31
символ.
b) идентификатор не должен начинаться с цифр.
c) в идентификаторах одноименные большие и малые буквы считаются эквивалентными (Ax,
aX, AX, ax – одно и тоже).
d) в идентификаторах нельзя использовать буквы русского алфавита.
Целые числа могут быть записаны в десятеричной, двоичной (добавляется B- binary),
восьмеричной (q) и шестнадцатеричной (h- hexadecimal).
Символы заключаются либо в одинарные, либо в двойные кавычки: “A”, ‘B’, ‘A+B’. Если
в качестве символа внутри строки надо указать кавычку то делается так: если строка
заключается в те кавычки, которую надо указать внутри строки, то эта кавычка удваевается,
иначе удваивание не требуется. Например: ‘don’’n’, ‘’don’t’’, ‘’don’’’’t’’. Разрешается
использовать кириллицу.
Программа на Ассемблере – это последовательность предложений, каждое из которых
записывается в отдельной строке. Переносить предложение на следующую строку или
записывать в одной строке два предложения нельзя. Если в предложении более 131 символа, то
132 – ой и все остальные символы игнорируются.
При записи предложений действуют следующие правила расстановки пробелов:
- пробел обязателен между двумя рядом стоящими идентификаторами или числами;
- внутри идентификаторов и чисел пробелы недопустимы;
- в остальных местах можно ставить или не ставить;
- там, где допустим один пробел, можно ставить любое число пробелов.
По смыслу все предложения ЯА делятся на три группы:
- комментарии
- команды
- директивы.
Комментарием считается любая строка, начинающаяся со знака ‘;’ (перед ним может
быть любое число пробелов) либо пустая строка.
Например:
; Заполнение регистра Ах.
В ЯА допустим и многострочный комментарий. Он должен начинаться со строки
COMMENT <маркер> <текст>.
В качестве маркера берется первый отличный от пробела символ, идущий за словом
COMMENT; этот символ начинает комментарий. Концом такого комментария считается конец
первой из последующих строк программы, в которой (в любой позиции) снова встретился этот
же маркер.
Например:
COMMENT *все это является
комментарием к тому же * и это тоже.
Такой вид комментария используется для временного исключения фрагмента программы.
6
1.10. Команды
Предложения-команды – это символьная форма записи машинных команд.
Синтаксис:
[< метка >:] < мнемокод > [<операнды>] [; < комментарий>]
Метка
Синтаксически, метка – это имя. Метка нужна для ссылок на команду из других мест
программы, например, для перехода на эту команду. В ЯА разрешается в одной строке указать
только метку (с двоеточием).
Это применяется, когда:
a) команду надо пометить двумя метками;
b) метка очень длинная => остальную часть команды
выгоднее поместить на следующей
строке.
Например:
Init:
Lab: ADD BX, AX;
Мнемокод
Мнемокод является обозначенной частью программы. Это служебное слово,
обозначающее операцию.
Операнды
Операнды обычно записываются в виде выражений состоящих из чисел или переменных.
Операнды отделяются друг от друга запятой.
Комментарий
В отличие от комментариев-предложений, эти комментарии обычно используются для
пояснения именно данной команды.
Помимо команд в программе ЯА надо указывать и другие вещи, например, константы,
переменные. Это делается с помощью директив.
Синтаксис:
[<имя>] <название директивы> [<операнды>] [;<комментарий>]
Имя, указанное в начале директивы – это, как правило, имя константы или переменной.
Название директивы, как и команда, служебное слово.
1.11. Директивы определения данных
Они применяются для описания переменных, с которыми работает программа. В
зависимости от размера переменной (байт, слово, 2 слова) используется необходимая
директива.
По директиве DB (define byte, определить байт) определяются данные размером в байт.
Синтаксис:
[<имя>] DB <операнд> {, <операнд>}
Встречая такую директиву, ассемблер вычисляет операнды и записывает их значения в
последовательные байты памяти. Первому из этих байтов дается указанное имя, по которому на
этот байт можно ссылаться из других мест программы.
Существует два способа задания операндов директивы DB (остальные способы
производны):
- ? (знак неопределенного значения);
- константные выражения от –128 до 255.
Операнд ?
Например, Х DB ?
По этой директиве описывается переменная Х. Для нее отводится один байт памяти, в
который ничего не записывается. Ассемблер запоминает адрес этого байта. Если в программе
встретится имя этой переменной, то он заменит его на этот адрес (в этом и заключается
трансляция имен).
Адрес ячейки, выделенной переменной с именем Х, принято называть значением имени Х
(не путать с содержимым ячейки памяти). Кроме того, по описанию переменной ассемблер
7
запоминает, сколько байтов занимает переменная в памяти. Этот размер называется типом
имени переменной. Таким образом, значение (адрес) и тип (размер) переменной однозначно
определяет ячейку, обозначенную этим именем.
В Ассемблере имеется оператор типа.
Синтаксис:
Type <имя>
Значением этого оператора является размер ячейки (в байтах), выделенной под
переменную с указанным именем. Если переменная описана по директиве DB, то для ее имени
значение этого оператора равно 1. В ЯА имеется стандартная константа с именем Byte и
значением 1.
Операнд – константное выражение от –128 до 255
Язык Ассемблер позволяет в качестве операндов записать выражение. Оно будет
вычислено и результат запишется в ячейку. Таким образом, мы не только создаем переменную
(отводим ячейку), но и сразу заносим значение.
В простейшем случае начальное значение задается в виде числа с величиной от –128 до
255.
Например:
А DB 254 ; 0FEh
B DB -2 ; 0FEh (=256-2=254)
Операнд-число, естественно, переводится в двоичную систему.
В другом случае в качестве начального значения переменной указывается символ. При
этом в качестве операнда можно указать как сам символ, так и его код. Например, эти
директивы эквивалентны:
Q DB 2Ah Q DB ‘*’
Важно отметить, что если указать в качестве операнда число, выходящее за рамки (-128,
255), то ассемблер зафиксирует ошибку.
Директива с несколькими операндами
Выше рассмотренные способы применены к описанию скалярных переменных. Если же
потребуется описать массив из 4 байт, то это можно сделать так:
M DB 2, -2, ?, ‘*’.
По директиве DB с несколькими операндами ассемблер выделяет в памяти соседние
байты памяти, по одному на каждый операнд, и записывает в эти байты значение операндов. В
нашем случае память заполнится так:
02
0FEh
2Ah
Операнд-строка
Возможно еще оно сокращение в директиве DB: если в ней несколько соседних операндов
– символы, то их можно объединить в одну строку. Например, следующие директивы
эквивалентны:
S DB
S DB
‘a’, ‘b’, ‘c’
‘ab’, ‘c’
S DB ‘abc’
S DB ‘a’, ‘bc’
В этом случае произойдет такое же заполнение памяти, как и в предыдущем случае. Также,
Type S=Byte, то есть S – имя ячейки с кодом символа ‘a’.
Операнд-конструкция повторения DUP
Рассмотрим еще одно сокращение. Зачастую в директиве приходится указывать
одинаковые операнды. Например, описание массива R из 8 элементов с занесением нулей:
R DB 0,0,0,0,0,0,0,0
Эту директиву можно записать короче:
R DB 8 DUP(0)
Здесь в качестве операнда используется конструкция повторения, которая в общем случае
8
имеет вид:
K DUP (P1, P2, …, Pn),
где К – константное выражение с положительным значением, n>=1, Pi – любой
допустимый операнд. Например, директивы слева и справа эквивалентны:
X DB 2 DUP (‘ab’, ?, 1)
X DB ‘ab’, ?, 1, ‘ab’,?,1
Y DB -7, 3 DUP (0, 2 DUP(?)) Y DB -7,0,?,?,0,?,?,0,?,?
Вложенность конструкции DUP можно использовать для наглядного описания
многомерных массивов.
Hапример:
A DB 20 DUP (30 DUP (?))
Описывает массив А размерностью 2030.
Директивой DW (define word, определить слово) описываются переменные размером в
слово. Она аналогична директиве DB, поэтому далее вкратце опишем ее использование.
Операнд ?
Пример: А DW ? (создается переменная А размером в слово).
В ЯА есть стандартная константа с именем Word и значением 2. Поэтому Type A=Word=2.
Константное выражение со значением от –32768 до 65535
Пример :
B DW 1234h
C DW -2
Как и в случае директивы DB, не отрицательные числа записываются в память как числа
без знака, а отрицательные числа – в дополнительном коде.
В частном случае рассматриваемого вида операнды директивы DW может быть строка из
одного или двух символов,
Например:
S1 DW ‘01’ или S2 DW ‘1’
Если указана строка из двух символов, тогда ЯА берет коды указанных символов (код ‘0’
– 30h и код ‘1’ – 31h) и образует из них число-слово (3031h). Если же указан один символ,
тогда к нему слева приписывается символ с кодом 0, то есть S2 будет содержать начальное
значение 0031h.
Несколько операндов, конструкция повторения.
В правой части директивы DW можно указать любое число операндов, а также
конструкцию повторения.
Например:
E DW 40000, 3 DUP (?)
Директива DD
По этой директиве (define double word) описываются переменные, под которые отводятся
двойные слова. Поэтому имена этих переменных имеют тип 4 или DWord. В остальном эта
директива похожа на DB и DW.
Операнд ?
Пример: A DD ?
Целое число со значением от – 231 до 232 - 1
Пример: B DD 123456h.
Константное выражение (со значением от –215 до 216 - 1)
Причина такого диапазона чисел в том, что в ЯА все выражения вычисляются в области
16-битовых чисел, то есть результаты всех операций берутся по модулю 216 (10000h). Поэтому
построить выражение, значением которого является
32-битовое или даже 17-битовое число,
не удастся. Единственное исключение – это явно задать в директиве DD “большое” число. Если
же мы укажем хотя бы одну операцию, то ответ тут же будет взят по модулю 216 .
9
Например:
по директиве X D 8000h+8002h
Начальным значением переменной Х станет число 2, а не число 10002h.
Несколько операндов, конструкция повторения.
Например:
X DW 33 DUP (?) , 123456h.
Директивы эквивалентности и присваивания
Директива EQU (equal, равно) применяется в ЯА для описания констант.
Синтаксис:
<имя> EQU <операнд>
После описания константы при последующих встречах этой константы в тексте
программы при компиляции будет заменяться на операнд.
Например, эти директивы эквивалентны:
A EQU ‘*’
T DB ‘*’
T DB A
Рассмотрим возможные операнды директивы EQU.
Операнд-имя
Если в правой части директивы указано имя регистра, переменной, константы и т. п.,
тогда имя слева объявляется синонимом данного имени и все последующие вхождения в текст
программы этого имени-синонима ассемблер будет заменять на имя, указанное справа.
Например: A DW ?
B EQU A
C DW B ; эквивалентно C DW A
Имена-синонимы используются для наглядных обозначений. Например, как имя-синоним
регистра.
Операнд - константное выражение
Примеры: N EQU 100
K EQU 2*N-1
B EQU ‘*’
В этом случае значением константы объявляется значение выражения, на которое оно
будет заменяться при компиляции.
Если в константном выражении используется имена других констант, то они должны быть
описаны выше данной директивы EQU.
Операнд - любой другой текст
Пример: S EQU ‘Вы ошиблись’
LX EQU X+(N-1)
В данном случае считается, что указанное имя обозначает операнд в том виде, как он
записан (операнд не вычисляется). Именно на этот текст будет замещаться каждое вхождение
данного имени в программу.
Например, следующие предложения эквивалентны:
ANS DB S, ‘!’
ANS DB ‘Вы ошиблись’, ‘!’
NEG LX
NEG X+(N-1)
Еще одна директива ЯА, похожая на EQU
Директива присваивания:
<имя>=<константное выражение>.
Это выражение определяет константу с именем, указанным в левой части, и числовым
значением, равным значению выражения справа. В отличие от констант, описанных по
10
директиве EQU, данная константа может менять свое значение, обозначая в разных частях
текста программы разные числа.
Например:
K=10
A DW K ;  A DW 10
K=K+4
B DW K
;  B DW 14
По окончании – 2 характерных примера:
K=1
N EQU K
A DW N ; A=1
K=2
B DW N ; B=2
Имя N – синоним K,
поэтому
А DW N эквивалентно
A DW K
K=1
N EQU K+10
C DW N ; C=11
K=2
D DW N ; D=11
В этом случае N сразу
вычислится и не будет
зависеть от К
Выражения
Выражения в ЯА могут состоять только из констант и чисел. Вычисления осуществляются
на этапе трансляции по модулю 216 (от 2-15 до 2-16-1).
Операции, применяемые в выражениях:
 Одноместные плюс и минус +К, -К
 Операторы сложения и вычитания К1+К2, К1-К2
Операторы умножения и деления: K1K2, K1K2, K1 MOD K2 (MOD-остаток от деления).
Важно заметить, что если X,Y-переменные, то X-Y - это не разность между значениями
переменных, а разность между их адресами;
Например: X DB 3, 5
Y DB 15
Z DB Y-X ; Z=2
Для сокращения записи операндов будем использовать след обозначения:
i18, i16, i32
константное выражение
r8, r16
регистр общего назначения
Sr
сегментный регистр CS, DS, SS, ES
m8, m16, m32
ячейка памяти (адресное выражение)
1.11. Команды пересылки
Команда MOV
Синтаксис: MOV <op1>, <op2>
По этой команде значение ор2 пересылается в ор1: ор1=ор2. Флаги эта команда не меняет.
Допустим след комбинации операндов:
Op1
Op2
r8
i8,r8,m8
m8
i8,r8
r16
i16,r16,sz,m16
Sr(кроме Cs)
r16,m16
11
m16
i16,r16,Sr
Замечание: из таблицы видно, что запрещены пересылки из
одной ячейки в другую, из
одного сегментного регистра в другой, запись константы в сегментный регистр.
Замечание: в ПК числа размером в слово хранятся в памяти в «перевёрнутом» виде, а в
регистрах - в нормальном виде. Команда MOV учитывает это и при пересылки слов между
памятью и регистрами сама «переворачивает» их.
Как правило, команде MOV легко узнается тип (размер) одного из операндов, он и
определяет размер пересылаемой величины. Иногда бывает необходимым явно указать тип
одного из операндов команды. Это можно сделать с помощью оператора PTR (от pointer,
указатель).
Синтаксис:
<тип> PTR <выражение>,
где <тип>-это Byte, Word или Dword, а <выражение> может быть константа или адресным.
Пример: Z DW 1110 h ;
z 10h|11h
mov byte ptr Z, 0; z 0 |11r z=1100h
Команда XCHG (exchange)
Синтаксис:
XCHG <op1>, <op2>
Команда меняет местами значения своих операторов (они должны быть либо словами,
либо байтами). Флаги при этом не меняются.
Пример:
Mov ax,62 ; Ax=62
Mov Si,135 ; si =135
XCHG Ax,Si ; Ax=135 Si=62
Допустимые значения операндов команды XCHG:
Ор1
Op2
r8
r8, m8
m8
r8
r16
r16,m16
m16
r16
Как видно, не допускается перестановка содержимого двух ячеек памяти.
Команды сложения и вычитания.
Что произойдет, если, например, при ячейке размером в 8 байтов мы складываем 250 и 10.
Результат (260, или 100000100 в) не «влезет» в байт. В этом случае в ПК ошибка не
фиксируется (программа не прерывается), левая единица (единица переноса) отбрасывается и в
качестве ответа выдаётся искаженная сумма (00000100 в , т.е. 4). Но зато во флаг переноса CF
записывают 1.
Такое суммирование с отбрасыванием единицы переноса в математике называется
суммированием по модулю 2K (К- размер ячейки), при этом в флаге CF фиксируется, был ли
перенос:
 x  y, если x  y  2 K , CF  0
сумма (x, y)  (x  y) mod 2 K  
 x  y  2 K , если x  y  2 K , CF  1
При вычитании без знаковых целых чисел также возникает проблема: что делать, если при
вычитании X-Y оказалось X<Y? Ведь в этом случае получается отрицательная разность, а это
уже вне области без знаковых чисел.
В ПК поступают следующим образом: при X>Y выполняется обычное вычитание, но если
X<Y, тогда числу X делается «заём» единицы (к числу X прибавляется величина 2 K) и только
1  2  (2 8  1)  2  (256  1)  2  257  2  255
после этого производится вычитание. Например. При K=8 вычитание 1-2 производится так:
12
(в двоичной системе замена 1 на 256+1-это замена 00000001 на 100000001, т.е. приписывание 1
слева). При этом ошибка не фиксируется, зато флаг переноса CF заносится 1, что сигнализирует
о займе 1 , о неправильном результате.
Такое вычитание в математике называют вычитанием по модулю 2K:
Теперь рассмотрим сложение и вычитание знаковых чисел. Поскольку целые числа со
 x  y, если x  y, CF  0
разность (x, y)  (x  y) mod 2 K   K
(2  x)  y, если x  y, CF  1
знаком представлены в дополнительном коде, то складывать и вычитать их можно по
алгоритмам для беззнаковых чисел. Делается это так: дополнительные коды знаковых
операндов рассматриваются как числа без знака и в таком виде их складывают или вычитают, а
полученный результат затем рассматривают как дополнительный код знакового ответа.
Пример 1: Сложить +3 и –1 .(K=8)
Доп.(+3)=3. Доп.(-1)=256-1=255.
Складываем (3+255) MOD 256=258 MOD 256=2.Теперь величина 2 рассматривается как
доп.код ответа, т.е. +2
Пример 2: Сложить –3 и +1 (К=8)
Доп.(-3)=256-3=253 Доп.(+1)=1.
Складываем: (253+1) MOD 256=254.Теперь рассматриваем эту величину как доп.код
ответа, получим результат
–2 (254=256-2).
Однако, возможны проблемы! Например, в байте знаковые числа находятся в области от
–128 до 127. Рассмотрим сложение знаковых чисел +127 и +2.Складывая их как знаковые числа
127 и 2 , получаем 129. Эту величину надо рассмотреть как дополнительный код: поскольку
129=256-127, то суммой будет считаться –127.
Почему так вышло? При представлении чисел левый разряд считается знаковым (1«минус», 0-«плюс»), а на модуль числа отводится 7 разрядов справа. У нас не получился ответ
129 =10000001 в, модуль которого не вмещается в эти 7 разрядов, поэтому модуль «залез» в
знаковый разряд, изменив его на противоположный. Такое «залезание» модуля (мантиссы,
цифровой части) числа на знаковый разряд называется переполнением мантиссы. В общем
случае оно происходит , если складывать числа одно знака, и настоящая сумма оказывается вне
диапазона представимых знаковых чисел (при К=8 [-128,127]). Переполнение мантиссы
фиксируется во флаге переполнения OF: он получает значение 1 , если было переполнение, и 0
иначе.
Аналогичное переполнение возможно и при вычитании, например : (+127)-(2)=127+2=129, а это дополнительный код числа –127.
Замечание. При сложении и вычитании чисел меняются также флаг нуля ZF и флаг знака SF.
Флаг ZF получает значение 1, если результат оказался нулевым, и значение 0 иначе. В флаг CF
заносится знаковый (самый левый) бит результата. Этот флаг полезен при работе со знаковыми
числами. CF=1, если результат отрицательный.
Пример:
9-9=0  ZF=1 SF=0
8-9=-1  ZF=0 SF=0
9-8=1  ZF=0 SF=0
Команды сложения и вычитания.
Синтаксис:
Сложение:
ADD <op1>, <op2>
Вычитание(Subtract): SUB <op1>, <op2>
В этих командах допустимы след. комбинации операндов:
Ор1
Op2
r8
i8, r8, m8
m8
i8, r8
13
r16
m16
i16, r16, m16
i16, r16
Команда ADD складывает операнды и записывает их сумму на место первого операнда:
ор1:=ор1-ор2.
Например:
ADD AH,12 ;AH:=AH+12
SUB SI, Z ; SI:=SI-Z
ADD Z, -300 ; Z:=Z+(-300)
Числа могут быть как знаковыми, так и беззнаковыми. В этих командах меняются флаги
переноса CF, переполнения OF, знака SF и нуля ZF.
Следующие команды увеличивают и уменьшают соответственную единицу: Inc <op>
Dec <op>
В этих командах допустимы следующие виды операндов: r8,m8,r16,m16.
Следующая команда рассматривает свой операнд как число со знаком и меняет его знак на
противоположный: ор:= -ор.
Neg <op>
Например:
Mov ah, 1
Neg ah; ah=-1
Здесь есть исключения: если ор=-128, то операнд не меняется, т.к. нет знакового числа
+128. Аналогично для чисел-слов: если значения операнда равно –32768, то команда не меняет
операнд. В этом особом случае флаг OF получает значение 1.
Ещё 2-е команды:
Сложение с учетом переноса: ADC <op1>, <op2>
Вычитание с учетом переноса: SBB <op1>, <op2>
Допустимые типы операндов - как в командах ADD и SUB.
Эти команды аналогично командам ADD и SUB за одним исключением – в команде ADC
к сумме операндов ещё прибавляется значение флага переноса CF:op1:=op1+op2+CF, а в
команде SBB из разности операндов ещё вычитается значения этого флага ор1:=ор1-ор2-CF.
Эти команды могут пригодится для работы с числами, размером Dword и более.
Например, сложить два числа размером Dword :
X=1204f003h и Y=8052300fh. Условно
разбиваем каждое число на два слова. Сначала складываем младшие (правые) части их,
используя команду ADD. При этом может получиться единица переноса , которая попадает в
флаг CF. Поэтому старшие (левые) части следует складывать командой ADC, которая и
учитывает эту единицу.
X=1204
F003
+
+
Y=8052
300F
9256
12012
+
1
CF
9257
2012
Замечание: При сложении старших разрядов также может получиться единица переноса.
Аналогичным образом реализуется вычитание беззнаковых чисел размером в двойное
слово.
Например: Ax, Bx-X,Cx, Dx-Y. Тогда:
(Ax,Bx):=(Ax,Bx)+(Cx,Dx)
ADC Bx,Dx; Bx=Yмл +Yмл, CF-перенос
ADC Ax,Cx ; Ax:=Xст +Yст + CF
(Ax,Bx):=(Ax,Bx)-(Cx,Dx)
Sub Bx,Dx : Bx:=Xмл-Yмл, CF – заем еденицы
SBB Ax,Cx :Ax:=Xст-Yст-CF
14
Команды умножения и деления
Команды умножения.
Если сложение и вычитания беззнаковых чисел происходит по одним и тем
же алгоритмам, (т.е. применяются одни и те же команды), то умножение чисел
этих двух классов выполняется по разным алгоритмам.
Синтаксис:
Умножение целых без знака: Mul <op>
Умножение целых со знаком: IMul <op>
В остальном эти команды действуют одинаково:
Умножение байтов: AX:=Al*<op> (op: r8,m8)
Умножение слов: (Dx,Ax):=Ax*<op> (op: r16,m16)
(В регистре Dx-старшая часть, в Ax- младшая)
Пример:
N db 10
Mov Al,26
Mul N ; Ax:=26*10=260=0104h
Mov Ax,8
Mov Bx,-1
IMul Bx;(Dx,Ax)= -8= 0FFFF FFF8 h
Dx
Ax
Как видно, результат умножения занимает двойной формат. Однако при умножении
маленьких чисел нет смысла переходить в программе на двойной формат. Если же мы
заранее не знаем , какие числа будут перемножаются , то есть после умножения возможно ли
остаться работать в том же формате или следует переходить на удвоенный формат. Это
может оценить по флагам CF и OF:
CF=OF=1 – если произведение занимает двойной формат
CF=OF=O –если произведению достаточен формат сомножителей.
Команды деления.
Как умножение, деление чисел без знака и со знаком также реализуется двумя командами:
Деление целых без знака: DIV op
Деление целых со знаком: IDIV op
Команды действуют следующим образом:
а) деление слова на байт (op: r8,m8)
AH:=Ax mod <op>, Al:=Ax div op
б) деление двойного слова на слово:
(op: r16,m16)
Dx:=(Dx,Ax) mod <op>, Ax:=(Dx,Ax) Div <op>
Примечание: При выполнении команды деления возможно появление ошибки с названием
«деление на 0 или переполнение ». Она возникает в двух случаях:
-делитель равен 0 (ор=0);
-не полное частное не вмещается в отведённое ему место (например, при делении
слова=600 на байт =2 результат типа байт =300 не войдет в AL)
При такой ошибке ПК прекращает выполнение программы.
Изменение размеров числа.
Зачастую приходится увеличивать размер числа. Например, если необходимо сложить
число, размером в слово, с числом размером в байт; таких команд в ПК нет, поэтому следует
увеличить байт до слова. Если число трактуется как беззнаковое, то слева добавляются нули. А
если число трактуется как знаковое, то в этом случае следует посмотреть на его знак и
добавлять нули, если число  0 и FFh , если число < 0.
15
Для осуществления расширения числа типа Byte со знаком в Ассемблере используется
команда:
Расширение байта до слова: CBW
В этой команде операнд берётся из AL, а результат записывается в AX, т.е.
00h при AL  0
AH : 
0ffh при AL  0
Флаги эта команда не меняет.
Аналогичная команда осуществляет расширение знакового числа из слова до двойного
слова: AX (Dx, Ax)
Расширение слова до двойного слова: CWD
Безусловный переход
Переходы бывают условными и безусловными. Отметим, что в ПК команды перехода не
меняют флаги.
Безусловный переход (Jump): JMP <op>
Операнд <ор> указывает адрес команды, которая должна быть выполнена следующей.
Указать адрес можно двумя способами:
a) в качестве <ор>использовать метку; этот переход называется прямым. Например:
L: Mov Ax,5
ROW L
b) в качестве операнда использовать переменную, содержащую адрес. Например:
JMP R; GMP L
Такой переход называется косвенным.
Команды сравнения и условного перехода
Условный переход реализуется в два шага: сначала сравниваются две величины, в
результате чего соответствующим образом формируются флаги (ZF,SF и т.д.), а затем
выполняется собственно условный переход.
Сравнение (compare): CMP<op1>,<op2>
Эта команда эквивалентна команде SUB за одним исключением: вычисленная разность
ор1-ор2 никуда не записывается. Поэтому единственный и главный эффект от этой команды –
это установка флагов, характеризующих эту разность.
Команда условного перехода.
Все команды условного перехода начинаются с буквы J (om jump). За буквой J следует
одна или несколько букв, в сокращенном виде описывающих условие.
Все команды условного перехода можно разделить на три группы.
В первую группу входят команды, которые ставятся после команды сравнения. В их
мнемокодах с помощью определенных букв описывается тот исход сравнения, при котором
надо делать переход. Ниже перечисленные эти буквы:
E-equal (равно)
N-not (не, отрицание)
G-greater (больше)- для чисел со знаком
L-less (меньше)-для чисел со знаком
A-above (выше, больше)- для чисел без знака
B-below (ниже, меньше)- для чисел без знака
Замечание: Система сравнения для чисел со знаком и чисел без знака разная, т.к. после
сравнения чисел со знаком и чисел без знака следует реагировать на разные флаги.
Флаги:
CF – содержит 1, если полученная сумма вышла за рамки размерности числа (флаг переноса)
CF=OF=1,если произведение занимает двойной формат.
OF- (переполнение мантиссы) содержит единицу, если результат сложения беззнаковых чисел
«залез» на крайний левый бит, обозначающий знак.
ZF- (флаг нуля)=1, если нулевой результат.
16
SF- (флаг знака) содержит знаковый, самый первый бит результата.
В таблице 1 приведены возможные варианты команд условного перехода и значения
просматриваемых командой флагов.
Таблица 1.
Мнемокод
Содержательное
Состояние флагов
условие
Для перехода
Для любых чисел
JE
JNE
ZF=1
Op1=op2
ZF=0
Op1op2
Для
чисел
со SF<>OF
JL/JNGE
знаком:
JLE/JNG
SF<>OF или ZF=1
Op1<op2
JG/JNLE
SF=OF и ZF=0
Op1<=op2
LGE/JNL
SF=OF
Op1>op2
Op1>=op2
JB/JNAE
CF=1
Для чисел без CF=1 или ZF=1
LBE/JNA
знака:
JA/JNBE
CF=0 и ZF=0
Op1<op2
JAE/JNB
CF=0
Op1<=op2
Op1>op2
Op1>=op2
Пример: Z,Y и Z размером в слово. Требуется записать в Z максимальное из Х и Y.
Решение этой задачи различно для чисел со знаком и без знака.
; числа со знаком
; числа без знака
MOV AX,X
MOV AX,X
CMP
AX,Y
CMP
AX,Y
JGE
M; x>=yM
JAE M
MOV AX,Y
MOV AX,Y
M: MOV Z,AX
MOV Z,AX
Во вторую группу команд условного перехода входят те, которые ставятся после команд,
отличных от команды сравнения, и которые реагируют на то или иное значение какого-нибудь
определенного флага. В мнемокодах этих команд после буквы J указывается первая буква
проверяемого флага. Переход осуществляется при значении флага =1.Если между J и <имя
флага> вставить N (not), то переход будет осуществляться при нулевом значении флага (см.
табл.2).
Пример. Пусть А,В и С- беззнаковые байтовые переменные. Требуется вычислить
С=АА+В, но если ответ превосходит размер байта, тогда надо передать управление на метку
error.
MOV AL,A
MUL AL
JC ERROR
;AA>255ERROR
ADD AL,B
Таблица 2.
Мнемокод Условие перехода
Мнемокод Условие перехода
ZF
JS
JC
JO
JP
ZF=1
JNZ
JNS
JNC
JNO
JNP
SF=1
CF=1
OF=1
PF=1
17
ZF=0
SF=0
CF=0
OF=0
PF=0
JC ERROR
; перенос (CF=1)ERROR
MOV C,AL
В третью группу входит только одна команда условного перехода, проверяющая
значение регистра CX (а не флаги):
JCXZ <метка>
Действие этой команды можно записать так:
If CX=0 then goto <метка>
Как эта команда используется для организации циклов.
Индивидуальные задания выбираются по вариантам вместе с преподавателем или по
списку группы (см. приложение 1).
18
ЗАДАНИЕ №1. Теоретический вопрос
При выполнении данного задания необходимо наиболее полно раскрыть поставленную
тему с приведением всех необходимых ссылок на использованные источники и литературу.
№
Индивидуальная тема
варианта
1.
Регулярные грамматики и языки программирования.
2.
Контекстно-свободные грамматики и языки программирования.
3.
Описание языка программирования.
4.
Формальные грамматики и распознающие механизмы.
5.
Конечные автоматы и преобразователи.
6.
Автоматы и преобразователи с магазинной памятью.
7.
Методы синтаксического анализа.
8.
Грамматики предшествования.
9.
Промежуточные формы представления программ.
10
Формальные методы описания перевода.
11
Разработка и реализация синтаксически управляемого перевода.
12
Основные концепции языков программирования.
ЗАДАНИЕ №2. Простые вычисления на языке Ассемблер
Из таблицы 3 взять задание и написать программу, вычисляющую значение переменной R
при указанных значениях.
Таблица 3.
1 R=x+y,где x=a+b-c, y=b·c-a , где b=8; a=30 ; c=7
2 R=x-y·z, где x=m-n, y=m+n, z=m·n, где m=16; n=180
3 R=x+y-z, где x=m·n, y=m+n, z=m-n, где m=190; n=4
4 R=x-x·y, где x=m+n, y=m-n, z=x+y, где m=-15; n=51
5 R=x+y-z, где x=m-n, y=m+n, z=3·x+y, где m=-15; n=200
6 R=m·x+y+n·z, где х=m+m·r, y=n+m, где m=-1; n=36
7 R=x·z-y, где x=m-2, y=m+2·n, где m=50; n=300
8 R=m·x+y, где x=m+n, y=m-2·n, где m=,-15; n=,51
9 R=m·x+y·z-n, x=m+2·n, y=2·m-n, z=x+y, где m=6; n=18
10 R=x-y-z, где x=m+n, y=m+n , z=m-n, где m=3; n=256
11 R=(x+y)·2, где x=-19; y=260
19
ЗАДАНИЕ №3. Условные вычисления на языке Ассемблер
Из таблицы 4 взять задание и написать программу, используя операторы условного и
безусловного переходов.
Таблица 4.
1.
a  b  a  b, если a  b  0
y
a  b  2  b, иначе
a  b  352  6  a, если a  b  0
2. y  
a  b  3  a, иначе
3.
a  b  a  b, если 0  a  30
y
a  b, иначе
4.
a  2  b  318, если 0  a  b  10
y
a  x  b, и, и
5.
2  a  b  221, если 0  a  b  117
y
a  b-a  b , иначе
a  b  a  b, если a  b  0
6. y  
a  b  2  a, иначе
7.
a  2  b  1, если b  3  a  0
y
b  1, иначе
a  b, если 0  a  b  3
8. y  
a  b  18, иначе
9.
a  b  c  c, если b  c  a  20
y
a  b  c, иначе
a  b, если 3  b  a   21
a  b, иначе
10. y  
a  b, если a  b   0
11. y  
a  b  1, иначе
12. y  35  a  17  b, если a  30
a  b, иначе
20
ТРЕБОВАНИЯ К ОФОРМЛЕНИЮ РЕЗУЛЬТАТОВ
ВЫПОЛНЕНИЯ КОНТРОЛЬНОЙ РАБОТЫ
Контрольная работа оформляется в следующем виде:
1. титульный лист;
2. содержание;
3. затем приводятся:
для теоретических заданий – вариант ответа;
для практических заданий – распечатки результатов выполненной работы в
эмуляторе emu8086 и описание проделанных действий.
4. список использованной литературы
21
СПИСОК РЕКОМЕНДУЕМЫХ ИСТОЧНИКОВ
1. А.П. Соколов Системы программирования: Теория, методы, алгоритмы. Учебное пособие.
М.: Финансы и статистика, 2004.
2. Э.А. Опалева, В.П. Самойленко Языки программирования и методы транскляции. СанктПетербург: БХВ-Петербург, 2005.
3. Р.Хантер Проектирование и конструирование компиляторов. М.: Финансы и статистика,
2000.
4. http://www.codenet.ru/ . Электронные материалы по основам компиляции (материал
находится на сервере в папке Common).
5. Иллюстрированный самоучитель по Ассемблеру (находится на сервере в папке Common).
6. Бредли Д. Програмирование на языке ассемблера для персональной ЭВМ фирмы IBM: Пер.
в англ.- М.: Радио и связь, 1988. –448 с.
7. Скэнлон Л. Персональные ЭВМ IBM РС и ХТ. Програмирование на языке ассемблера: Пер.
с англ. – М.: Радио и связь, 1991. –336 с.
8. Абель П. Язык Ассемблера для IBM РС и програмирования: Пер. с англ. – М.: Высшая
школа, 1992. –477 с.
9. Нортон П., Сохуэ Д. Язык ассемблера для IBM РС: Пер. с англ. – М.: Издательство
«Компьютер»; Финансы и статистика, 1992. –352 с.
10. Использование Turbo Assembler при разработке программ. – Киев: «Диалектика», 1994. –
228 с.
11. Лямин Л. В. Макроассемблер MASM. – М.: Радио и связь, 1994. –320 с.
12. Пильщиков В.Н. Програмирование на языке ассемблера IBM РС. – М.: «ДИАЛОГМИФИ», 1996. –288 с.
13. Майко Г.В. Ассемблер для IBM РС: - М.: «Бизнес-Информ», «Сирин» 1997.-212 с.
22
КОНТРОЛЬНЫЕ ВОПРОСЫ
1. Что такое регистр? Какие регистры Вы знаете?
2. Какие размеры данных Вы знаете?
3. Для чего используются флаги?
4. Каким образом хранятся в компьютере положительные и отрицательные числа, символы?
5. Что такое идентификатор? По каким правилам он строится?
6. Как строятся комментарии?
7. Опишите общие правила построения команды в ЯА?
8. Что такое директивы? Для чего они применяются?
9. Какие директивы используются для описания данных и констант?
10. Как записывается операнд-конструкция повторения?
11. Какие команды пересылки Вы знаете?
12. Расскажите о командах сложения и вычитания? В чем отличие команд сложения и
вычитания, учитывающих значение флага CF, где они применяются?
13. Различают ли команды сложения и вычитания знаковых и беззнаковых чисел?
14. Расскажите о командах умножения и деления? Почему в этих командах один операнд?
15. Каким образом можно изменить размер числа? В каких случаях это может пригодиться?
16. Как организовать безусловный переход в программе?
17. Какой переход называют прямым, а какой – косвенным?
18. Как в ЯА организуется условный переход?
19. Для чего используется команда сравнения?
20. Как строится команда условного перехода?
21. На какие три группы делятся команды условного перехода?
22. Почему используются отдельные команды для сравнения знаковых и беззнаковых чисел?
23
Номер
варианта
1
2
3
4
5
6
7
8
ПРИЛОЖЕНИЕ 1. СПИСОК СТУДЕНТОВ
ФИО студента
Дмитриева Анастасия Ивановна
Ершов Игорь Сергеевич
Киреев Алексей Игоревич
Кузьмина Алёна Валентиновна
Осипов Сергей Николаевич
Поросёнков Константин Сергеевич
Шахова Елена Александровна
Гришин Игорь Александрович
24
Download