
- •Безумовний перехід
- •Умовний перехід
- •Формат регістру прапорців.
- •If (Interrupt Flag) – прапорець переривання. Якщо стан цього прапорця нульовий, переривання заборонені, якщо одиничний – дозволені (керує тільки маскованими апаратними перериваннями).
- •Команди переходу для беззнакових даних.
- •Команди переходу для знакових даних
- •Спеціальні арифметичні перевірки
- •Ссув та циклічний ссув розрядів
- •Очищення екрану.
- •Склад макрокоманд (макросів)
Ці методичні вказівки розроблені у відповідності з діючою робочою програмою з курсу “Програмування”, створенною у 2003 році для студентів спеціальності “Прикладна математика” і охоплють розділи, що зв’язані з вивченням основ програмування на прикладі мови Асемблер.
Методичні вказівки містять керівництво до восьми лабораторних робіт, відповідаючих вказаним розділам.
Структура методичних вказівок до кожної лабораторної роботи така: мета роботи, короткі теоретичні відомості, вказівки до підготування до роботи, робоче завдання та контрольні запитання. Варіанти завдань наведено у окремому документі.
ЛІТЕРАТУРА, ЩО РЕКОМЕНДОВАНА
Абель П. Язык Ассемблера для IBM PC и программирования/ Пер.с англ. Ю.В.Сальникова.- М.:Высш.шк.,1992.-442с7:илл.
ЛАБОРАТОРНА РОБОТА №1
ПЕРША ПРОГРАМА НА АСЕМБЛЕРІ
Мета роботи: ознайомитись з основними вимогами до програм на мові “Асемблер”
КОРОТКІ ТЕОРЕТИЧНІ ВІДОМОСТІ
Першим етапом створення програми є написання текстового файлу на спеціальній мові – Асемблері. Цей файл створюється будь яким текстовим редактором.
Пізніше цей текстовий файл буде оброблено спеціальною програмою – транслятором для перетворення до машинного коду.
У цій та наступних лабораторних роботах наведені правила написання програм на мові Асемблера фірми Microsoft - MASM. Turbo Assembler, на якому будуть виконуватися лабораторні роботи, по умочуванню працює у режимі MASM.
Програма, написана на мові Асемлера, складається з рядків. Максимальна довжина рядка – 80 символів. Рядки відділяються один від одного символом «Enter».
Базовий формат рядка
[мітка] команда [операнд_1][,операнд_2] [;коментар]
У квадратних дужках вказані необов’язкові поля.
Мітка, якщо вона є, команда та перший операнд відділяються один від одного не менш як одним символом пропуску або табуляції.
МІТКА – це символьне ім’я або ідентифікатор, що помічає відповідну строку, щоб до неї можна було звернутися. Символьне ім’я може мати будь яку кількість символів, але транслятор відрізняє тільки перший 31 символ. Тому символьне ім’я повинно бути унікальним за першими 31 сімволами. Припустимі символи:
літери від A до Z або від a до z (у режимі, що прийнятий по умовчванню, транслятор не відрізняє великі та маленькі букви);
цифри від 0 до 9;
спеціалні символи: знак питання(“?”), крапка (“.”) – тільки перший символ, комерційне “а” (“@”), підкреслювання (“_”), знак долару (“$”).
Першим символом у символьному імені обов’язково повинна бути літера або спеціальний символ.
Імена регістрів зарезервовані. Іх можна використовувати тільки для визначення регістрів.
Команда визначає дію, яку повинен виконати процесор або транслятор з мови Асемблер. В якості команд можуть використовуватись команди процесора (власне команди) та директиви Асембреру (псевдокоманди). Команди процесора на етапі трансляції перетворюються на машинний код і виконуються під час виконання програми. Директиви вказують програмі – транслятору, що їй треба робити. Вони виконуються на етапі трансляції і у машинний код не перетворюються.
ОПЕРАНД визначає елемент, над яким виконує дію команда.
Команда може мати один чи два операнди, або не мати їх зовсім.
RET - команда без операнда;
INC CX - команда з одним операндом;
ADD AX,12 - команда з двома операндами.
Якщо команда має два операнди, вони розділяються комою (“,”). При використовуванні двох операндів першим вказується операнд– приймач, другим - операнд–джерело. Тобто результат операціїї заноситься до першого операнду.
Приклади завдання операндів.
MOV AX,BX ;переслати вміст BX у AX
MOV AX,WORDA ;переслати вміст чарунки пам’яті з
;им’ям WORDA у AX
MOV AX,[BX] ;переслати вміст чарунки пам’яти за адресою, що
; вказана у BX до AX
MOV AX,25 ;переслати число 25 у регістр AX
Коментар починається з крапки з комою (“;”). Він може займати усю строку абу бути останнім полем у строці, як показано у форматі команди. Коментар присутній тільки у похідному коді команди та листігу і не наводить до генерації машиних кодів. У коментарі припускаються будь які символи основної клавіатури.
ДИРЕКТИВИ (або псевдокоманди).
Це команди, які дозволяють керувати процесом трансляції та формування листінгу.
Директива SEGMENT. Застосовується для опису сегментів, що використовуються у програмі. Будь яка програма містить не менш як один сегмент – сегмент кодів. Можуть буди присутні також сегменти стеку та даних, а також додатковий сегмент. Формат директиви.
Ім’я Директива Операнд
ім’я SEGMENT [атрибути]
; вміст сегменту
ім’я ENDS
Ім’я сегменту обов’язково повинно бути присутнім, бути унікальним і відповідати угоді задля символьних імен у Асемблері. Директива ENDS визначає кінець сегменту. Обидві директиви (SEGMENT та ENDS) повинні мати однакові імена. Атрибути сегменту зараз нам знадобляться тільки для опису сегменту стеку.
Сегмент стеку визначається наступним чином:
ім’я SEGMENT PARA STACK 'Stack'
DB 30 DUP(?)
ім’я ENDS
Директива PROC. Сегмент коду містить команди програми, що виконуються. Він може містити у собі одну або декілька процедур, які визначаються директивою PROC. Сегмент, що містить тільки одну процедуру, має вигляд:
ім’я_сегменту SEGMENT
ім’я_процедури PROC FAR
; текст процедури
RET ; команда виходу з процедури
ім’я _процедури ENDP
ім’я_сегменту ENDS
Ім’я процедури повинно бути присутнім, бути унікальним та відповідати угоді про символьні імена у Асемблері. Оператр FAR показує, що ця процедура може викликатись з іншого сегменту.
Директива ASSUME. Процесор використовуе регістр SS для адресування стеку, регістр DS – для адресування сегменту даних та регістр CS – для адресування сегменту кода. Асемблеру треба вказати призначення кожного сегменту.
Директива Операнд
ASSUME SS:ім’я_сегм_стека,DS:ім’я_сегм_данных,CS:ім’я_сегм_кода
де ім’я_сегм_стека, ім’я_сегм_данных, ім’я_сегм_кода – імена відповідно сегментів стеку, даних і кода, визначені директивою SEGMENT.
Операнди можуть записуватись у будь якій послідовності. Регістр ES також може бути присутнім серед операндів. Якщо програма не використовує регістр ES, то його можна не вказувати у директиві ASSUME, або вказати ES:NOTHING.
Директива END. Повністю завершує програму.
Директива Операнд
END [місце входу у програму]
Операнд може бути пропущений. якщо програма не призначена для виконання (асемблюється тільки для визначення даних або повинна бути скомпонована з інщим (головним) модулем). Для звичайної програми з одним (головним) модулем операнд містить ім’я, вказане в директиві PROC, яка була визначена як FAR.
ІНІЦІАЛІЗАЦІЯ ПРОГРАМИ.
Існують два основних типи завантажуваних модулей: EXE і COM. Розглянемо вимоги до EXE-програм. Система DOS має чотири вимоги для ініціалізації асемблерної EXE-програми.
1. Необхідно вказати Асемблеру, які сегментні регістри яким сегментам віповідають (виконується директивою ASSUME).
2. Необхідно зберегти в стеці адресу, що знаходиться у регістрі DS.
Безпосередньо перед завантажуванним модулем у оперативній пам’яті знаходиться 256-байтова (100Н) ділянка пам’яті, яка зветься префіксом програмного сегменту (PSP), в якій DOS зберігає свою службову інформацію. Після завантаження ЕХЕ-програми у оперативну пам’ять регістр DS містить адресу початку (базу) PSP.
Програма користувача повинна зберегти цю адресу, записавши її до стеку. По закінченні програми команда RET візьме цю адресу зі стеку для повернення в DOS.
3. не обхідно записати до стеку “0”.
4. Необхідно завантажити до DS адресу сегменту даних. Завантажувач DOS встановлює вірні адреси стеку у регістрі SS та сегменту кодів у регістрі CS. Тому що програма завантажувача використовує регістр DS для зберігання бази PSP, необхідно явно ініціалізувати регістр DS.
Вихід з програми та повернення у DOS виконується за допомогою команди RET. Команда RET забезпечує вихід з програми користувача і повернення у DOS, використовуючи для цього адресу, що була записана до стеку з регістру DS на початку програми. Виконує вона це наступним чином. Команда RET для процедури типу FAR добуває зі стеку два верхніх слова і записує іх у регістри IP та CS. Верхні два слова у стеці містять ноль та базу PSP. Таким чином ноль потрапляє в IP, а база PSP – в CS. Таким засобом команда RET передае курування за адресою база_PSP: 0, тобто на нульову чарунку PSP, а в цій чарунці міститься команда системного повернення до DOS.
Приклад програми.
SEGST SEGMENT PARA STACK 'Stack'
DB 30 DUP(?)
SEGST ENDS
;-------------------------------------
SEGDT SEGMENT
A DB 5 ;ці дані не використовуються у наведеній програмі
B DW 300 ;і наведені задля ілюстрування використання сегменту
;даних
SEGDT ENDS
;-------------------------------------
SEGCOD SEGMENT
ASSUME CS:SEGCOD,SS:SEGST,DS:SEGDT
BEGIN PROC FAR
PUSH DS ;збережіть вміст DS в стеці
SUB AX,AX ;обнулюйте регістр AX
PUSH AX ;занесіть вміст AX (тобто 0) до стеку
MOV AX,SEGDT ;занесіть адресу початку сегменту даних у
;регістр AX
MOV DS,AX ;занесіть вміст AX у регістр DS
;-----------------------------------------------------
SUB BX,BX ;обнулюйте регістр BX
ADD BX,10 ;додайте до вмісту BX 10
MOV CX,20 ;занесіть у CX 20
ADD BX,CX ;додайте CX до BX
SUB BX,CX ;віднімить CX від BX
;-------------------------------------------------------
RET
BEGIN ENDP
SEGCOD ENDS
END BEGIN
ПІДГОТОВКА ДО РОБОТИ
Вивчить короткі теоретичні відомості та рекомендовану літературу.
Підготуйте програму у відповідності з своїм варіантом.
РОБОЧЕ ЗАВДАННЯ
Наьеріть текст підготовленої програми, використовуючи будь який текстовий редактор, наприклад, редактор Norton Commander.
КОНТРОЛЬНІ ЗАПИТАННЯ
Наведіть формат рядку мови Асемблер.
Що буде знаходитись у регістрах AX и BX після виконання наступних команд
MOV AX, 20
MOV BX, 10
ADD AX, BX
3. Перерахуйте вимоги для ініціалізації EXE-програми.
4. Що містить сегментний регістр DS після завантаження EXE-програми у оперативну пам’ять.
5. Як виконується повернення із програми користувача до DOS.
ЛАБОРАТОРНА РОБОТА №2
ТРАНСЛЯЦІЯ, КОМПОНУВАННЯ ТА НАЛАГОДЖУВАННЯ ПРОГРАМИ
Мета роботи: засвоїти процеси трансляції, компонування та налагоджування програми, що написана на мові Асемблер.
КОРОТКІ ТЕОРЕТИЧНІ ВІДОМОСТІ
Процес створення програми на мові Асемблер включає до себе наступні етапи (мал.1).
Першим етапом створення програми є написання ТЕКСТОВОГО файлу на мові Асемблер (далі цей файл будемо називати похідним текстовим файлом). Виконується цей етап за допомогою будь якого текстового редактора, наприклад, редактора Norton Commander. Для файлів, що написані на мові Асемблер, прийняте розширення .asm.
На другому етапі ви повинні виконати трансляцію вашого похідного файлу у об’єктний код. В процесі тренсляції текст вашої програми буде перетворено у машинний код, який на цьому етапі ще не прив’язаний до конкретних фізичних адрес. Об’ектний код вашої програми в результаті трансляції буде розміщено у OBJ-файл – файл з розширенням .obj. Для трансляції використовується програма – транслятор tasm.exe. Для трансляції вашої програми введіть наступний командний рядок:
[шлях]tasm[опції] sours[,object][,listing][,xref]
де sours, object, listing, xref - відповідно шляхи та імена похідного файлу, OBJ-файлу, файлу листінга та XREF-файлу (файлу перехрестного посилання).
Якщо запустити tasm без параметрів на екран буде виведено формат командного рядку для tasm та опції транслятора.
Файл перехрестного посилання для роботи з невеликими прграмами не потрібен.
Наприклад, для похідного файлу name.asm командний рядок може виглядати так:
tasm name.asm, name.obj, name.lst
При цьому вважається, що похідний файл та файл tasm.exe знаходяться в одному каталозі. У протилежному випадку треба вказувати шлях до файлів. При збереженні порядку перелічення файлів розширення можна опустити. Якщо ви впевнені у відсутності помилок, виконати трансляцію можна за допомогою такого командного рядка
tasm name
При цьому буде створено тільки об’єктний файл з тим же ім’ям, що і похідний, але з розширенням .obj.
Транслятор перетворює похідний файл у машиний код та видає на екран повідомлення про помилки, що зустрілися. Під час трансляції визначаються синтаксичні помилки вашої програми, наприклад, неприпустима команда, використання однакових, або неприпустимих імен, невірний формат директиви Асемблера та інше. На початку роботи з Асемблером програміст робить багато синтаксичних помилок. Для зручності визначення місця помилки можна використати файл листінгу. Файл листінг є текстовим файлом і щоб його продивитись, можно використати відповідні засоби Norton Commander.
Нище наведен листінг програми з лабораторної роботи №1.
Turbo Assembler Version 4.0 01/07/03 21:20:02 Page 1
name.asm
1 0000 SEGST SEGMENT PARA STACK 'Stack'
2 0000 1E*(??) DB 30 DUP(?)
3 001E SEGST ENDS
4 ;-------------------------------------
5 0000 SEGDT SEGMENT
6 0000 05 A DB 5 ; ці дані не використовуються в наведеній програмі
7 0001 012C B DW 300; і наведені для ілюстрації використання сегменту
8 ; даних
9 0003 SEGDT ENDS
10 ;-------------------------------------
11 0000 SEGCOD SEGMENT
12 ASSUME CS:SEGCOD,SS:SEGST,DS:SEGDT
13 0000 BEGIN PROC FAR
14 0000 1E PUSH DS ;збережіть вміст DS в стеці
15 0001 2B C0 SUB AX,AX ;обнулюйте регістр AX
16 0003 50 PUSH AX ;занесіть вміст AX (тобто 0) у стек
17 0004 B8 0000s MOV AX,SEGDT;занесіть адресу початку сегменту в
18 ;регістр AX
19 0007 8E D8 MOV DS,AX ;занесіть вміст AX в регістр DS
20 0009 2B DB SUB BX,BX ;обнулюйте регістр BX
21 000B 83 C3 0A ADD BX,10 ;додайте до вмісту BX 10
22 MOW CX,20 ;занесіть в CX 20
**Error** name.asm(22) Illegal instruction
23 000E 03 D9 ADD BX,CX ;додайте CX до BX
24 0010 2B D9 SUB BX,CX ;відніміть CX від BX
25 0012 CB RET
26 0013 BEGIN ENDP
27 0013 SEGCOD ENDS
28 END BEGIN
Turbo Assembler Version 4.0 01/07/03 21:20:02 Page 2
Symbol Table
Symbol Name Type Value
??DATE Text "01/07/03"
??FILENAME Text "name "
??TIME Text "21:20:02"
??VERSION Number 0400
@CPU Text 0101H
@CURSEG Text SEGCOD
@FILENAME Text PR_MET
@WORDSIZE Text 2
A Byte SEGDT:0000
B Word SEGDT:0001
BEGIN Far SEGCOD:0000
Groups & Segments Bit Size Align Combine Class
SEGCOD 16 0013 Para none
SEGDT 16 0003 Para none
SEGST 16 001E Para Stack STACK
Turbo Assembler Version 4.0 01/07/03 21:20:02 Page 3
Error Summary
**Error** name.asm(22) Illegal instruction
Під час набирання програми у двадцять першому рядку була зроблена помилка: замість MOV було набрано MOW.
У правій частині листінга розташован похідний текст Вашої програми. У лівій частині листінга наводиться:
у першому стовбчику порядковий номер рядка явашої програми;
у другому стовбчику – зміщення відносно початку відповідного сегменту команди, що розташована в цьому рядку;
у третьому стовбчику – машиний код цієї команди. Зверніть увагу, що директиви Асемблера не генерують машиний код.
У кінці листінга наводиться таблиця ідентіфікаторів, імена ділянок даних в сегменті даних (А і В) та мітки, призначені командам в сегменті кодів (у нашому прикладі BEGIN). Друга частина таблиці містить визначені у програмі сегменти з їх розмірами у байтах, вирівнюванням та класом.
У разі виникнення помилки після рядка з помилкою буде виведено повідомлення про помилку та її причину.
Для виправлення помилок, визначених на етапі трансляції, Вам необхідно повернутись до першого етапу – текстовим редактором виправити помилки та повторити трансляцію. Процес повторяється доти, доки не будуть усунені усі помилки. Тільки в цьому разі буде створено об’єктний файл.
Третім етапом створення програми є КОМПОНУВАННЯ. На етапі компонування OBJ-файл, що створено під час трансляціїї похідного файлу, переторюється у EXE-файл, що може виконуватись. При цьому завершується формування адрес, які не були визначені на етапі трансляції, об’єднуються, якщо це необхідно, декілька OBJ-файл в єдиний EXE-файл.
Для компонування програми слід ввести командний рядок наступного вигляді:
[путь]tlink objfiles, [exefiles], [mapfiles], [libfiles], [defiles]
де objfiles та exefiles шляхи та імена відповідно об’єктного та ехе-файлу. Інші файли для роботи на нашему етапі не потрібні.
Якщо запустити tlink без параметрів на екран буде виведено формат командного рядка для tlink та опції компонувальника.
Наприклад, для компонування нашої програми командний рядок буде виглядати наступним образом:
tlink name.obj, name.exe
При цьому очікується, що всі файли знаходяться в одному каталозі.
При збереженні послідовності файлів розширення можна не вказувати.
Якщо ви впевненні у відсутності помилок, то можна ввести командний рядок у вигляді:
tlink name
Типовою помилкою на цьому етапі є неправильне визначення сегменту стеку.
У разі винекниння помилок компонування необхідно повернутись на етап редагування, знову странслювати програму та знову скомпонувати.
Коли усунені всі помилки, компонувальник сформує ехе-файл – файл з розширенням ехе.
EXE-файл вже є програмою, що виконується, її можна запустити для виконання командами MS DOS.
Для перевірки, чи вірно ви виконали вимоги до роботи програми під керуванням MS DOS, запустіть вашу програми на виконання. Якщо програми не “висить”, то вимоги ініціалізації ехе-програми виконані.
Може виникнути необхідність створити файл, що виконується, не у вигляді EXE-файлу, а у вигліді COM-файлу. Особливості COM-файла та правила його створення будуть розглянуті у лабораторній роботі №3.
Отже, ви створили вашу програму. Тепер її необхідно НАЛАГОДИТИ, тобто перевірити, чи вірно вона працює. На етапі налагоджування знаходяться логічні помилки у вашій програмі, які не можуть бути знайдені на єтапах трансляції та компонування. Особливо складно налагодити програму, яка не “спілкується” з користувачем – не виводить інформацію на екран. Для налагоджування асемблерних програм використовується спеціальна програма – налагоджувач. Одним з таких налагоджувачів є програма td.exe. Для запуску цієї програми введіть командний рядо такого вигляду:
[шлях]td.exe [шлях]ім’я_файлу.exe
Ім’я файлу - ім’я того файлу, який ви хочете налагодити. Налагоджувати можна тількі ті файли, що виконуються (EXE- и COM-файли).
Вигляд екрану після запуску налагоджувача подано на малюнку 2.
А
Г
Д
Б
В
Малюнок.2. Вигляд екрану після завантаження налагоджувача.
Натисніть «Enter» (тому що символьну таблицю ми не створювали) і верхнє повідомлення знике.
Вийти з налагоджувача можна, натиснув клавіши Alt-X або вибрав у верхньому меню пункт “Файл”, а у меню, що випадає, пункт “Вихід”.
У вікні “А” виведен вміст кодового сегменту: у лівому стовбчику - зміщення команд відносно сегментного регістру CS. У другому стовбчику знаходяться машині коди команд, у третьому – текст асемблерної програми.
У вікні “Б” знаходиться вміст регістрів процесора, у вікні “В” значення прапорців (вміст регістру прапорців), у вікні “Г” – вміст сегменту даних, у вікні “Д” – вміст стеку.
Одною з основних дій налагоджування програми є ТРАСУВАННЯ програми – її покрокове виконання. Під час трасування ваша програми буде виконуватись послідовно по одній команді. Для того, щоб виконати трасування, вам необхідно натиснути клавішу «F7». При цьому буде виконана одна команда вашої програми. Стрілка перед машиним кодом команди вказує на команду, яка буде виконуватись наступною. Після виконання кожної команди інші вікна показують новий стан процесора ( регістрів, прапорців, оперативної пам’яті, стеку). Це дозволяє простежити за вірністю виконання програми.
У випадку виявленя помилок вам треба повернутись до першого етапу (реедагування), тобто виправити похідний файл, потім послідовно виконати етапи трансляції, компонування на налагоджування і так до тїєї пори доки ваша програма не буде працювати вірно.
Для більш докладного ознайомлення з роботою програм tasm.exe, tlink.exe, td.exe вам необхідно звернутись до відповідної документації.
ПІДГОТОВКА ДО РОБОТИ
Вивчіть короткі теоретичні відомості та рекомендовану літературу.
РОБОЧЕ ЗАВДАННЯ,
Для похідного текстового файлу, підготовленого під час виконання лабораторної роботи №1, виконайте трансляцію, компонування та налагоджування програми.
КОНТРОЛЬНІ ЗАПИТАННЯ
Які існують етапи створення асемблерної програми.
Як виконати трансляцію програми, що написана на Асемблері.
Які файли формуються на етапі трансляції
Що таке об’єктний файл.
Що таке файл листінгу.
Які помилки виявляються на етапі трансляції.
Як виконується компонування програми.
Який файл формується на етапі компонування.
Як перевірити вірність виконання умов роботи програми під керуванням MS DOS.
За допомогою якої програми можна налагодити вашу програму.
Які вікна ви бачите на екрані після запуску програми – налагоджувача.
Що таке трасування програми, як воно виконується.
ЛАБОРАТОРНА РОБОТА № 3
СОМ – ФАЙЛИ
Мета роботи: вивчити призначення та особливості СОМ – файлів, навчитися створювати асемблерні програми у вигляді СОМ – файлів.
КОРОТКІ ТЕОРЕТИЧНІ ВІДОМОСТІ
Програму, що буде виконуватись, можна створювати не тільки у вигляді EXE-файлу, але й у вигляді СОМ – файлу. Прикладом СОМ – файлу може бути COMMAND.COM. Програми у вигляді EXE-файлу та у вигляді СОМ файлу мають наступні відмінності:
Розмір програми. Програма у форматі EXE може мати у принципі будь який розмір. СОМ-програма обмежена розміром одного сегменту і не перевищує 64 Кбайт.
Форма представлення файлу на диску. СОМ-файл представлений на диску у вигляді абсолютного образу пам’яті, тобто так, як він виглядає у оперативній пам’яті. EXE-файл має спеціальний заголовок розміром 512 байт, де MS DOS зберігає свою службову інформацію.
Сегмент стеку. У EXE-програмі необхідно визначати сегмент стеку. У СОМ-програмі стек генерується автоматично. При цьому при створенні асемблерної програми, що буде перетворена у COM-файл сегмент стеку визначати не треба. Якщо максимального розміру сегменту (64К) достатньо для розміщення і програми і стеку, MS DOS встановлює регістр SP на кінець сегменту (FFFE). Це вершина стеку. Якщо програма займає весь сегмент і місця для стеку недостатньо, то MS DOS встановлює стек у кінці пам’яті, що доступна MS DOS.
Сегмент даних. В EXE-програмі звичайно визначається сегмент даних, і регістр DS ініціалізується адресою цього сегменту. У СОМ- програмі усі дані повинні розташовуватись в кодовому сегменті. Таким чином, у СОМ-програмі у вас буде тільки один сегмент – сегмент кодів.
5. Ініціалізація. На початку EXE-програми виконувся запис до стеку вмісту регістру DS, нуля та ініціалізація регістру DS. Тому що сегменти стеку і даних у СОМ-програмі відсутні, ці кроки виконувати не треба. Після завантажування СОМ-програми у оперативну пам’ять, усі сегментні регістри містять адресу префіксу програмного сегменту (PSP) – 256-байтового (100(16)) блоку, що MS DOS резервує у оперативній пам’яті перед EXE- та СОМ-програмами. Тому що регістр CS встановлено на початок PSP, треба встановити пару регістрів CS:IP на початок програми. Це виконується директивою ORG 100h, яка вказується після директиви SEGMENT. Ця директива встановлює вказівник команд IP (зміщення відносно CS) в значення 100h.
Створення СОМ-файлу. Для створення СОМ файлу необхідно під час компонування вказати опцію /t. Командний рядок для компонування буде мати вигляд:
[шлях]tlink/t objfiles,[comfiles],[mapfiles],[libfiles],[defiles]
При цьому файл для виконання по умовчуванню буде мати розширення .com.
Перетворимо програму з лабораторної роботи №1 у вигляд, необхідний для створення СОМ-програми.
SEGCOD SEGMENT PARA 'CODE'
ASSUME CS:SEGCOD, SS:SEGCOD, DS:SEGCOD, ES:SEGCOD
ORG 100H
BEGIN: JMP MAIN
A DB 5 ;ці дані не використовуються в наведеній програмі
B DW 300 ; і наведені тільки для ілюстрації визначеня даних
;у СОМ-програмі
MAIN PROC NEAR
SUB BX,BX ;обнулюйте регістр BX
ADD BX,10 ;додати до вмісту BX 10
MOV CX,20 ;занести в CX 20
ADD BX,CX ;додати CX к BX
SUB BX,CX ;відняти CX из BX
RET
MAIN ENDP
SEGCOD ENDS
END BEGIN
Зверніть увагу, які були проведені зміни:
Сегмент стеку і сегмент даних відсутні.
Директива ASSUME ініціалізує усі сегментні регістри адресою початку сегменту кодів.
Директива ORG 100h встановлює вказівник команд на початок вашої програми (після PSP).
Команда JMP (безумовний перехід) використовується для обходу ділянки даних.
Після мітки місця входу у вашупрграму (BEGIN) стоять дві крапки. Їх призначення буде розглянуте у лабораторній роботі № 5.
Процедура MAIN задана з параметром NEAR (внутрішня), тому що її початок вже не є місцем входу у програму.
ПІДГОТОВКА ДО РОБОТИ
Вивчити короткі теоретичні відомості та рекомендовану літературу.
Перетворити похідний текст програми з лабораторної роботи №1 для створення СОМ-файлу.
РОБОЧЕ ЗАВДАННЯ
1. Набрати підготовлену програму, странслювати її, скомпонувати, налагодити.
2. Запустити програму на виконання. Перевірити, чи виконується повернення до MS DOS.
КОНТРОЛЬНІ ЗАПИТАННЯ
Скільки сегментів у вашій програмі.
Де у вашій програмі розташовується стек.
Яке значення містить регістр SP.
Навіщо необхідна директива ORG 100h.
У чому різниця в представлені exe- та com-прогрми на диску.
Сформулюйте основні відмінності exe- і com-програми.
ЛАБОРАТОРНА РОБОТА № 4
ВИЗНАЧЕННЯ ДАНИХ
Мета роботи: ознайомитись з засобами визначення констант та робочих ділянок у асемблерній програмі.
КОРОТКІ ТЕОРЕТИЧНІ ВІДОМОСТІ
В лабораторній роботі № 1 ми задавали небхідні нам дані безпосередньо у команді. Напрклад, ми писали
MOV AX,25
У цьому випадку число 25 стає часткою об’єктного коду.
Такий засіб визначення даних є доцільним, якщо потрібне число (в нашому випадку 25) зустрічається у вашій програмі один раз. Якщо ж потрібне число зустрічається у програмі декілька разів, то це приводидь до невиправданих витрат оперативної пам’яті. Пам’ять під ваше число буде виділятись стільки разів, скільки ви його вказуєте у командах. Крім того, якщо виникне необхідність змінити це число, вам доведеться розшуккувати його по всій програмі. Тут велика ймовірність помилки. Більш доцільним є запис потрібного числа у чарунку оперативної пам’яті, присвоєння цій чарунці символьного імені, а потім звертання до цього чиса за іменем. В цьому разі пам’ять під число буде виділятись один раз і за необхідності змінення цього числа виконати заміну можна буде тільки в одному місці.
В лабораторній роботі № 1 ми використовували для збереження результатів обчислювань (проміжних та остаточних) регістри загального призначення. Такий засіб є найбільш швидкодіючим. Але у регістрах можна зберігати тільки обмежену кількість інформації. Замість використання регістрів для збереження результатів можна виділяти у оперативній пам’яті так звані робочі ділянки – визначену кількість чарунок оперативної пам’яті, яким можна присвоїти імена і у командах звертатися до них за іменами.
В Асемблері для опису похідних даних та виділення робочих ділянок у оперативній пам’яті служать директиви ВИЗНАЧЕННЯ ДАНИХ.
За допомогою цих директив ви можете задавати КОНСТАНТИ (числа, значення яких визначається у похідному тексті вашої програми і потім не змінюються) і ЗМІННІ (робочі ділянки визначеної довжини, значення яких може змінюватись у процесі роботи вашої програми).
Основний формат визначеня даних
[ім’я] Dn вираз
Ім’я елементу даних не обов’язкове, але, якщо ви хочете у програмі звертатись до цього елементу, вам необхідно це ім’я вкзати. Ім’я створюється за правилами символьних імен (ідентифікаторів), які були наведені в лабораторній роботі № 1 під час опису міток.
Директиви визначення даних (Dn) можуть використовуватись наступні: DB (байт), DW (слово), DD (подвійне слово), DQ (чотири слова) та DT (десять байт).
У полі “вираз” може знаходитись:
Константа.
Наприклад:
ABC DB 25
Послідовність констант.
Наприклад:
BCD DB 1,2,3,4,5
Константи у послідовності повинні розділятися комами. Кількість констант у послідовності обмежується тільки довжиною рядка. Ім’я (у нашому прикладі BCD) вказує на першу константу у послідовності (в нашому прикладі – “1”). До другої константи (“2”) можна звернутися за ім’ям BCD+1 (тому що перша константа займає один байт), до третьої - BCD+2 і так далі. Якби ми використовували в цьому прикладі директиву DW, то до BCD необхідно було би додавати відповідно 2, 4 і так далі.
В якості виразу може стояти знак питання (“?”) для навизначенного значення змінної:
CDE DB (?)
В цьому випадку значення змінній CDE не присвоюється.
Вираз припускає повторення константи або змінної у наступному вигляді:
[ім‘я] Dn кількість_повторень DUP(вираз)
наприклад:
DEF DB 10 DUP(?)
Оператор повторення (DUP) може бути вкладеним, наприклад:
EFH DB 10 DUP(4 DUP(2))
У цьому випадку будуть згенеровані 4 копії константи “2”, а потім це значення повториться 10 разів. У результаті буде сформована послідовність з сорока двійок.
Розрізняйте ініціалізовані та неініціалізовані дані. У разі неініціалізованих даних (у полі “вираз” стоїть знак питання – “?”) в оперативній пам’яті віділяється чарунка пам’яті заданого розміру і ніяке значення їй не присвоюється. Для ініціалізованих даних (усі інші значення у полі “вираз”) також віділяється чарунка пам’яті заданого розміру і їй присвоюється вказане значення.
Константа, що задається у полі “вмраз” може бути символьним рядком або числовою константою.
СИМВОЛЬНИЙ РЯДОК використовується для представлення тексту. Він береться у апострофи або лапки, напрклад:
‘Лабораторна робота № 4’
або
“Лабораторна робота № 4”
Асемблер переводить кожен символ символьного рядку у відповідний ASCII-код. Символьний рядок визначається директивою DB, у який вказуються символи у нормальній послідовності зліва направо.
NAME1 DB 'Лабораторная работа N 5'
ЧИСЛОВІ КОНСТАНТИ використовуються для арифметичних значень та для адрес пам’яті. Числова константа вказується у директиві визначення даних безпосередньо, без лапок або апострофів. Асемблер перетворює усі числові константи у двійкові (в листінгу наводиться шістнадцатькове представлення двійкових констант). Під час роботи з налагоджувачем зверніть увагу, що числові константи розміром більше байту записуються у оперативну пам’ять у зворотній послідовності байтів – справо наліво (за більш молодшею адресою – більш молодший байт). Так наприклад, шістнадцятькову константу розміром в слово 1234h ви побачите записаною у пам’яті як 34 12.
Числові константи можуть задаватись у наступних форматах:
ДЕСЯТЬКОВИЙ ФОРМАТ припускає десятькові цифри від 0 до 9 та визначається останньою буквою D. Десятьковий формат приймається по умовчуванню, тобто, якщо ніяка літера після числа не вказана, то це десятьковий формат. Десятьковий формат перетворюється Асемблером у двійковий, який у листінгу записується у шістнадцатьковому форматі.
Наприклад:
NAME2 DB 12D
або
NAME2 DB 12
ШІСТНАДЦАТЬКОВИЙ ФОРМАТ припускає цифри від 0 до 9 та літери від А до F і визначається у кінці буквою H. Тому що Асемблер вважає, що з літери починаються символьні імена, то першим знаком шістнадцатькової константи обов’язково повинна бути цифра від 0 до 9. Якщо вам необхідно, наприклад, задати константу A0C1H, її треба записати у вигляді 0A0C1H.
Приклад визначення шістнадцатькової константи.
NAME3 DB 0CH
ДВІЙКОВИЙ ФОРМАТ припускає цифри 0 та 1 і визначається у кінці літерою В.
NAME4 DB 11001010B
ВІСІМКОВИЙ ФОРМАТ припускає цифри від 0 до 7 і визначається останньою літерою Q або O. У наш час вісімковий формат використовується рідко.
NAME5 DB 10Q
Є ще дісятьковий формат з крапкою, що плаває, але він використовується для визначення даних для математичного сопроцесора.
Під час запису шістнадцатькових констант та літер, що визначають формат числа, можна використовувати як великі так і маленікі букви.
При завданні символьних рядків та числових констант слід пам’ятати, що, наприклад, ‘14’ та 14 є дві різні константи. Перша перетворюється у два байта ASCII-кода, відповідні символам 1 та 4. Друга пертворюється у двійкове число 1110, у шістнадцатьковому представленні – 0Е.
ДИРЕКТИВА ВИЗНАЧЕННЯ БАЙТА (DB) – визначає байт. Символьний вираз у директиві DB може містити символьний рядок будь якої довжини (обмежується тільки довжиною асемблерного рядка). Числова константа у директиві DB може містити одну або більше однобайтових констант. Один байт у листінгу представляється двома шістнадцатьковими цифрами. Найбільше додатне шістнадцатькове число у одному байті - 7F, усі більші числа від 80 до FF представляють від’ємні значення. У десятьковому форматі ці межі визначаються числами від +127 до –128.
Приклади використання директиви визначення байта:
NAME6 DB ?
NAME7 DB 'Завдання N 5'
NAME8 DB 12H
NAME9 DB 112
NAME10 DB 01101100B
NAME11 DB 10,11,12,13,14
NAME12 DB 2 DUP(10)
ДИРЕКТИВА ВИЗНАЧЕННЯ СЛОВА (DW) визначає константи та змінні, що мають довжину одне слово – два байти. Симольний вираз у DW обмежен двома символами. Числовий вираз у DW може містити одну або більш двобайтових констант.
Два байти представляються чотирма шістнадцатьковими цифрами. Найбільше додатне шістнадцатькове число у двох байтах - 7FFF, числа від 8000 до FFFF представляють від’ємні значення. У десятьковому коді ці межі визначаються числами +32767 і -32768.
У полі “вираз” директиви DW може бути підставлене ім’я константи або змінної, визначеної раніше, наприклад
NAME13 DW NAME8
У цьому випадку під іменем NAME13 буде згенерована константа, що дорівнює адресі (зміщенню) константи NAME8. Це так званна адресова константа.
Приклади використання директиви визначення слова:
NAME14 DW ?
NAME15 DW 23,64
NAME16 DW '12'
NAME17 DW NAME15
NAME18 DW 0110111100001010B
NAME19 DW 1F0BH
ДИРЕКТИВА ВИЗНАЧЕННЯ ПОДВІЙНОГО СЛОВА (DD) визначає елементи, які мають довжину два слова – чотири байти. Розмір числових констант, що використовуються, не повинен перевищувати чотирьох байт (вісім шістнадцатькових цифр). Найбільше додатне шістнадцатькове число, яке може бути використане у директиві DD, - 7FFFFFFF. Діапазон від’ємних чисел від 80000000 до FFFFFFFF. У десятьковому коді діапазон припустимих чисел у цій директиві від +2147483647 до -2147483648. Символьний вираз у директиві DD обмежен двома символами. Асемблер перетворює їх у ASCII-код і вирівнює їх справа, як показано у наведеному нижче рядку листінга.
0010 00 00 32 33 NAME20 DD '23'
Приклади використання директиви визначення подвійного слова:
NAME21 DD 1F00FFFFH
NAME22 DD 'AB'
NAME23 DD ?
NAME24 DD 45,47,49
NAME25 DD NAME23-NAME21
ДИРЕКТИВА ВИЗНАЧЕННЯ ЧОТИРЬОХ СЛІВ (DQ) визначає елементи, що мають довжину чотири слова (вісім байт). Числові константи, що використовуються в директиві не повинні перевищувати розмір вісім байт. Обробка Асемблером символьних рядків у директиві DQ така, як і у директивах DW і DD.
Приклади визначення директиви визначення чотирьох слів:
NAME26 DQ 245H
NAME27 DQ 100
ДИРЕКТИВА ВИЗНАЧЕННЯ ДЕСЯТЬОХ БАЙТ (DT) визначає елементи даних, що мають довжину десять байт. Призначена для визначення так званих “спакованих десятькових” числових значень, в яких у кожному байті кожна тетрада містить двійково – десятьковий код відповідної десятькової цифри. При цьому код більш старшої цифри знаходиться в старшій тетраді.
Приклади використання директиви визначення десятьох байт:
NAME28 DT ?
NAME29 DT '23'
Більш докладно про можливі значення поля “вираз” для кожної директиви звертайтесь до документації на відповідну версію мови Асемблер.
БЕЗПОСЕРЕДНІ ОПЕРАНДИ
Константа, що задається безпосередньо у команді, зветься безпосереднім операндом. Значення безпосереднього операнда входить у об’єктний код, що генерується для цієї команди. Припустима довжина безпосереднього операнда залежить від довжини першого операнда у команді. Наприклад, у команді
MOV AL, XX
безпосередній операнд, який ми визначили як ХХ, повинен мати довжину один байт, тому що регістр AL є однобайтовим регістром.
У команді
MOV AX, XX
безпосередній операнд може мати довжину слово (два байти).
При невиконанні цих правил транслятор сгенерує повідомлення про помилку.
ДИРЕКТИВА EQU
Директива EQU присвоює певне значення символьному імені (ідентіфікатору). Наприклад, якщо ви задали
KOL EQU 10
то кожен раз, коли транслятор в тексті вашої програми зустріне ідентифікатор KOL, він замінить його на значення 10. Так транслятор перетворить директиву
NAME30 DW KOL DUP(?)
в директиву
NAME30 DW 10 DUP(?)
Ім’я, що пов’язане з деяким значенням за допомогою директиви EQU, може бути використане в якості операнда у команді. Наприклад,
MOV AX, KOL
Транслятор замінить ім’я KOL на значення 10, створюючи безпосередній операнд, так, якби у команді було задане
MOV AX, 10
У відмінності від директив визначення даних директива EQU не виділяє місце під константу у оперативній пам’яті, а тільки вказує транслятору на необхідність заміни ідентифікатора, що стоїть у лівій частині директиви, на значення, що знаходиться у правій частині директиви. За допомогою директиви EQU можно присвоїти ідентифікатору як символьні, так і числові значення.
ПІДГОТОВКА ДО РОБОТИ
Вивчити короткі теоретичні відомості та рекомендовану літературу.
Написати текст програми, що відповідає вашому варіанту. Ваша програма повинна мати тільки сегмент даних і закінчуватись директивою END.
РОБОЧЕ ЗАВДАННЯ,
1. Набрати підготовлену програму, странслювати її. Під час трансляції створити листінг. Об’єктний файл не створювати. Вивчити одержаний листінг. Перевірити, який вигляд у об’єктному мають різні константи.
Змінити текст лабораторної роботи № 1, замінивши безпосердні операнди, що використані у програмі, на константи, визначені у сегменті даних. Странслювати змінену програму, скомпонувати її та перевірити налагоджувачем.
КОНТРОЛЬНІ ЗАПИТАННЯ
У чому різниця між ініціалізованими та неініціалізованими даними.
В чому відмінність представлення у пам’яті двох констант NAMEA DB 42 та NAMEB DB '42'.
Яке значення підставиться замість імені NAMED у виразі
NAMEC DW 20
NAMED DW NAMEC
4. У сегменті даних наведен запис
NAMEE DW 1, 2, 3, 4
Як звернутися у програмі до другої константи цього рядка.
5. У якій системі счислення задаються числові константи.
ЛАБОРАТОРНА РОБОТА № 5
ОРГАНІЗАЦІЯ ПРОЦЕСІВ, ЩО РОЗГАЛУЖУЮТЬСЯ
Мета роботи: ознайомитись з механізмом організації процесів, що розгалужуються та командами Асемблера, що використовуються для цієї мети.
КОРОТКІ ТЕОРЕТИЧНІ ВІДОМОСТІ
У лабораторній роботі № 1 ви створили програму, команди якої виконуються послідовно так, як ви їх записали. Така програма є лінійним процесом. У цій роботі ми розберемося, як організувати процес, що розгалужується, - програму, послідовність виконання команд якої залежіть від результатів її роботи. Прикладом процесу, що рогалужується може бути найпростійший алгоритм:
Є два числа А та В.
Якщо A>B, обчислити C=A+B.
У протилежному випадку, тобто, якщо A<=B, обчислити C=B-A.
Для організації процесів, що розгалужуються вам необхідно мати команди, яки можуть передавати керування за адресою команди, яка не знаходиться безпосередньо за тією командою, що зараз виконується. Передача керування може здійснюватись вперед, для виконання нової групи команд, або назад, для повторення команд, що вже виконувались.
Є три типи переходів (передачі керування).
Перехід типу SHORT (короткий) передає керування у межі змінення адреси на один байт (-128 - +127).
Перехід типу NEAR (ближній або внутрішньосегментний) передає керування у межах одного сегменту.
Перехід типу FAR (далекий або міжсегментний) передає керування у другий сегмент.
Під час переходів SHORT та NEAR змінюється тільки вміст вказівника команд IP. Під час FAR-переходів змінюється вміст вказівника команд IP та кодового сегментного регістра CS.
Роздивимося, які є переходи для передачі керування у програмі.
Безумовний перехід
Безумовний перехід виконує передачу керування за будь яких обставин.
Для виконання безумовного переходу у Асемблері використовується команда JMP.
Наприклад, наведена нижче програма виконує додавання чисел натурального ряду.
codseg segment
assume cs:codseg, ds:codseg, ss: codseg
org 100h
main proc near
sub ax, ax ; в ax накопичується сума
mov bx, 1 ; в bx формуються числа натурального ряду
a20: add ax, bx
add bx, 1
jmp a20
ret
main endp
codseg ends
end main
Команда JMB A20 передає керування команді з міткою А20. Дві крапки після мітки значать, що тип мітки NEAR, тобто керування на цю мітку може передаватись тільки в межах сегменту кодів. Зверніть увагу, при вказуванні мітки у команді JMB дві крапки після імені мітки не ставляться.
Мітку можна записувати у одному рядку з командою
A20: ADD AX, BX
або в окремому рядку.
A20:
ADD AX, BX
Цей цикл не має виходу і приводить к нескінченному виконанню – такі цикли звичайно не використовуються.
Роздивимось листінг цієї програми.
Turbo Assembler Version 4.0 08/07/03 21:23:38 Page 1
v_pr.asm
1 0000 codseg segment
2 assume cs:codseg, ds:codseg, ss: codseg
3 org 100h
4 0100 main proc near
5 0100 2B C0 sub ax, ax ; в ax накопичується сума
6 0102 BB 0001 mov bx, 1 ; в bx формуються числа натурального ряда
7 0105 03 C3 a20: add ax, bx
8 0107 83 C3 01 add bx, 1
9 010A EB F9 jmp a20
10 010C C3 ret
11 010D main endp
12 010D codseg ends
end main
У нашому прикладі операнд команди JMB (мітка А20) відповідає семи байтам від команди, наступної за JMP, до команди, на яку ми передаємо керування. В цьому можна впевнитись, дивлячись на об’єктний код команди EBF9. Тут EB – машиний код для короткого перходу JMP , а F9 – від’ємне значення зміщення (-7). Команда JMP додає F7 до командного вказівника (IP), який містить адресу команди, наступної за JMP (010С). В результаті додавання буде отримана адреса переходу (0106). Оперенд команди JMP для переходу уперед буде мати додатне значення.
Команда JMB для переходу у межах від –128 до +127 байт має тип SHORT. Асемблер генерує у цьому разі однобайтовий операнд у межах від 00 до FF. Команда JMP для переходу, перевищуючого ці межи, отримує тип NEAR,, для якого генерується інший машиний код та двухбайтовий операнд. Під час передачі керування назад
A50: ....
....
JMP A50
транслятор, коли дійде до команди JMP, вже знає “відстань” між командою JMP та міткою А50 і згенерує вірний код команди (типу SHORT або NEAR) в залежності від реальної відстані.
Під час передачі керування уперед
JMP A90
........
A90:
транслятор, коли дійде до команди JMP, не знає типу переходу (NEAR чи SHORT) і автоматично згенерує команду JMP для переходу типу NEAR. Для того, щоб вказати транслятору на необхідність генерації команди для короткого переходу (SHORT), слід використати оператор SHORT:
JMP SHORT A90
.....
A90:
Це дозволить згенерувати більш оптимальний код команди.