mov ah,2 - Северо-Кавказский горно

advertisement
Министерство образования и науки РФ
Федеральное государственное бюджетное образовательное учреждение
высшего профессионального образования
«Северо-Кавказский горно-металлургический институт
(государственный технологический университет)»
*
*
*
Кафедра «Автоматизированная обработка информации»
АССЕМБЛЕР
МЕТОДИЧЕСКИЕ УКАЗАНИЯ

по выполнению лабораторных работ для студентов
направления подготовки 230100.62 –
«Информатика и вычислительная техника»
Составители: А. С. Мирошников, Е. А. Соколова
Допущено
редакционно-издательским советом
Северо-Кавказского горно-металлургического института
(государственного технологического университета)
Протокол заседания РИСа № 1 от 17.01.2014 г.
ВЛАДИКАВКАЗ 2014
–1–
УДК 004.43
ББК 32.98
М64
Рецензент: кандидат технических наук, доцент Будаева А. А.
М64
Ассемблер: Методические указания по выполнению лабораторных
работ для студентов, обучающихся по направлению подготовки 230102.62 –
«Информатика и вычислительная техника» / Сост. А. С. Мирошников,
Е. А. Соколова; Северо-Кавказский горно-металлургический институт
(государственный технологический университет. – Владикавказ: СевероКавказский горно-металлургический институт (государственный технологический университет). Изд-во «Терек», 2014. – 60 с.
Методические указания предназначены для передачи студентам практических навыков программирования на Ассемблере, содержат описание
основных операторов и примеры задач, а также необходимые примеры исходного кода для выполнения лабораторных работ по курсу «Программирование на Ассемблере» для студентов, обучающихся по направлению
подготовки 230102.62 – «Информатика и вычислительная техника».
УДК 004.43
ББК 32.98
Редактор Иванченко Н. К.
Компьютерная верстка Меркушевой О. А.
© Составление. ФГБОУ ВПО СКГМИ (ГТУ), 2014
© Мирошников А. С., Соколова Е. А. Составление, 2014
Подписано в печать 10.04.14. Формат бумаги 60841/16. Бумага офсетная. Гарнитура «Таймс».
Печать на ризографе. Усл. п. л. 3,49. Тираж 50 экз. Заказ №
.
Северо-Кавказский горно-металлургический институт (государственный технологический
университет). Изд-во «Терек».
Отпечатано в отделе оперативной полиграфии СКГМИ (ГТУ).
362021, Владикавказ, ул. Николаева, 44.
–2–
СОДЕРЖАНИЕ
Лабораторная работа 1 …………………………………………
3
Лабораторная работа 2 …………………………………………
18
Лабораторная работа 3 …………………………………………
35
Лабораторная работа 4 …………………………………………
43
Лабораторная работа 5 …………………………………………
47
Лабораторная работа 6 …………………………………………
49
Приложение I. Форма титульного листа ……………………...
54
Приложение II. Шестнадцатирично-десятичные преобразования
55
Приложение III. ASCII символы ……………………………...
58
Список литература ……………………………………………..
60
–3–
Лабораторная работа 1
Цель: Ознакомить студентов с особенностями персонального
компьютера, процессором, регистрами, памятью, двоичной и
шестнадцатеричной системами счисления. Научить записывать
десятичные числа в двоичной и шестнадцатеричной формах, а
также переводить числа из одной системы счисления в другую.
Как и все остальные, программы на языке Ассемблер состоят
из команд. Но каждая команда в Ассемблере имеет свой машинный код, выполняемый процессором. Поэтому говорят, что язык
Ассемблер является языком низкого уровня.
Большинство команд работает с данными. Сами команды,
т. е. их машинные коды, и данные располагаются в памяти компьютера. Из памяти процессор выбирает команды одну за другой, и исполняет их. При выборке и выполнении команды процессором используется не только память, но и порты вводавывода, шины адреса (ША) и данных (ШД), регистры и остальные блоки компьютера (Рис.1.1). Поэтому написание ассемблерных программ требует знаний организации всей системы
компьютера.
Процессор
ША
ШД
Регистры
Порт
ввода-вывода
Память
Рис.1.1. Элементы компьютера.
–4–
Память компьютера
Память компьютера можно представить в виде последовательности ячеек, каждая из которых имеет свой номер 0, 1, 2, …,
называемый адресом. Машинный код команды занимает одну или
несколько ячеек памяти. Для его выполнения процессор с помощью регистров устанавливает на ША адрес первой ячейки, с которой начинается машинный код, а затем через ШД считывает из
памяти команду и начинает ее выполнять. Если команда подразумевает работу с некоторыми данными (их чтение или запись), то
сначала на ША устанавливается адрес памяти, а затем через ШД
данные читаются из памяти или записываются в нее. После выполнения одной команды процессор начинает выбирать из памяти
следующую и т. д.
Шину можно представить в виде набора проводников, в каждом из которых может протекать напряжение заданного уровня
(1), либо отсутствовать (0). Система счисления, построенная на
цифрах 0 и 1, называется двоичной. Например, с помощью двух
проводников или двух разрядов можно задать четыре числа:
00 = 0, 01 = 1, 10 = 2, 11 = 3. Каждый разряд в числе принято
называть битом. Группа из восьми бит образует байт. Байт является основной единицей хранения чисел в памяти. Графически
байт изображается следующим образом:
d7
d0
Рис 1.2. Графическое изображение байта.
Биты в байте нумеруются от 0 до 7, при этом бит d0 является
младшим, а d7 – старшим.
Группа из двух байт (16 бит) образует слово, четыре байта
(32 бита) – двойное слово, а 16 байт – параграф.
–5–
Системы счисления
Двоичная система счисления является наглядной, так как отражает состояние каждого бита в числе. Но у нее есть существенный недостаток – числа в двоичной форме очень громоздки. С
другой стороны, привычная для нас десятичная система слишком
сложна для перевода чисел в двоичную и обратно. Поэтому
наибольшее распространение в практике получила шестнадцатиразрядная система счисления. В программах на ассемблере разрешается использовать также и восьмеричную систему счисления,
но на практике она применяется крайне редко.
В таблице 1.1 приведены представления чисел от 0 до 16 в
двоичной, восьмеричной, десятичной и шестнадцатеричной системах. Для указания системы счисления после числа записывается буква: b – для двоичной, q или o – для восьмеричной, d – для
десятичной и h – для шестнадцатеричной. Числа, указанные без
буквы, относят к десятичной системе счисления.
Таблица 1.1
Формы представления чисел
Двоичное
B
1
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
Восьмеричное
q или o
2
0
1
2
3
4
5
6
7
10
11
12
Десятичное
[d]
3
0
1
2
3
4
5
6
7
8
9
10
–6–
Шестнадцатеричное
h
4
0
1
2
3
4
5
6
7
8
9
A
Окончание табл. 1.1
1
1011
1100
1101
1110
1111
10000
2
13
14
15
16
17
20
3
11
12
13
14
15
16
4
B
C
D
E
F
10
Используя таблицу 1.1, можно легко переводить числа из
шестнадцатеричной системы счисления в двоичную и обратно.
Например, число 5Eh запишется как 01011110b (5 = 0101 + E =
1110), а число 101101010001b как B51h (1011 = B + 0101 = 5 +
0001 = 1). В приложении 0 рассматривается перевод чисел из десятичной системы в шестнадцатеричную и обратно.
Адресация памяти
Процессоры 8086 и 80286 являются 16-разрядными: ШД и все
регистры имеют по 16 разрядов. Эти процессоры могут работать с
числами от 0 до 65535 (216-1 = 65535). Процессоры i386 и i486 являются 32-разрядными, а Pentium – 64-разрядным.
Однако ША у процессора 8086 не 16-разрядная, а 20-разрядная, что позволяет адресовать 1 Мб памяти (220 = 1048576 = 1 Мб).
При этом для установки на ША физического 20-разрядного адреса
используют два 16-разрядных числа. Такой адрес принято записывать в виде SSSS:OOOO, где SSSS – сегментная часть адреса,
сегмент (segment, 16 бит), а OOOO – смещение (offset, 16 бит).
Для вычисления физического адреса используют формулу:
<Физический_адрес> = SSSS · 16 + OOOO.
Например, физический адрес 00001Dh можно записать в виде:
0001:000D или 0000:001D.
Память лучше всего рассматривать следующим образом:
–7–
CS, SS
DS
Рис. 1.3. Сегментные регистры
и сегменты памяти.
ES
Сегменты
памяти
0 1 2 3 4 5 6 7 8 9 ABCDE F
– 1 параграф = 16 байт (0..F)
0
1
2
3
Байт по адресу: 0000:002C
0001:000C
0002:001C
Рис. 1.4. Адресация.
Сегментная часть SSSS в адресе SSSS:OOOO по существу является номером параграфа. Для ее хранения у процессора есть
специальные сегментные регистры. Оставляя постоянной сегментную часть, а меняя только смещение, можно адресовать
65536 байт или 64 Kб. Эту область называют сегментом памяти. В
процессоре 8086 имеется четыре сегментных регистра CS, DS, SS
и ES. Следовательно, одновременно можно использовать четыре
различных сегмента памяти. Хотя эти сегменты иногда могут пересекаться или вовсе совпадать друг с другом, т. е. начинаться с
одного и того же адреса (рис. 1.3, 1.4).
–8–
Процессор 80286 имеет 24-разрядную шину адреса, что
позволяет адресовать 224 = 16 Мб. Однако описанный выше
способ сегментной адресации памяти не позволяет выйти за
пределы 1 Мб. Для преодоления этого ограничения в процессоре
80286, так же как и в i386, i486 и Pentium используются два режима работы процессора: реальный и защищенный. В реальном режиме процессор 80286 функционирует подобно процессору 8086,
но с повышенным быстродействием, расширенным набором команд и обращается лишь к 1 Мб памяти. Это также относится к
процессорам i386, i486 и Pentium.
Защищенный режим является более сложным и выходит за
рамки данного курса.
Регистры процессора
Процессор содержит двенадцать 16-разрядных регистров,
которые принято объединять в три группы: регистры общего
назначения, регистры-указатели и сегментные регистры. Кроме
того, в состав процессора входит счетчик команд и регистр
флагов (рис. 1.4).
Регистры общего назначения
В группу регистров общего назначения включаются регистры
АХ, BX, CX и DX. Особенностью этих регистров является то, что
их можно использовать в любых арифметических, логических и
других машинных операциях. В то же время каждый из этих регистров имеет определенную специализацию: некоторые команды
требуют, чтобы их операнд или операнды обязательно находились
в определенных регистрах. Например, команды деления требуют,
чтобы первый операнд (делимое) находился в регистре AX или в
двух регистрах DX и AX (в зависимости от размера делителя), а
команды управления циклом используют регистр CX в качестве
счетчика цикла.
–9–
Регистры общего назначения
Регистры указатели
AX
AH
AL
Аккумулятор
SI
Индекс источника
BX
BH
BL
Базовый регистр
DI
Индекс приемника
CX
CH
CL
Счетчик
BP
Указатель базы
DX
DH
DL
Регистр данных
SP
Указатель стека
Сегментные регистры
Прочие регистры
CS
Регистр сегмента кода
DS
Регистр сегмента данных
SS
Регистр сегмента стека
ES
Регистр дополнительного сегмента данных
IP
Flags
Указатель команд
Регистр флагов
Рис. 1.5. Регистры процессора.
Регистры AX, BX, CX и DX устроены так, что возможен независимый доступ к их старшей и младшей половинам. Можно сказать, что каждый из этих регистров состоит из двух байтовых регистров. Обозначают эти половины буквами H (high – старший) и
L (low – младший) и первой буквой из названия регистра: AH и
AL – AX, BH и BL – BX и т. д.
Если, например, регистр CX содержит число 2E5Ch, то CH будет содержать 2Eh, а CL – 5Ch. Или наоборот, если записать в регистр DH число 60h, а в DL 2Аh, то в регистре DX будет содержаться число 6052h.
– 10 –
CX = 2E5Ch
d15
d8 d7
d0
0 0 1 0 1 1 1 0 0 1 0 1 1 1 0 0
d7
d0
d7
0 0 1 0 1 1 1 0
CH = 2Eh
DH = 60h
d7
CL = 5Ch
DL = 52h
d0
d7
0 1 1 0 0 0 0 0
d15
d0
0 1 0 1 1 1 0 0
d0
0 0 1 0 1 0 1 0
d8 d7
d0
0 1 1 0 0 0 0 0 0 0 1 0 1 0 1 0
DX = 6052h
Рис. 1.6. Пример записи чисел в регистр.
В дальнейшем будут использоваться регистровые пары,
например DX:AX, при этом первый регистр (DX) является старшим, а второй (AX) младшим. В регистровых парах содержимое
обоих регистров рассматривается как одно число подобно AH и
AL в AX или BH и BL в BX.
Сегментные регистры
Сегментные регистры CS, DS, SS и ES, как уже известно, используются процессором для хранения сегментной части адреса.
Эти регистры не могут быть использованы ни в каких арифметических, логических и им подобных операциях. Можно только записывать или читать из них, да и то здесь есть определенные
ограничения.
Каждый из сегментных регистров имеет свою специализацию.
При написании программ команды стараются хранить в одном
месте памяти, а данные – в другом. Регистр CS указывает на начало
– 11 –
блока памяти, в котором располагаются команды. Этот блок
называется сегментом кода. Если все команды в программе занимают более 64 Кб, то в памяти располагаются два и более сегментов кода, а для перехода от одного сегмента к другому меняют
содержимое регистра CS. В регистр DS обычно записывается сегментная часть адреса начала блока данных – сегмента данных, а
регистр SS всегда используется для адресации стека. Конечно,
можно хранить данные в сегменте кода или команды в сегменте
стека, но это только усложняет и запутывает написание
программ.
В редких случаях данные хранят совместно с командами. Хотя существуют программы, где все три сегмента – кода, данных и стека –
обязательно должны совпадать. Такие программы называются COMпрограммами. В EXE-программах данные сегменты, как правило,
разделены между собой.
Регистр ES используется как дополнительный сегментный регистр при доступе к данным, которые расположены вне основного
сегмента данных.
Регистры-указатели
CS
Сегмент кода
Сегмент данных
DS
SS
Сегмент стека
Рис. 1.7. Основные программные
сегменты.
В группу регистров указателей входят SI, DI, BP и SP. Регистры SI и DI еще называют
индексными. Они, как и регистры общего назначения, могут
использоваться произвольным
образом. Однако их основное
назначение – хранить индексы
(смещения) относительно начала некоторого сегмента памяти,
адрес которого хранится в одном из сегментных регистров. В
– 12 –
командах работы со строками
регистр SI используется совместно с сегментным регистром DS для определения адреса источника
данных. В этих же командах регистр DI используется совместно с
регистром ES для определения адреса назначения, т. е. куда помещаются данные. Данная специализация регистров SI и DI будет
рассмотрена подробнее при описании команд работы со строками.
Регистровые указатели SP и BP обеспечивают доступ к данным в сегменте стека. Реже они используются в операциях сложения или вычитания. Эти регистры связаны с сегментным регистром SS для адресации стека. В регистровой паре SS:SP хранится
адрес элемента, записанного в стек последним. Регистр BP в основном используется в процедурах для временной фиксации адресов в сегменте стека. Использование регистров SP и BP более подробно будет рассмотрено при описании стека и процедур.
Указатель команд
Регистр IP называется указателем команд. Он связан с сегментным регистром CS. Регистровая пара CS:IP содержит адрес
команды, которая должна быть выполнена следующей. IP хранит
смещение этой команды относительно сегмента кода, на начало
которого указывает регистр CS. Процессор после завершения выполнения команды выбирает из памяти следующую, адрес которой хранится в CS:IP. Выбрав команду и проанализировав ее,
процессор меняет содержимое регистров CS:IP на адрес следующей команды, а только потом начинает выполнение выбранной.
Это означает, что при выполнении команды в CS:IP уже хранится
адрес следующей команды.
Флаговый регистр
У процессора имеется регистр флагов. Флаг – это бит, принимающий значение 1 («флаг установлен»), если выполнено некоторое условие, и значение 0 («флаг сброшен») в противном случае.
– 13 –
Данный регистр содержит шесть флагов состояния и три флага
управления состоянием процессора.
Флаги состояния автоматически меняются при выполнении
команд и фиксируют те или иные свойства их результата, например, равен ли он нулю. Проверка этих флагов позволяет проанализировать результаты команд.
Флаги управления состоянием должны меняться программой.
Состояние этих флагов оказывает влияние на дальнейшее работу
процессора.
Флаги состояния:
CF (carry flag) – флаг переноса. Он наиболее полезен в арифметических операциях над числами без знака. Например, если при
сложении беззнаковых чисел получилась слишком большая сумма
– с единицей переноса, которой нет места в ячейке, тогда CF принимает значение 1, а если сумма «укладывается» в размер ячейки,
то значение CF будет 0 (рис. 1.7а).
OF (overflow flag) – флаг переполнения. Полезен в арифметических операциях над числами со знаком. Например, если при
сложении или вычитании знаковых чисел получился результат, по
модулю превосходящий допустимую величину, тогда OF принимает значение 1, в противном случае 0 (рис. 1.7б).
ZF (zero flag) – флаг нуля. Устанавливается в 1, если результат
операции оказался нулевым.
SF (sign flag) – флаг знака. Устанавливается в 1, если в операции над знаковыми числами получился отрицательный результат.
PF (parity flag) – флаг четности. Устанавливается в 1, если в
восьми младших битах результата содержится четное число двоичных единиц.
AF (auxiliary carry flag) – флаг дополнительного переноса.
Фиксирует заем или перенос из бита d3. Применяется в операциях
над двоично-десятичными числами (рис. 1.7в).
Флаги управления состоянием:
DF (direction flag) – флаг направления. Устанавливает направление строк в строковых командах: при DF = 0 строки просматри– 14 –
ваются «вперед» (от начала к концу), а при DF = 1 – в обратном
направлении.
IF (interrupt flag) – флаг прерываний. При IF = 0 процессор перестает реагировать на поступающие к нему прерывания, а при
IF = 1 блокировка прерываний снимается.
TF (trap flag) – флаг трассировки. При TF = 1 после выполнения каждой команды процессор делает прерывание, чем можно
воспользоваться при отладке программы – для ее трассировки.
В процессорах 8086 и 80286 регистр флагов имеет следующую
структуру (рис. 1.7г).
а
d6
d0
1
б
d5
d0
Знаковый бит
в
d7
d0
г
– 15 –
d15
d8 d7
OF DF IF TF SF ZF
AF
PF
d0
CF
Рис. 1.8. Структура регистра флагов.
Так как процессоры i386 и i486 являются 32-разрядными, а
Pentium 64-разрядным, то структура регистра флагов в этих процессорах немного другая. Чтение и запись регистра флагов производится через стек командами pushf и popf соответственно. Также
имеются команды условного перехода для анализа отдельных
флагов и команды изменения флагов управления. При их использовании не обязательно знать расположение флагов в регистре.
Все эти команды будут детально рассмотрены позднее.
Варианты индивидуальных заданий
Перевести заданные десятичные числа в двоичную и затем в
шестнадцатеричную системы счисления:
№
1
2
3
4
Число
125
98
357
148
№
5
6
7
8
Число
451
745
325
136
№
9
10
11
12
Число
348
256
105
204
№
13
14
15
16
Число
907
154
621
452
№
17
18
19
20
Число
304
300
402
750
Контрольные вопросы
1. Объясните понятия «бит», «байт», «слово» и «параграф».
2. Какие системы счисления применяются в программах на
Ассемблере? Объясните особенности каждой из них.
3. Для чего процессор использует шину адреса и данных?
4. Что такое сегмент памяти, каков его максимальный размер и с каких адресов он может начинаться?
5. В каком виде принято записывать адреса памяти? Как вычислить физический адрес памяти?
– 16 –
6. Что такое разрядность шины?
7. Что такое разрядность процессора?
8. Какие основные группы регистров Вы знаете?
9. Какие регистры относят к регистрам общего назначения?
Каково их назначение?
10. Какие регистры относят к сегментным регистрам? Каково их назначение?
11. Какие регистры относят к регистрам-указателям? Каково их назначение?
12. Что такое регистровая пара?
13. Поясните понятия «старший» и «младший» байты в слове
памяти.
14. Какие основные типы программных сегментов Вы знаете?
Какие регистры используются для их адресации?
15. Для чего служит регистр IP?
16. Для чего служит фланговый регистр?
17. Какие флаги относятся к флагам состояния процессора?
Каково их назначение?
18. Какие флаги относятся к флагам управления состоянием
процессора? Каково их назначение?
19. Объясните понятие «флаг».
20. Что такое специализация регистров? Приведите пример.
– 17 –
Лабораторная работа 2
ОСНОВЫ ПРОГРАММ НА ЯЗЫКЕ АССЕМБЛЕРА
Цель: ознакомить студентов с основными элементами программ на Ассемблере: идентификаторы, константы, выражения
и т. п. Научить правильному применению основных элементов в
тексте программы и составлению структуры текста программы.
Идентификаторы
Идентификаторы используются для обозначения различных
объектов программы – переменных, меток, названий операций и т. п.
Идентификатор – это последовательность из латинских букв (больших и малых), цифр и следующих знаков: ? . @ _ $. Причем на эту
последовательность накладываются следующие ограничения:
– длина идентификатора может быть любой, но значащими в
Turbo Assembler являются только первые 255 символов;
– идентификатор не может начинаться с цифры (7А – ошибка);
– точка может быть только первым символом идентификатора
(.А – можно, А. – нельзя);
– в идентификаторах регистр символов не учитывается (АХ,
Ах, аХ и ах – один идентификатор).
Идентификаторы делятся на служебные слова и имена. Служебные слова имеют заранее определенный смысл, они используются для обозначения таких объектов, как регистры (AX, SI,
…), названия команд (ADD, NEG, …) и т. п. Все остальные идентификаторы называются именами. Ими обозначают переменные,
метки и другие объекты программы.
– 18 –
Константы
Фиксированные значения в программах принято называть константами. Простейшими константами могут быть числа или символы,
но любая константа интерпретируется как фиксированное числовое
значение. Каждый символ имеет свой числовой код, поэтому даже
строку символов можно записать в виде последовательности чисел:
db ‘СТРОКА’
db 91h, 92h, 90h, 8Eh, 8Ah, 80h.
Числовые константы
Числовые константы всегда начинаются с цифры (0 – 9) и содержат произвольное число алфавитно-цифровых символов. Существует одна особенность, касающаяся шестнадцатеричных констант. Если подобная константа начинается с буквы (C5h), то перед ней необходимо поставить 0:
0C5h – числовая константа С5h;
C5h – идентификатор С5h.
Фактическое значение константы зависит от основания, т. е.
системы счисления, которая выбрана для интерпретации константы. Системы счисления рассматривались в лабораторной работе
№ 1. За каждой системой счисления закреплен идентифицирующий символ, по которому можно определить основание числа.
Символ b закреплен за двоичной системой, o или q – за восьмеричной, d – за десятичной и h – за шестнадцатеричной. Транслятор определяет основание числовой константы, проверяя сначала
ее последний символ. Регистр букв шестнадцатеричных констант
и идентифицирующих основание символов по умолчанию значения не имеет.
Для числовых констант, не имеющих заключительного символа, используется текущее, назначенное по умолчанию, основание.
Обычно им является основание 10.
– 19 –
Строковые константы
Для представления символьных констант, равно как и для записи любых символов, в программе используется американский
стандартный код для обмена информацией ASCII (American
Standard Code for Information Interchange). Этот код обеспечивает
представление 256 символов, каждый из которых имеет однобайтовый код. ASCII-коды рассматриваются в Приложении III.
Один или несколько ASCII символов, заключенных в апострофы (‘$’) или кавычки (“ABC+”), будут рассматриваться как
символьная константа.
Если в качестве символа или внутри строки надо указать апостроф или кавычку, то делается это так: если символ или строка
заключена в апострофы, то апостроф надо удвоить, а вот кавычку
удваивать не надо, и наоборот, если внешними являются кавычки,
то кавычку надо удвоить, а апостроф нет:
don’t = ‘don’’t’ = “don’t”
don”t = “don””t” = ‘don”t’
Выражения и операторы
Выражения используются для описания операндов директив и
команд. Они делятся на два класса: константные и адресные. Если
значением выражения является целое число (2 * 6, 5 mod 2, …), то
оно называется константным выражением, а если значением является адрес, то это адресное выражение. К простым адресным выражениям можно отнести имена переменных или меток, которые
обозначают адреса переменных или команд соответственно.
Значение выражения определяется во время трансляции программы: встретив в программе выражение, Turbo Assembler вычисляет его и полученное выражение записывает в машинный код.
– 20 –
В выражениях можно использовать операторы. Действия операторов будут рассмотрены в ходе курса, а пока приведем старшинство всех операторов языка ассемблер в порядке убывания:
1. <>, (), [], LENGTH, MASK, SIZE, WIDTH, .
2. HIGH, LOW
3. +, - (одноместные)
4. :
5. OFFSET, PTR, SEG, THIS, TYPE
6. *, /, MOD, SHL, SHR
7. +, - (двухместные)
8. EQ, GE, GT, LE, LT, NE
9. NOT
10. AND
11. OR, XOR
12. LARGE, SHORT, SMALL, .TYPE
Операторы одного старшинства вычисляются слева направо.
Например, A + B - C – это (A + B) - C.
Предложения
Программа на ассемблере – это последовательность предложений, каждое из которых записывается в отдельной строке:
<Предложение>
<Предложение>
…
<Предложение>
Регистр написания символов в предложениях по умолчанию
роли не играет. На практике используются предложения длиной
до 80 символов, полностью помещающихся на экране компьютера. Предложения можно переносить с одной строки на другую с
помощью символа «\». Но для его использования выше в тексте
– 21 –
программы должна быть указана директива VERSION с параметром M510 или M520:
version m510
…
db ‘Пример строки \
с продолжением’
Комментарии
Комментарии предназначены для пояснения смысла программы. Транслятор игнорирует их при переводе текста программы в
машинные коды
Комментарием считается любая строка, начинающаяся со знака «;». В комментариях можно использовать любые символы, в
том числе и русские буквы. Например:
;это коментарий
L10: ;это метка
mov ax, 0FFh ;команда AX = 255
В языке Ассемблера допустим и многострочный комментарий.
Он определяется директивой COMMENT:
СOMMENT <маркер> <текст комментария>
В качестве маркера берется первый за словом COMMENT
символ, отличный от пробела. Этот символ начинает комментарий. Концом такого комментария считается конец первой из последующих строк программы, в которой снова встретится этот же
маркер. Например:
mov ax, 0FFh
comment * все
это является
комментарием * и это тоже до конца строки
mov bx, 2Ch
– 22 –
Такой вид комментария обычно используется, когда надо
(например, при отладке) временно исключить из программы некоторый ее фрагмент.
Использование комментариев считается хорошей практикой
программирования на любом языке.
Команды
Предложения-команды – это символьная форма записи машинных команд. Общий синтаксис этого типа предложений таков:
[<метка>:]
<мнемокод>
[<операнд1>][,
<операнд2>]
[;<комментарий>]
Примеры:
L: add dx, 02h ;увеличение dx на 2
neg cl
cwb
Синтаксически, метка – это имя, после которого обязательно ставится двоеточие. Метка нужна для ссылок на команду из
других мест программы, например, для перехода на эту команду. В отличие от машинного языка, где надо высчитывать адреса ячеек, в которые попадают команды, чтобы затем указывать
эти адреса в командах перехода, в языке ассемблера достаточно
лишь пометить команду и затем ссылать на нее по метке.
Разрешается в одной строке указывать только метку и
больше ничего. Такая метка относится к следующей за меткой
команде программы. Эта возможность полезна, по крайней мере, в двух случаях: когда команду надо пометить двумя или более метками и когда метка очень длинная и потому остальная
часть команды слишком сильно сдвигается вправо, что плохо
смотрится.
– 23 –
Пример:
INITIALIZATION:
L: add bx, ax
Команды, работающие с одним операндом, могут работать с
регистрами, адресами памяти или с сегментными регистрами.
В отличие от машинного языка, в ассемблерных командах
не указываются адреса ячеек и, чтобы сослаться на какую-то
переменную (ячейку), ей дают имя, а затем в командах указывают это имя.
Директивы
В программах на языке Ассемблера часто встречаются предложения, которые управляют процессом транслирования – перевода команд в машинные коды. Они называются директивами.
Другими словами, директивы являются командами не для процессора, а для транслятора.
Директивы позволяют формировать структуру программы,
объявлять переменные, разрешать или запрещать использование
определенных команд процессора, формировать файл листинга,
создавать блоки условного ассемблирования и многое другое.
Формат директив следующий:
[<имя>] <название_директивы> [<операнды>] [;<коментарий>]
Пример:
SSeg segment stack ‘stack’
db 10
jumps
– 24 –
Имя, указываемое в начале директивы – это, как правило, имя
константы, переменной, процедуры или сегмента. Названия директив являются служебными словами и будут рассматриваться
по мере знакомства с ними.
Для каждой директивы характерен свой набор операндов, которые, если они есть, отделяются друг от друга запятыми. Операнды будут рассматриваться вместе с директивами.
Программные сегменты
Каким же образом написать программу, чтобы команды располагались вместе в одном сегменте памяти, данные в другом, а
стек в третьем? Для этого все предложения, которые необходимо
разместить в одном сегменте памяти, в тексте программы объединяются в так называемый программный сегмент. Это аналог сегмента памяти, но в терминах языка Ассемблера. Программный
сегмент имеет следующую структуру:
<имя_сегмента> segment <параметры>
<предложение>
…
<предложение>
<имя_сегмента> ends
Программному сегменту дается имя, которое должно быть повторено дважды: в директиве SEGMENT, открывающей сегмент,
и в директиве ENDS, закрывающей его. Предложений в сегменте
может быть сколько угодно, но их совокупный размер не должен
превышать 64 Кб – максимального размера сегмента памяти.
Параметры директивы SEGMENT в основном используются,
когда программа большая и хранится в нескольких файлах, и параметры указывают, как объединять эти файлы. Если же программа не большая, умещается в одном файле, тогда параметры
не нужны. Они будут рассмотрены позже.
Шаблон программы
– 25 –
Известно, что программы, выполняемые под управлением MS
DOS, могут принадлежать к одному из двух типов, которым соответствуют расширения имен выполнимых файлов .com и .exe. Основное различие этих программ заключается в том, что COM программы состоят из единственного сегмента, в котором размещаются команды, данные и стек, а EXE программы состоят из отдельных сегментов кода, данных и стека. В результате, размер
COM программы не может превышать 64 Кб, а размер EXE программы практически не ограничен.
В листинге 2.1 приведен шаблон EXE программы. COM программы будут рассмотрены отдельно.
1
.286
2
3 ;Сегмент кода
4
5 Cseg segment
6
assume cs:Cseg, ds:Dseg, ss:Sseg
7
;код инициализации
8 begin: mov ax, Dseg
9
mov ds, ax
10
;тело программы
11
;...
12
;выход из программы
13
mov ax, 4C00h
14
int 21h
15 Cseg ends
16
17 ;Сегмент данных
18
19 DSeg segment
20
;описание данных
21
;...
22 DSeg ends
23
– 26 –
24 ;Сегмент стека
25
26 SSeg segment stack 'stack'
27
dw 100 dup(?)
28 SSeg ends
29
30
end begin
Листинг 2.1 Шаблон программы.
В начале курса при написании программ рекомендуется использовать этот шаблон для избежания ошибок, связанных с особенностями EXE программ. Рассмотрим этот шаблон более подробно.
В начале программы, при необходимости, указываются директивы для всей программы в целом. В данном примере строка 1 содержит директиву .286. Следовательно, ниже в тексте программы
можно использовать команды процессора 80286, это пригодится в
дальнейшем. По умолчанию, без указания соответствующей директивы, используются только команды процессора 8086. В данном месте программы указываются такие директивы, как .model,
jumps, locals, .386, .486, .alpha, .seq и др.
Далее идет описание программных сегментов кода, данных
и стека.
Сегмент кода Cseg (строки 5 – 15) начинается с директивы
ASSUME. Данной директивой транслятору сообщается, чтобы в
ниже записанных командах, где префикс сегмента не указан, он
все имена из сегмента Cseg транслировал с префиксом CS:, имена
из сегмента Dseg транслировал с префиксом DS:, а регистр SS использовал по умолчанию для сегмента SSeg.
Формат директивы ASSUME следующий:
assume <сегментный_регистр>:<имя_сегмента>
[, <сегментный_регистр>:<имя сегмента>]
– 27 –
Вместо имени сегмента в директиве можно использовать служебное слово NOTHING для указания явного указания, что данный сегментный регистр не связан ни с одним программным сегментом. Например,
assume cs:Cseg, es:nothing
Директиву ASSUME можно использовать в программе несколько раз, изменяя связи сегментных регистров с программными сегментами. Разорвать одновременно все связи можно строкой
assume nothing
Следует отметить, что применение директивы ASSUME требует определенных навыков в написании программ и на начальном этапе лучше использовать приведенный в листинге 2.1 шаблон программы. Обычно директива ASSUME указывается один
раз в самом начале сегмента кода.
Директива ASSUME не загружает в сегментные регистры
начальные адреса сегментов, а лишь предполагает, что в программе будет сделана такая загрузка.
Каковы же начальные значения сегментных регистров?
Операционная система MS DOS, загрузив программу в память
компьютера, устанавливает начальные значения сегментных регистров следующим образом (рис 2.1.): регистры DS и ES указывают на специальную область памяти, называемую префиксом программного сегмента – PSP (Program Segment Prefics) и используемую операционной системой для управления программой.
256 б.
PSP
DS
ES
CSeg
SSeg
DSeg
Сегмент кода Сегмент данных
CS
Сегмент стека
SS
– 28 –
Рис. 2.1. Программа в памяти компьютера.
После PSP в памяти поочередно размещаются программные
сегменты кода – адресуется регистром CS, данных и стека – адресуется регистром SS. По умолчанию, хотя в начале программы
можно указать директиву .seq, программные сегменты располагаются в памяти в том порядке, в котором они записаны в программе. Если указать директиву .alpha, то сегменты в памяти будут
расположены в алфавитном порядке.
.286
.alpha
;Сегмент кода
Cseg segment
assume cs:Cseg, ds:Dseg, ss:Sseg
...
Какая команда в программе будет выполнена первой? Для ее
указания используется понятие «точка входа». В приведенном
выше шаблоне точкой входа служит метка begin. Она указывается
в двух местах: первый раз перед командой (строка 8), которую
нужно выполнить первой (данная команда не обязательно должна
быть первой в программе, она может находиться, где угодно) и
второй раз в заключительной директиве END (строка 30), завершающей программу. Любой текст после директивы END игнорируется транслятором.
Смещение точки входа (метка begin:) относительно сегмента
команд (Cseg) заносится операционной системой в регистр IP.
Следовательно, в регистрах CS и IP хранится адрес команды, выполняемой первой. Если в директиве END не указана точка входа,
то первой будет выполнена команда по адресу CS:0000, а регистр
– 29 –
CS будет указывать на сегмент, расположенный сразу после PSP.
Тогда для корректной работы программы необходимо, чтобы в
памяти, а не в программе, первым располагался сегмент кода и
начинался с нужной команды. Очень часто в сегменте команд
сначала записывают процедуры, а после них команды основной
программы. Для избежания вышеперечисленных трудностей следует явно указывать точку входа в программе.
Следует обратить внимание, что при начальной загрузке (рис. 2.1.)
регистр DS указывает не на программный сегмент данных (DSeg), а
на PSP. Командами mov в строках 8 и 9 в регистр DS заносится
сегментный адрес программного сегмента данных DSeg. Почему
нельзя было обойтись одной командой mov ds, Dseg ? Как Вы уже
знаете, в сегментные регистры нельзя заносить напрямую константы, а имя DSeg рассматривается именно как константа, хотя свое
значение она получает только при загрузке готовой программы в
память. После выполнения строки 9 (mov ds, ax) регистр DS будет
указывать на программный сегмент данных и только после этого
обращение к переменным в сегменте DSeg будет корректно.
Для завершения работы программы и возврата в операционную систему в шаблоне программы используется вызов функции
DOS 4Ch прерывания 21h с кодом завершения программы 00h
(строки 13 – 14). Работа с прерываниями и функциями DOS и BIOS входит в курс «Системное программирование», хотя в дальнейшем будут рассмотрены некоторые из них, в основном операции ввода/вывода. А пока отметим, что номер функции 4Ch записывается в регистр AH, код завершения, например 00h, в регистр
AL и командой int 21h исполняется данная функция, которая завершает работу программы.
В строках 19 – 22 описан сегмент данных. В данном случае он
пустой, т. е. не содержит данных. Далее в тексте, при приведении
примеров, будут встречаться строки типа:
;в сегменте данных
M db ?
– 30 –
K
dw 50
Это означает, что сегмент данных должен выглядеть следующим образом:
DSeg segment
;...
M db ?
K dw 50
;...
DSeg ends
Если встретятся строки вида:
;в сегменте кода
mov dx, offset Msg
mov ah, 09h
int 21h
то их необходимо располагать в теле программы между строками
9 и 13.
Сегмент стека является особым типом программных сегментов и работа с ним будет рассмотрена позже. Здесь отметим, что в
директиве SEGMENT указываются два обязательных параметра
для сегмента стека: STACK и ‘STACK’ (строка 26), а в строке 27 в
памяти резервируется 100 слов директивой dw. Иными словами,
размер стека будет равен 100 словам или 200 байтам. Можно изменить размер стека, указав вместо константы 100 любое другое
значение, например 200 или 500, но размер стека должен быть достаточным для правильной работы стековых команд. Поэтому на
первое время выбрано значение – 100 слов. Максимальный же
размер стека равен 64 Кб, как и любого сегмента памяти.
Пример. Вывод на экран сообщения
Программа типа .COM
CSEG segment
org 100h
– 31 –
Start:
mov ah,9
mov dx,offset String
int 21h
mov ah,10h
int 16h
mov ah,9
mov dx,offset String1
int 21h
mov ah,10h
int 16h
int 20h
String db 'Press any key:$'
String1 db 'You press key, that ok!:$'
CSEG ends
end Start
Программа типа .EXE
.model
small
.stack
64
.data
mes db 'privet$'
.code
start:
mov ax,@data
mov ds,ax
mov ah,9h
mov dx, offset mes
int 21h
mov ah,10h
– 32 –
int 16h
mov ax,4c00h
int
Варианты индивидуальных заданий
Необходимо реализовать вывод на экран сообщения (исполняемый файл –exe, com)
Контрольные вопросы
1. Объясните понятие «идентификатор». Каково назначение идентификаторов в программах? Каковы правила записи
идентификаторов в программах на Ассемблере?
2. Объясните понятие «ключевое слово».
3. Что такое «константа»? Какие виды констант Вы знаете? Каковы их отличия друг от друга?
4. Каковы особенности записи числовых и строковых констант?
5. Какие виды выражений Вы знаете? Для чего выражения
используются в программах?
6. Что такое «оператор»? Приведите пример.
7. Каков порядок выполнения операторов в выражении?
8. Какие основные виды предложений программ на ассемблере Вы знаете? Охарактеризуйте их.
9. Каковы особенности записи предложений в программах на
Ассемблере?
10. Что такое комментарий в программах? Как записываются комментарии в программах на Ассемблере?
11. Что такое «команда»? Каковы правила записи команд в
программах на Ассемблере?
12. Как записываются метки в программах на Ассемблере?
Для чего они служат?
– 33 –
13. Какие виды операторов Вы знаете? Каковы правила сочетания операндов в команде?
14. Каково назначение директив в программе? Как записываются директивы?
15. Каковы особенности использования сегментных регистров?
16. Как в тексте программы записать программный сегмент? Какие основные виды программных сегментов Вы знаете?
Каковы особенности объявления сегмента стека?
17. Для чего в программе употребляется директива ASSUME?
Каковы начальные значения сегментных регистров?
18. Объясните понятие «точка входа». Как объявить точку
входа в программе?
19. С помощью каких команд можно осуществить выход из
программы?
20. С помощью каких команд можно правильно адресовать
сегмент данных?
– 34 –
Лабораторная работа № 3
ОСНОВНЫЕ АРИФМЕТИЧЕСКИЕ ОПЕРАЦИИ
Цель работы: изучение основных арифметических операторов.
Краткие теоретические положения
Для операции сложения используется оператор ADD. Формат
оператора:
ADD-приемник, источник.
Значение источника прибавляется к приемнику при этом значение источника остается неизменным.
Для операции сложения используется оператор SUB. Формат
оператора: SUB-приемник, источник.
Значение источника вычитается из приемника при этом значение источника остается неизменным.
Существует оператор, аналогичный следующей команде:
ADD AX,1.
Данная строка прибавляет к регистру AX единицу. Упрощенным
вариантом данной записи является оператор INC: INC-приемник.
К значению приемника прибавляется единица.
Существует оператор аналогичный следующей команде:
SUB AX,1.
– 35 –
Данная строка вычитает из регистра AX единицу. Упрощенным
вариантом данной записи является оператор DEC: DEC-приемник.
Из значения приемника вычитается единица.
Отладка
Часто бывает так, что программа, успешно пройдя этапы
трансляции и компоновки, все же работает не так, как ожидалось
или вообще не работает. Это означает, что формально, с точки
зрения правил языка программирования, программа написана
правильно (в ней нет синтаксических ошибок), однако алгоритм
ее в чем-то не верен. Для отладки такой программы следует воспользоваться услугами отладчика.
В данном курсе рассматривается работа с отладчиком Turbo
Debugger, представленным программой td.exe. Turbo Debugger является полноэкранной утилитой и имеет массу возможностей для отладки программ. Здесь рассматриваются только некоторые из них.
Для отладки в Turbo Debugger созданного исполняемого модуля hello.exe с отладочной информацией выполните командную
строку: td hello.
На экран будет выведен кадр отладчика, показанный на рис. 3.1.
– 36 –
Главное меню
Окно Module
Указатель
строки
Окно Watches
Строка «горячих» клавиш
Рис. 3.1. Экран программы Turbo Debugger.
Сверху экрана располагается главное меню, активизируемое
клавишей <F10>. С его помощью выполняются все основные команды Turbo Debugger.
Внизу экрана расположена строка «горячих» клавиш для
быстрого выполнения команд Turbo Debugger. Имеется три вида
набора «горячих» клавиш: основной, Ctrl- и Alt-набор. Два последних для каждого окна разные и выводятся после нажатия клавиш <Ctrl> и <Alt> соответственно.
Завершить работу с программой Turbo Debugger можно нажатием клавиш <Alt>+<X>, либо выполнить команду главного меню
<File|Quit>.
При отладке программы удобно просматривать не только содержимое переменных, но и регистров. Выполните команду глав– 37 –
ного меню <View|Registers>. На экране появится окно Regs, отображающее содержимое регистров, включая состояния флагов регистра флагов.
Окно Module
Так как исполняемый файл hello.exe содержит отладочную
информацию, то в Turbo Debugger возможно использование окон
Module. При открытии программы отладчик проверяет содержимое в ней отладочной информации и в случае успеха открывает
окно Module, в которое выводит исходный текст главного модуля.
Программа может состоять из нескольких модулей, объединенных
компоновщиком в один исполняемый файл. Окно Module вызывается нажатием «горячей» клавиши <F3>, либо выполнением команды главного меню <View|Module...>.
– 38 –
Рис. 3.2. Основные окна Turbo Debugger.
В окне Module часто выполняются следующие действия:
– запуск, либо автоматическое продолжение выполнения
программы.
<Ctrl>+<F2> – досрочное, аварийное завершение выполнения
программы.
<F2>
– установка, либо снятие точки останова в строке, где
находится курсор. Отладчик прекращает автоматическое выполнение программы и останавливается перед
выполнением строки с точкой останова. Дальнейшее
выполнение программы можно продолжить клавишами: <F4>, <F7>, <F8> и <F9>, либо досрочно завершить программу клавишами <Ctrl>+<F2>.
<F4>
– автоматическое выполнение программы с текущей
строки до строки, на которой установлен курсор.
<F7>, <F8> – пошаговое выполнение программы.
<F9>
<Alt>+<F5> – вызов экрана DOS. Выполняется для просмотра
выводимой программой на экран информации.
<Ctrl>+<F7>, – помещение переменной или регистра в окно Watches
<Ctrl>+<W> для просмотра и изменения их содержимого.
Окно Module не предназначено для редактирования текста
программы при обнаружении ошибки. Для ее исправления требуется выйти из отладчика, в текстовом редакторе исправить ошиб-
– 39 –
ку, затем создать исполняемый модуль и загрузить его в Turbo
Debugger для дальнейшей отладки
Пример. Использование основных арифметических операторов
Разработать программу, реализующую формулу:
Х= - 4А + (В + С) / 4 + 2.
data segment
a dw 2
b dw 10
c dw 30
x dw ?
data ends
code segment
assume cs: code, ds: data
start:
mov ax, data ; загрузить адрес
mov ds, ax
; сегмента данных
mov ax, a
mov bx, b
mov cx, c
sal ax, 1
; ax <- 2a
sal ax, 1
; ax <- 4a
neg ax
;ax <- -4a
add bx, cx
; bx <- b+c
sar bx, 1
; bx <- (b+c)/2
sar bx, 1
; bx <- (b+c)/4
inc bx
inc bx
; bx <- (b+c)/4+2
add ax, bx
; ax <- -4a+(b+c)/4+2
mov x, ax
; запись результата в память
– 40 –
quit:
mov ax, 4c00h
int 21h
code ends
end start
; код завершения 0
; выход в dos
Варианты индивидуальных заданий
Написать, программу, выполняющую подсчет арифметического выражения:
№ Пример №
Пример
№
Пример
№
Пример
№
Пример
1
8*a+b/16- 5 -a+b/2+c/2+3 9 (8*a+b/16)*2+c 13 a+b/16-8*c+5 17
c/2+6
2
4*a+b/+c 6
3
8*a-b/16- 7
11 4*a+b/16-c/4+7 15 4*a+b/16+5+4 19 a/2+b/16+c/8+5
c/4+7
(4*a+b/16)+9
4
-4*a+bc/16+4
8
-8*a-b/16c/2+2
8*a+b/16+
+4*c-11
10 2*a+b/16+2*c 14 2*a+b/16-11 18 a+b/16+4*c-18
8*a+b/16+ 12 -(-a-b-c)/16-4 16
+16*c-5
8*a+b/1628+2*c
20 a/4+b/16+c/2+3
Контрольные вопросы
1. Какой формат оператора сложения?
2. Какой формат оператора вычитания?
3. Как используются операторы sal и sar?
4. Как используется оператор neg?
5. Как используются команды INC и DEC ?
6. Какие инструментальные средства используются при создании ассемблерных программ?
7. На какие этапы подразделяется процесс создания ассемблерных программ?
– 41 –
8. Каково место кодирования в процессе создания ассемблерных программ? Каким инструментальным средством оно
осуществляется?
9. Каково место транслирования в процессе создания ассемблерных программ? Каким инструментальным средством оно
осуществляется?
10. Каковы назначения ключей транслятора /z, /zi и /l?
11. Каково назначение файла листинга? Как он создается и из
чего состоит?
12. Каково место компоновки в процессе создания ассемблерных программ? Каким инструментальным средством оно
осуществляется?
13. Каким образом создать исполняемый модуль, включающий
в себя отладочную информацию?
14. Каково место отладки в процессе создания ассемблерных
программ? Каким инструментальным средством оно осуществляется?
15. С помощью каких окон в основном осуществляется отладка программы в Turbo Debugger?
16. Каково назначение окна «Module» в Turbo Debugger? Какие
горячие клавиши используются в этом окне и какие действия они
выполняют?
17. Каково назначение окна «Wathes» в Turbo Debugger? Какие
горячие клавиши используются в этом окне и какие действия они
выполняют?
18. Каково назначение окна «Regs» в Turbo Debugger? Какие
горячие клавиши используются в этом окне и какие действия они
выполняют?
19. Каково назначение окна «Dump» в Turbo Debugger? Какие
горячие клавиши используются в этом окне и какие действия они
выполняют?
20. Каково назначение и структура окна «CPU»? Как его вызвать?
– 42 –
Лабораторная работа 4
Цель работы: научиться использовать операторы циклов.
Краткие теоретические положения. Для реализации циклов
в Ассемблере используются следующие операторы:
Loop-метка, при этом количество повторов задается в регистре cx.
Команда
Перевод (с англ.)
Назначение
– 43 –
Процессор
LOOP-метка
loop – петля
Организация циклов
8086
Jnz-метка, количество повторов заносится в регистр cx, но в
отличие от оператора loop необходимо использовать оператор dec
чтобы исключить бесконечный цикл (значение в регистре cx не
уменьшается при очередном прохождении цикла)
Команда
Перевод (с англ.)
Назначение
Процессор
JNZ-метка
JUMP not zero
перейти пока не нуль
Организация
циклов
8086
Оператор безусловного перехода:
Команда Перевод (с англ.)
Назначение
JMP-метка jump – прыжок Безусловный переход
Процессор
8086
Пример. Вывести на экран сообщения в цикле реализации
с помощью оператора loop
(1) mov cx,3
(2) Label_1:
(3) mov ah,9
(4) mov dx,offset Str
(5) int 21h
(6) loop Label_1
реализация с помощью оператора jnz
(1) mov cx,3
(2) Label_1:
(3) mov ah,9
(4) mov dx,offset Str
(5) int 21h
– 44 –
(6) dec cx
(7) jnz Label_1
Дан массив из десяти знаковых чисел типа слово.
Найти сумму всех положительных и отрицательных чисел.
Массив слов.
data segment
sum_otricat dw ?
сумма отрицательных чисел
sum_pologit dw ?
сумма положительных чисел
mass dw 1,-4,6,-2,-3,8,-5,5,-1,7
data ends
code segment
assume cs: code, ds: data
start:
mov ax, data
mov ds, ax
; Загрузить сегментный адрес данных
lea bx, mass ; Загрузить адрес смещения массива
mov cx, 10 ; Установить счетчик повторений цикла
xor ax, ax
; Обнулить начальную сумму положительных чисел
xor dx, dx
; Обнулить начальную сумму отрицательных чисел
beg:
mov si, [bx]
cmp si, 0
jl m1
add ax, si
jmp m2
m1:
add dx, si
m2:
inc bx
; в si очередной элемент
;если меньше нуля
;если больше или равно нулю
– 45 –
; указатель сдвинуть на следующий элемент
массива
inc bx
loop beg
mov sum_pologit, ax
mov sum_otricat, dx
quit: mov ax,4C00h
; Код завершения 0
int 21h
; Выход в DOS
code ends
end start
Варианты индивидуальных заданий
В заданном массиве чисел, найти сумму чисел, принадлежащих
промежутку А:
№
А
№
А
№
А
№
А
№
А
1
(-3,8)
5
(-6,6)
9
(-10,1)
13
(1.7)
17
(-3,14)
2
(-9,9)
6
(-8,8)
10
(-4,15)
14
(2,10)
18
(-1,10)
3
(0,15)
7
(-3,18)
11
(0,7)
15
(-11,7)
19
(-9,8)
4
(-13,0)
8
(-4,4)
12
(-6,1)
16
(-7,12)
20
(-8,8)
Контрольные вопросы
1. Какие операторы используются в Ассемблере для организации циклов?
2. Чем отличается оператор jnz от loop?
3. В каком регистре хранится количество повторов цикла?
4. Оператор безусловного перехода?
5. Приведите пример использования операторов цикла?
– 46 –
Лабораторная работа 5
Цель работы: изучить возможности использования операторов Push и pop.
Краткие теоретические положения
Схема команды:
рush-источник
– 47 –
Команда push используется совместно с командой pop для записи значений в стек и извлечения их из стека. Размер записываемых значений — слово или двойное слово.
Схема команды:
рop-приемник
Команда применяется для восстановления содержимого вершины стека в регистр, ячейку памяти или сегментный регистр
Пример: Дан массив из 8 байт. Рассматривая его как массив из 64 бит, посчитать количество единиц.
data segment
NA
db
01101101b,
11011011b,10110110b,
01111101b,
10010000b,10000110b
db 11111111b, 00000000b ;всего 35 единиц
COLICHESTVO db 0
data ends
code segment
assume cs: code, ds:data
START:
mov ax, data
mov ds, ax
; Загрузить сегментный адрес данных
lea bx, NA
; bx-текущий адрес массива NA
mov cx, 8
; счетчик числа интераций по байтам
xor dl, dl
; счётчик, единиц
BEG:
mov al, [bx] ; считать очередной байт массива
push cx
; организовать цикл по битам
mov cx, 8
m1:
shr al, 1
; сдвиг вправо и вытолкнутый разряд
попадает в CF
jnc m2
; переход, если очередной бит 0
inc dl
– 48 –
m2:
loop m1
; вложенный цикл
pop cx
inc bx ;перейти к следующему байту
loop BEG
mov COLICHESTVO, dl
QUIT:
mov ax, 4c00h
; Код завершения 0
Int 21h
; Выход в DOS
code ends
end START
Варианты индивидуальных заданий
Выполнить задание, рассмотренное в лабораторной работе в
Turbo Debugger и подробно описать работу программы.
Контрольные вопросы
1. Что происходит со значениями регистров при загрузке нового значения?
2. Какие операторы используются для временного хранения
значений регистров?
3. Формат оператора pop?
4. Формат оператора push?
5. Куда записываются значения с помощью операторов Pop и
push?
Лабораторная работа 6
Цель работы: научиться управлять положением курсора на
экране монитора.
Краткие теоретические положения
– 49 –
Для позиционирования курсора используется 2 функция 10
прерывания. При этом номер страницы указывается в регистре bh
в регистр dh заносится номер строки в регистр dl номер столбца.
mov ah,2
mov bh,0
mov dh,10 ;stroka
mov dl, 35 ;stolbec
int 10h
Для управления видеорежимом используется 6 функция 10
прерывания. При этом в регистр al заносится число закрашиваемых строк, в регистр bh цвет фона и цвет символов соответственно. В регистры dh и ch заносится позиция строки левого верхнего
угла закрашиваемой области. В регистры dl и cl заносится позиция минимального и максимального значения столбца закрашиваемой области.
mov ax,604h ; dopolnitelnie stroki poidut vniz
mov bh,41h ; cvet fona i simvolov
mov dx,0a23h ; 0a- kol-vo strok sverhu, 23- chislo stolbcov sprava
mov cx,0a27h ; 0a- (24-(kol-vo strok cverhu)),27- (80-1-(chislo
stolbcov sprava))
int 10h
Пример: позиционирование курсора
CSEG segment
org 100h
Start:
mov ah,2
mov bh,0
mov dh,10 ;stroka
mov dl, 35 ;stolbec
int 10h
mov ah,9
– 50 –
mov dx,offset String1
int 21h
mov ah,2
mov bh,0
mov dh,11 ;stroka
mov dl, 35 ;stolbec
int 10h
mov ah,9
mov dx,offset String2
int 21h
mov ah,2
mov bh,0
mov dh,12 ;stroka
mov dl, 35 ;stolbec
int 10h
mov ah,9
mov dx,offset String2
int 21h
mov ah,2
mov bh,0
mov dh,13 ;stroka
mov dl, 35 ;stolbec
int 10h
mov ah,9
mov dx,offset String1
int 21h
mov ah,10h
int 16h
int 20h
String1 db '*****$'
String2 db '* *$'
CSEG ends
– 51 –
end Start
Пример: обращение к видеорежиму
CSEG segment
org 100h
Start:
mov ax,604h ; dopolnitelnie stroki poidut vniz
mov bh,41h ; cvet fona i simvolov
mov dx,0a23h ; 0a- kol-vo strok sverhu, 23- chislo stolbcov sprava
mov cx,0a27h ; 0a- (24-(kol-vo strok cverhu)),27- (80-1-(chislo
stolbcov sprava))
int 10h
mov ah,2
mov bh,0
mov dh,10 ;stroka
mov dl, 35 ;stolbec
int 10h
mov ah,9
mov dx,offset String1
int 21h
mov ah,2
mov bh,0
mov dh,11 ;stroka
mov dl, 35 ;stolbec
int 10h
mov ah,9
mov dx,offset String2
int 21h
mov ah,2
mov bh,0
mov dh,12 ;stroka
mov dl, 35 ;stolbec
int 10h
– 52 –
mov ah,9
mov dx,offset String2
int 21h
mov ah,2
mov bh,0
mov dh,13 ;stroka
mov dl, 35 ;stolbec
int 10h
mov ah,9
mov dx,offset String3
int 21h
mov ah,10h
int 16h
int 20h
String1 db 0c9h,0cdh,0cbh,0cdh,0bbh,'$'
String2 db 0bah,0ceh,0b0h,0ceh,0bah,'$'
String3 db 0c8h,0cdh,0cah,0cdh,0bch,'$'
CSEG ends
end Start
Варианты индивидуальных заданий
Написать программу, выводящую на экран некоторый рисунок, состоящий из простых фигур(прямых линий и других геометрических фигур).
Контрольные вопросы
1. Какое прерывание используется для позиционирования
курсора?
– 53 –
2. Какое прерывание используется для обращения к видеорежиму?
3. В какой регистр помещается цвет фона, символов?
4. Каким образом указывается начальная координата области закрашивания?
5. Формат 2 функции 10 прерывания?
Приложение I
Образец оформления титульного листа
– 54 –
Северо-Кавказский горно-металлургический институт
(государственный технологический университет)
Кафедра АОИ
Лабораторная работа №
«Название»
Выполнил: ____________________
Проверил: ____________________
Владикавказ
20 ____ г.
Приложение II
Шестнадцатирично-десятичные преобразования
– 55 –
В данном приложении представлены приемы преобразования
между шестнадцатеричным и десятичным форматами. В первом
разделе показан пример преобразования А7В8 в десятичное
42936, а во втором – 42936 обратно в А7В8.
Преобразование шестнадцатеричного формата в десятичный
Для перевода числа А7В8 в десятичное число необходимо последовательно начиная с самой левой цифры (А) умножать на 16 и
складывать со следующей цифрой. Так как операции выполняются в десятичном формате, то числа от А до F необходимо преобразовать в десятичные от 10 до 15:
(( А * 16 + 7) * 16 + B) * 16 + 8 =
((10 * 16 + 7) * 16 + 11) * 16 + 8 = 42936.
Можно использовать также таблицу преобразования. Для
шестнадцатеричного числа А7В8 представим правую цифру (8)
как позицию 1, следующую влево цифру (В) – как позицию 2,
следующую цифру (7) – как позицию 3 и самую левую цифру (А)
– как позицию 4. Из табл. II.2 выберем значения для каждой
шестнадцатиричной цифры:
Для позиции 1 (8), столбец 1
Для позиции 2 (В), столбец 2
Для позиции 3 (7), столбец 3
Для позиции 4 (А), столбец 4
Десятичное значение
8
176
1792
40960
42936
Преобразование десятичного формата в шестнадцатеричный
Для преобразования десятичного числа 42936 в шестнадцатеричный формат необходимо сначала исходное число 42936 разделить на 16; число (6), получившееся в остатке, является младшей
шестнадцатеричной цифрой. Затем полученное частное необходимо снова разделить на 16 и полученный остаток (11 или В) даст
следующую влево шестнадцатеричную цифру. Продолжая таким
– 56 –
образом деление до тех пор, пока в частном не получится 0, получим из остатков все необходимые шестнадцатеричные цифры:
42936 / 16
Частное
2683
Остаток
8
Шестнадцатеричное значение
8 (младшая цифра)
2683 / 16
167
11
В
167 / 16
10
7
7
10 / 16
0
10
А (старшая цифра)
Для преобразования чисел из десятичного формата в шестнадцатиричный можно также воспользоваться табл. II.1. Для десятичного числа 42936 необходимо найти в таблице число, равное
или ближайшее меньшее исходного, и записать соответствующую
шестнадцатеричную цифру и ее позицию. Затем следует вычесть
найденное десятичное число из 42936 и с полученной разностью
проделать проделать ту же операцию:
Дес.
Шест.
Исходное десятичное число
42936
Вычесть ближайшее меньшее
Разность
40960
1976
А000
Вычесть ближайшее меньшее
1792
700
Разность
184
Вычесть ближайшее меньшее
Разность
176
8
В0
8
Результирующее шестнадцатеричное число
А7В8
Таблица II.1
0 0
0 0
0 0
0 0
– 57 –
0 0
0 0
0 0
0 0 0000
1 268435456 1 16777216 1 1048576 1 65536 1 4096 1 256
1 16
1 1 0001
2 536870912 2 33554432 2 2097152 2 131072 2 8192 2 512
2 32
2 2 0010
3 805306368 3 50331648 3 3145728 3 196608 3 12288 3 768
3 48
3 3 0011
4 1073741824 4 67108864 4 4194304 4 262144 4 16384 4 1024 4 64
4 4 0100
5 1342177280 5 83886080 5 5242880 5 327680 5 20480 5 1280 5 80
5 5 0101
6 1610612736 6 100663296 6 6291456 6 393216 6 24576 6 1536 6 96
6 6 0110
7 1879048192 7 117440512 7 7340032 7 458752 7 28672 7 1792 7 112 7 7 0111
8 2147483648 8 134217728 8 8388608 8 524288 8 32768 8 2048 8 128 8 8 1000
9 2415919104 9 150994944 9 9437184 9 589824 9 36864 9 2304 9 144 9 9 1001
A 2684354560 A 167772160 A 10485760 A 655360 A 40960 A 2560 A 160 A 10 1010
B 2952790016 B 184549376 B 11534336 B 720896 B 45056 B 2816 B 176 B 11 1011
C 3221225472 C 201326592 C 12582912 C 786432 C 49152 C 3072 C 192 C 12 1100
D 3489660928 D 218103808 D 13631488 D 851968 D 53248 D 3328 D 208 D 13 1101
E 3758096384 E 234881024 E 14680064 E 917504 E 57344 E 3584 E 224 E 14 1110
F 4026531840 F 251658240 F 15728640 F 983040 F 61440 F 3840 F 240 F 15 1111
8
7
6
5
4
3
2
1
Приложение III
ASCII символы
– 58 –
Все символы, отображаемые на экране дисплея или выводимые
на печать, имеют закрепленные за ними коды, которые называются
кодами ASCII (American Standard Code for Information Interchange
американский стандартный код для обмена информацией).
Каждый код ASCII занимает один байт и может принимать
значения от 0 до 255. Совокупность всех 256 кодов вместе с изображениями символов приведены в следующей таблице:
Таблица III.1
0 1 2 3 4 5 6 7 8 9 A B C D E F
0
1
2
3
4
5
6
7
8
9
A
B
C
D
E
F
Управляющие
символы
Основной набор
символов
Символы
псевдографики
Коды ASCII 00h – 1Fh называются управляющими. Они используются в функциях MS DOS ввода-вывода на внешние уст3
ройства для управления соответствующим процессом. Например, при выводе с помощью функций DOS код 0Dh переводу курсора в начало строки, а код 07h вызывает краткий сигнал динамика.
– 59 –
Коды ASCII 20h – 7Fh составляют основной или другими словами стандартный набор символов. Изображения этих символов
не меняются.
Коды ASCII 80h – FFh соответствуют в основном знакам
национального алфавита той или иной страны. В данном наборе
обычно выделяются символы псевдографики с кодами ASCII
B0h – DFh.
Любой код ASCII может быть введен с клавиатуры, если держать нажатой клавишу <Alt> и набрать номер кода на дополнительной клавиатуре (с соответственно установленным режимом
«NumLock»). Когда клавиша <Alt> освобождается, код вводится.
ЛИТЕРАТУРА
1. Юров В. И. Ассемблер. СПб.: БХВ-Петербург, 2002. 608 с.
2. Пирогов В. Ю. Ассемблер для Windows: Учебное пособие. М.:
Изд-во МГУ, 2004. 71 с.
– 60 –
3. Кинг Д. Создание эффективного программного обеспечения. М.:
Институт компьютерных исследований, 2003.
4. Баканов В. М., Осипов Д. В. Введение в практику разработки программ на языке Ассемблер: Учебно-методическое пособие по выполнению лабораторных работ. М.: МГАПИ, 2005. 63 с.: ил.
– 61 –
АССЕМБЛЕР
МЕТОДИЧЕСКИЕ УКАЗАНИЯ

по выполнению лабораторных работ для студентов,
обучающихся по направлению подготовки 230100.62 –
«Информатика и вычислительная техника»
Составители: А. С. Мирошников, Е. А. Соколова
ВЛАДИКАВКАЗ 2014
– 62 –
Related documents
Download