Автор работы: Пользователь скрыл имя, 15 Марта 2013 в 19:59, доклад
Після створення процесора 8086 фірма Intel розробила більш досконалі процесори об’єднані під назвою I 80x86, така назва означає, що всі команди мікропроцесора, які виконуються на молодших моделях обов’язково виконуються на старше, отже все ПЗ, які розроблені для процесора 8086 успішно будуть працювати і на останніх моделях 80486 і Pentium. Ми будемо розглядати процесори з точки зору програміста. Не дивлячись на різноманітність моделей процесорів, найбільш важливим з точки зору біології програмування є 8086 як базова модель і 80386 , як перший процесор фірми Intel, який в повному об’ємі реалізував принцип багатозадачності.
0 – 9
Отже діапазон представлення чисел 0 – 9. Значення старшоWптетради не суттєве:
х |
х |
х |
Х |
1 |
0 |
0 |
1 |
9
Для зручності відладки в старшCптетраду записують 0:
0 0 0 0
Х |
х |
х |
Х |
1 |
0 |
0 |
1 |
0 –9
Зворотне
представлення просте: молодш0птетрада,
якщо вона знаходиться у межах
представлення чисел 0 – 9 визначає
відповідне двійково-десяткове
Лекція за 24.09.98.
Приклад структури програми на мові асемблера (ш0блон).
Приведемо основні директиви, які використовуються і програмі на мові асемблера. Тепер використовуються спрощені способи опису сегментів. Сегменти – це частини програми (сегменти даних). Текст програми можна набирати великими або малими буквами, програма асемблера самостійно переводить текст у верхній регістр. Обов’язково у тексті програми писати коментарі. Текст який стоїть за символом “;” є коментарем, він ігнорується при асемблюванні програми. Директива яка як правило йде з початку програми dosseg описує розташування сегментів. Директива mode small – директива опису моделі пам’яті, наприклад в цьому випадку говорять, що модель пам’яті типу small, тобто є один сегмент коду і один сегмент коду і один сегмент даних. Директива .stack 100 – директива, яка задає початок сегменту стеку. В стеці зберігаються тимчасові змінні і адреси повернення з підпрограми або переривань. Як правило будь-яка програма має сегмент стеку. В даному випадку такий запис директиви .stack 100 позначає, що стек має довжину 100байтів. Точну величину стеку визначає число викликів підпрограм та системних ф-цій, стек треба збільшувати. В кінцевому підсумку розмір стеку підбирають експериментально, коли програма вже написана і відлагоджена. Директива .data – директива початку сегменту ініціалізованих даних, після цього рядка поміщають змінні значення яких відоме (ініціалізовані змінні). Директива .data ? – директива початку сегменту неініціалізованих даних. Директива .code – початок сегменту коду. Сегмент коду – це частина коду яка містить команди МП, власне це й є сама програма. В деяких випадках в цей сегмент можна поміщати не тільки команди, а й дані. Наприклад у підпрограмах обробки переривань. Директива .startup – точка початку виконання програми. З наступного після даного рядка починається виконання програми після її завантаження в пам’ять, ця директива повинн0пбути обов’язково всередині сегмента коду, але не обов’язково н0пйого початку. Директива .exit 0. – це директива закінчення програми при виконанні цього рядка управління буде передане ОС. Таких директив в програмі може бути кілька, число після директиви може приймати кілька значень, це число після закінчення програми присвоюється змінній ОС з назвою ERRORLEVEL, ця змінна використовується в командних файлах. Є спеціальні команди для роботи з цією змінною. Використовуючи різні числа можна повідомляти ОС, яка причина закінчення програми. Директиви початку і закінчення програми є по суті макровизначеними, вони визначають необхідний код який автоматично додається на початок і кінець програми. Цей код можна подивитись у файлі лістингу після асемблювання. End – директива закінчення тексту програми на мові асемблера. Рядки які розміщені після директиви end можна писати коментар в довільній формі.
Команди мови асемблера.
Мінімальна одиниця тексту програми на мові асемблера – це рядок. Асемблер проглядає програму порядкові зверху в низ, кожний рядок закінчується символом переведення рядка Vпйого довжина в більшості випадків не може перевищувати 255 символів, однак зручно обмежувати довжину рядка широкою екрану (80 символів). При необхідності вводити в програмі довгі рядки їх можна об’єднувати, в кінець рядка при цьому потрібно включати символ \.
Рядок 1 \
Рядок 2 Рядок 1 Рядок 2.
В текст програми можна вставляти порожні рядки, які складаються тільки із розділювачів. В мові асемблера розділювачами служать символи пропуску та горизонтальна табуляція. При допомозі пустих рядків зручно розділяти логічні частини програми. Рядок може складатись тільки із коментарів, в такому випадку перший символ рядка обов’язково ;. В кожному рядку може розміщуватись або команда мікропроцесора, яка записана у мнемонічному (словом) вигляді, або директива, директиви інакше називають псевдооператорами. Команда мікропроцесора – це інструкція яку мікропроцесор буде виконувати в процесі виконання програми. Асемблер переводить рядки з мнемоніками (буквеними записами команд) у послідовності байт, які безпосередньо може виконувати процесор. Директиви служать для визначення даних, які використовуються в програмі і для управління процесом асемблювання. Рядок у програмі на мові асемблера може складатися з 4 полів:
Обов’язковим є тільки поле оператора або псевдооператора, всі решту полів можуть бути відсутні. Мітка є спрощеною мнемонічною формою запису адреси команди в сегменті коду. Так саме ім’я є спрощеною формою запису вмісту деякої переважно в сегменті даних. Отже рядки в програмі записуються в такому загальному вигляді:
[< мітка >]: < команда > < операнди >; коментарі
< ім’я > <директива < операнди >; коментарі
Потрібно звернути увагу на відсутність “:” після імені. Поля в рядках мови асемблера розділяються між собою на крайній мірі одним пропуском. Розглянемо поля детальніше. Поле мітки. При визначенні в програмі мітки або імені змінної можна використовувати букви латинського алфавіту великі або малі, а також символи :? _ @ $. Максимальна к-сть символів з яких може складатись мітка або ім’я 255, але відрізняються мітки та імена по перших 32символах. Доцільно в програмі використовувати осмислені імена. Зручно і програмі для швидкого розпізнавання міток від імені починати всі мітки з букви L і записувати їх тільки великими буквами. При записі імен змінних зручно використовувати префікс, який означає тип змінної, наприклад : skp_byte. При програмуванні з використанням асемблера masm, або tasm можна використовувати будь-яке число локальних міток @@. Для переходу до таких міток треба використовувати зарезервовані слова: @F – forward; @B – backward. Перш0п@F – це перехід до наступної мітки, @B – це перехід до попередньої мітки. Мітка або ім’я змінної не повиннVпбути зарезервованим словом.
Поле операндів.
Поле операндів залежить від попереднього поля.
Поле коментарів.
Структура програми на мові asm.
При роботі будь-якої програми в будь-який момент часу можна виділяти декілька ділянок пам’яті з якими працює процесор. Використання сегментів є особливістю процесорів х86. Воно переслідує таку мету:ами.
За вання сегментів є спробою заха вити незв’язані ділянки пам’яті в програмі. Допускалось, що для того, щоб визначити адресу деякої комірки пам’яті потрібно знати дві складові цієї адреси: адресу початкового сегменту та адресу зміщення комірки пам’яті від початку сегменту. Адреси початків сегментів знаходяться у відповідних сегментах регістрах CS, DS, SS, ES – змінюючи вміст цих регістрів можна дістати доступ до тих чи інших ділянок пам’яті, тому такий запис легко зламати. Тому в процесорі 386 в захащеному режимі роботи адреси початків сегментів, їх довжини та права доступу зберігаються в спеціальних системних одиницях. В сегментних регістрах зберігають тільки індекс структури всередині таблиці. Це дозволило ізолювати сегменти та обмежило доступ до них з програми. Адже для доступу потрібно знати не тільки вміст сегменту регістру, але й тієї структури на яку він вказує. Така зміна можлива тільки при використанні привілейованих команд, що виконується тільки в певних умовах, можуть виконуватись в ОС, але не можуть використовуватись в програмах користувача. Паралельно з цим збільшення розміру сегментів:амід 64Кб для 86, до 4Гб для 486. Крім того програма буде виконуватись, якщо змінити адресу початку сегменту. Це означає, що в пам’яті він буде перенесений в інше місце. При цьому відносне зміщення в сегменті не можна зміщувати. Це дозволить переносити програму в пам’яті навіть під час її виконання. Використання сегментації пам’яті дозволяє різко збільшити розміри пам’яті, яку можна використати. Так, в захащеному режимі максимально можливий об’єм пам’яті, яку можна адресувати – 64Тб. Це віртуальна пам’ять. Тоді як фізичний об’єм пам’яті складає 4Гб. В деяких випадках використовувати сегментацію недоцільно. Тому в старших моделях можна працювати із сегментами довжиною до 4Гб. Це означає, що вся фізична пам’ять розглядається як один сегмент. Повністю усі переваги сегментації пам’яті проявляється в захащеному режимі роботи. В реальному режимі роботи оперує з 4-ма сегментами:а
Для процесорів 386 з’явились ще 2 сегменти додаткових даних. Ці сегменти в пам’яті можуть розташиняватись як завгодно по відношенню один до одного. Ніяких обмежень на їх розташування немає. Сегменти можуть починатись з однієї адреси, тобто можуть перекриватись. Вони можуть розташиняватись в пам’яті без перекривання, або між ними можуть бути проміжки.
Для визначення адреси наступної
команди після виконання попере
В початковій версії необхідно було відмітити точку входу в програму деякою міткою. Ім’я цієї мітки потім вказувалось в директиві end. Це було ознакою закінчення файлу з програмою. У сучасних асемблерах для визначення точки входу в програму використовується директива startup. Вона записується в сегменті коду, це спрощує запис і, крім цього, автоматично ініціалізує значення сегментних регістрів. В старих версіях це потрібно було робити вручну.
Для закінчення програми потрібно було скористяватись стандартною директивою. Вона робить відповідний виклик автоматично. Якщо програму необхідно закінчити спеціальним чином, наприклад встановити резидентну програму, то користяватись цією директивою не можна. В таких випадках потрібно явно викликати відповідну функцію операційної системи.
В усіх інших сегментах виділяється місце для змінних, що використовуються в програмі. Поділ сегментів на сегменти даних, стеку та додаткових даних зумовлена тим, що змінні, які тут визначені мають різні властивості. Змінні в програмі можна розбити на 2 великі групи:
Використовується для збереження змінних, що визначає програміст. Як правило це робиться при допомозі псевдооператорів виділення пам’яті. Для визначення адреси початку сегменту використовується регістр DS. Для визначення другої компоненти адреси (відповідного зміщення всередині сегменту) використовується кілька способів адресації. Зауважимо, що способів визначення адреси змінної набагато більше ніж способів визначення адреси команди. В мові асемблер є засоби для явного розділ. збереження змінних. Ці змінні можуть мати або не мати початкових значень, а також можуть бути змінними константами. Розділяти ці типи змінних не обов’язково. Усіх їх можна зберігати в сегменті даних.
Змінні, початкові значення яких відоме як правило записуються в сегменті, що починається директивою data. До цих змінних відносяться також ті, початкові значення яких відоме і в процесі роботи вони не повиннVпмінятись.
Неініціалізовані змінні записуються в сегмент який починається директивою data.
Сегмент стеку використовується для збереження тимчасових даних для яких недоцільно виділяти змінні. Адреса початку цього сегменту розміщується в регістрі SS, а зміщення відносно початку в регістрі SP. Для визначення сегменту стеку використовується директива stack. Цей сегмент відрізняється від сегменту даних і коду. В сегменті даних і коду можна явно адресувати б-я комірку пам’яті. Тут значення регістру при виконанні команд. В кожний момент часу пара цих регістрів SS і SP вказує на так звану вершину стеку. Сюди можна записати або прочитати значення. Стек організований за правилом: перший записаний, останній прочитаний. Тому у програмі команди запису і зчитування зі стеку потрібно використовувати попарно. Стек переважно використовується для тимчасового зберігання адреси повернення з програми або перервань. Ще одне ми.
За вання стеку – при його допомозі можна передавати аргументи підпрограмам і організовувати локальні змінні.