Лабораторна робота №7
Вивчення команд роботи з регістрами і пам’яттю МП х8086
Мета роботи: Вивчити основні способи адресації.
Короткі теоретичні відомості
Способи адресації.
Способом, або режимом адресації називають процедуру знаходження операнда для виконуваної команди. Якщо команда використовує два операнди, то для кожного з них повинен бути заданий спосіб адресації, причому режими адресації першого і другого операнда можуть, як збігатися, так і відрізнятися. Операнди команди можуть перебувати в різних місцях: безпосередньо у складі коду команди, в будь-якому регістрі, в комірці пам'яті; у останньому випадку існує кілька можливостей вказівки його адреси. Строго кажучи, способи адресації є елементом архітектури процесора, відображаючи закладені в ньому можливості пошуку операндів. З іншого боку, різні способи адресації певним чином позначаються в мові асемблера і є розділом мови.
У програмах, написаних на мові асемблера термін "операнд" застосуємо до позначення тих фізичних об'єктів, з якими має справу процесор при виконанні машинної команди і, кажучи про операнди команд мови, розуміють насправді операнди машинних команд. По відношенню до команд асемблера використовується термін "параметри".
В архітектурі сучасних 32-розрядних процесорів Intel передбачені досить витончені способи адресації; в МП 86 способів адресації менше. Ми в цій лабораторній роботі ознайомимося з режимами адресації, використовувані в МП 86.
Розрізняють такі режими адресації:
1. регістровий;
2. безпосередній;
3. прямий;
4. регістровий непрямий (базовий або індексний);
5. регістровий непрямий зі зміщенням (базовий або індексний);
6. базово-індексний;
7. базовий індексний зі зміщенням.
1.1 Регістровий режим
Значення операнда-джерела попередньо запам'ятовується в одному з вбудованих регістрів мікропроцесора.
Сам регистр становится эффективным адресом. Операнд (байт или слово) находится в регистре. Этот способ применим ко всем программно-адресуемым регистрам процессора:
Сам регістр стає ефективним адресом. Операнд (байт або слово) знаходиться в регістрі. Цей спосіб застосовний до всіх програмно-адресуючих регістрів процесора:
inc CX | ; Збільшення на 1 вмісту CX |
push DS | ; Сегментна адреса зберігається в стеку |
xchg BX,BP | ; Регістри BX і BP обмінюються вмістом |
mov ES,AX | ; Вміст AX пересилається в ES |
1.2 Безпосередній режим
Безпосередня адресація. Операнд (байт або слово) указується в команді і після трансляції поступає в код команди; він може мати любе значення (число, адреса, код ASCII), а також представлений у вигляді символічного позначення.
mov АН, 40h | ; Число 40h завантажується в АН |
mov AL,'*' | ; Код ASCII символу "*' завантажується в AL |
int 21h | ; Команда переривання с аргументом 21h |
limit equ 528 | ; Число 528 получає позначення limit |
mov CX,limit | ; Число, позначене limit, завантажується в СХ |
Команда mov, використана в останньому реченні, має два операнди; перший операнд визначається за допомогою реєстрової адресації, другий - за допомогою безпосередньої.
Важливим застосуванням безпосередньої адресації є пересилання відносних адрес (зсувів), для цього використовується описувач offset (зсув):; Сегмент данных
string db “Privet"; Рядок символів
; Сегмент команд
mov DX,offset string; Адрес рядка засилаєтся в DX
1.3 Прямий режим.
Адресується пам'ять; адрес комірки пам'яті (слова або байта) указується в команді (зазвичай в символічній формі) і поступає в код команди:
; Сегмент даних
meml dw 0; Слово пам’яті містить 0
mem2 db 230; Байт пам’яті містить 230
; Сегмент команд
inc meml; Вміст слова meml збільшується на 1
mov DX, meml; Вміст слова з ім'ям menu завантажується в DX
mov AL,mem2; Вміст байта з ім'ям mem2 завантажується в АL
Порівнюючи цей приклад з попереднім, ми бачимо, що вказівка в команді імені елементу пам'яті означає, що операндом є вміст цього осередку; вказівка імені осередку з описувачем offset - що операндом є адреса комірки.
Пряма адресація пам'яті на першій погляд, здається, простою і наглядною. Якщо ми хочемо звернутися, наприклад, до комірки meml, ми просто вказуємо її ім'я в програмі. У дійсності, однак, справа йде складніше. Адреса будь-якої комірки складається з двох компонентів: сегментної адреси і зсуву. Позначення meml і mem2 в попередньому прикладі, є зсувами. Сегментні ж адреси зберігаються в сегментних регістрах. Однак сегментних регістрів чотири: DS, ES, CS і SS. Яким чином процесор дізнається, з якого регістра узяти сегментну адресу, і як повідомити йому про це в програмі?
Процесор розрізняє групу кодів, що носять назву префіксів. Є декілька груп префіксів: повторення, розміру адреси, розміру операнда, заміни сегменту. Тут нас цікавитимуть префікси заміни сегменту.
Команди процесора, звертаються до пам'яті, можуть в якості першого байта свого коду містити префікс заміни сегменту, за допомогою якого процесор визначає, з якого сегментного регістра узяти сегментну адресу. Для сегментного регістра ES код префікса становить 26h, для SS - 361i, для CS - 2Eh. Якщо префікс відсутній, сегментна адреса береться з регістра DS (хоча для нього теж передбачений свій префікс).
У наведеному прикладі, за замовчуванням, всі дані адресуються через сегментний регістр DS, так що замість inc meml можна було написати inc DS: mem. У разі заміни сегментного регістра його обов'язково потрібно вказувати явно:
inc ES: mem1
inc CS: mem2
Звернення до комірки пам'яті за відомою абсолютною адресою здійснюється наступним чином:
mov AL,DS: [17h] | Завантаження в AL вмісту комірки зі зміщенням 17h в сегменті, визначеному вмістом DS |
1.4 Регістровий непрямий (базовий і індексний).
Адресується пам'ять (байт або слово). Відносна адреса елементу пам'яті знаходиться в регістрі, позначення якого полягає в прямі дужки. У МП 86 непряма адресація допустима тільки через регістри ВХ, ВР, SI і DI. При використанні регістрів ВХ або ВР адресацію називають базовою, при використанні регістрів SI або DI - індексною.
Якщо непряма адресація здійснюється через один з регістрів ВХ, SI або DI, то мається на увазі сегмент, що адресується через DS, тому при адресації через цей регістр позначення DS: можна опустити:
mov es: [bx],'1' ――――→ mov [bx],'1'
До речі, цей фрагмент трохи ефективніше попереднього в сенсі витрачання пам'яті. Через відсутність в коді останньої команди префікса заміни сегмента він займає на 1 байт менше місця.
Регістри ВХ, SI і DI в даному застосуванні зовсім рівнозначні, і з однаковим успіхом можна скористатися будь-яким з них:
Не так стоїть справа з регістром ВР. Цей регістр спеціально призначений для роботи зі стеком, і при адресації через цей регістр в режимах непрямої адресації мається на увазі сегмент стека; іншими словами, в якості сегментного регістра за замовчуванням використовується регістр SS.
Зазвичай непряма адресація до стека використовується в тих випадках, коли необхідно звернутися до даних, що містяться в стеку, без вилучення їх звідти (наприклад, якщо К ці дані доводиться прочитувати неодноразово).
Позначення цього способу адресації:
[BX] | (мається на увазі DS: [BX]) |
[BP] | (мається на увазі SS: [BP]) |
[SI] | (мається на увазі DS: [SI]) |
[DI] | (мається на увазі DS: [DI]) |
Використання базової адресації, на перший погляд, знижує ефективність програми, оскільки вимагає додаткової операції - завантаження в базовий регістр необхідної адреси. Однак команда з базовою адресацією займає менше місця в пам'яті (так як в неї не входить адреса комірки) і виконується швидше команди з прямою адресацією (через те, що команда коротше, процесору потрібно менше часу на її зчитування з пам'яті). Тому базова адресація ефективна в тих випадках, коли за заданою адресою доводиться звертатися багато разів, особливо, в циклі. Виграш виявляється тим більше, чим більше число, раз відбувається звернення за вказаною адресою. З іншого боку, можливості цього режиму адресації невеликі, і на практиці частіше використовують більш складні способи.
Приклади:
mov SI, offset string | ; В SI завантажується відносна адреса комірки string |
mov AX, [SI] | ; Вміст комірки string завантажується в AX |
inc [SI] | ; Збільшуватися вміст комірки string |
mov BX, [SI] | ; Нове вміст комірки string завантажується в BX |
mov DI, SI | ; Відносна адреса комірки string копіюється в DI |
1.5 Регістровий непрямий режим із зсувом (базовий і індексний).
Адресується пам'ять (байт або слово). Відносна адреса операнда визначається, як сума вмісту регістра BX, BP, SI або DI і вказаної в команді константи, іноді званої зсувом. Зсув може бути числом або адресою. Так само, як і у випадку базової адресації, при використанні регістрів BX, SI і DI мається на увазі сегмент, що адресується через DS, а при використанні ВР мається на увазі сегмент стека і, відповідно, регістр SS.
зсув = {SP, BP, DI, SI, BX} + зсув з команди
Іноді можна зустрітися з альтернативними позначеннями того ж способу адресації, які допускає асемблер. Замість, наприклад, 4 [ВХ] можна з таким же успіхом написати [ВХ +4], 4 + [ВХ] або [ВХ] +4. Така неоднозначність мови нічого, крім плутанини, не приносить, проте її треба мати на увазі, так як з цими позначеннями можна зіткнутися, наприклад, розглядаючи текст деассемблірованной програми.
Розглянемо тепер приклад використання базової адресації зі зміщенням при зверненні до стека:
зсув = {SP, BP, DI, SI, BX} + зсув з команди
Тут квадратні дужки [] - це теж оператор. Він обчислює адресу як суму того, що знаходиться всередині дужок з тим, що знаходиться зовні.
array db 0, 10, 20, 30, 40, 50, 60; Нехай в сегменті даних визначений масив:
Послідовність команд:
mov BX,5
mov AL,array [5]; завантажить в AL елемент масиву з індексом 5, тобто 50.
Той же результат буде отриманий і в таких послідовностях команд:mov BX,offset array
mov AL,5 [BX]
или
mov AL, [BX] +5
mov AL, [BX+5]
1.6 Базово-індексний режим
Адресується пам'ять (байт або слово). Відносна адреса операнда визначається, як сума вмісту наступних пар регістрів:
зсув [BX] [SI] | (мається на увазі DS: зсув [BX] [SI]) |
зсув [BX] [DI] | (мається на увазі DS: зсув [BX] [DI]) |
зсув [BP] [SI] | (мається на увазі SS: зсув [BP] [SI]) |
зсув [BP] [DI] | (мається на увазі SS: зсув [BP] [DI]) |
У всіх цих випадках можна також писати:
зсув [BX+SI] |
[ зсув +BX+SI] |
[BX+SI] + зсув |
Це надзвичайно поширений спосіб адресації, особливо, при роботі з масивами. У ньому використовуються два регістри, при цьому одним з них повинен бути базовий (ВХ або ВР), а іншим - індексний (SI або DI). Як правило, в одному з регістрів знаходиться адреса масиву, а в іншому - індекс в ньому, при цьому абсолютно байдуже, в якому що.
1.7 Базово-індексна адресація зі зміщенням.
Адресується пам'ять (байт або слово). Відносна адреса операнда визначається як сума вмісту двох регістрів і зсуву.
Це спосіб адресації є розвитком попереднього. У ньому використовуються ті ж пари регістрів, але отриманий з їх допомогою результуючий адресу можна ще змістити на значення вказаної в команді константи. Як і у випадку базово-індексної адресації, константа може представлятись індексом (і тоді в одному з регістрів повинна міститися базова адреса пам'яті), але може бути і базовою адресою. В останньому випадку регістри можуть використовуватися для зберігання складових індексу.
Наведемо формальний приклад даного режиму адресації.
Нехай в сегменті даних визначений масив з 24 байт
syms db 'ЙЦУКЕНГШЩЗХЪ'
db 'йцукенгшщзхъ'
послідовність команд
mov BX,12mov SI,6
mov DL,syms [BX] [SI]; завантажить в регістр DL елемент з індексом 6 з другого ряду, тобто код ASCII букви г
Той же результат буде отриманий і в такому варіанті:
mov BX,offset syms
mov SI,6
mov DL,12 [BX] [SI]
2. Порядок виконання роботи:
1. За допомогою редактора емулятора EMU 8086 напишіть програму, вихідний текст якої наводиться в лістингу № 1:
2. Створіть виконуваний файл типу COM.
3. Вивчіть структуру програми, також вивчіть структуру сегмента даних програми: знайдіть в ньому всі змінні, визначені в тексті програми.
4. Переробіть програму з використанням спрощених директив сегментації так, щоб отримати виконуваний файл тіпа.com і порівняйте розміри програм.
5. Виконайте перші 5 кроків програми, аналізуючи і записуючи стан регістрів на кожному кроці.
6. Занесіть в СХ 00FFh. Визначте за способом адресації комірку пам'яті в сегменті, де відбудуться зміни, записати її адресу.
7. Виконайте подальші кроки програми, аналізуючи можливі способи адресації.
8. Підготуйте звіт, який повинен містити тексти програм, адреси сегментних регістрів і запису адрес комірок пам'яті проти відповідних команд, а також запис вмісту цих осередків.
9. У звіті повинні міститися відповіді на наступні запитання.
3. контрольні питання
Як переслати вміст X в Y?
Чим відрізняються команди
MOV [si], cx
і
MOV si, cx?
До якого способу адресації відноситься команда MOV dx, offset message?
Які сегменти використовуються при наступних варіантах адресації: [BX] [SI], [BX] [DI], [BP] [SI], [BP] [DI]?
5. Що станеться при виконанні інструкції
MOV AL, DS: 17h?
Чим ця команда відрізняється від такою:
MOV AL, DS: [17h]?
6. Вкажіть, які інструкції в програмі (лістинг № 1), створеної в даній лабораторній роботі, відносяться до інструкцій:
з безпосереднім;
непрямим режимом адресації?
7. Вкажіть спосіб запису звернення безпосередньо до комірки пам'яті за відомою абсолютною адресою?
8. Префікси, Види префіксів. Префікси заміни сегменту?
9. Перерахуйте регістри непрямої і базової адресації. Опишіть відмінності?
10. Сутність ефективності базової адресації в порівнянні з прямою?
Лістинг №1.
TITLE MOVE2 MOVE2 SEGMENT 'CODE' ASSUME CS: MOVE2, DS: DATA MYPROC PROC OUTPROC:
MOV AX,DATA MOV DS,AX MOV AH,BH MOV AH,X MOV CH,3 MOV AX,3 MOV AX,Y MOV [SI],CX MOV [BP],CX MOV [SI],258 MOV [BP+516],1027 MOV BYTE PTR X,255 MOV BYTE PTR [DI+515],4 MOV WORD PTR [DI+515],4 MOV [DI+BP+515],258 MOV AX, [SI+BX+258] MOV AH,4CH INT 21H MYPROC ENDP MOVE2 ENDS DATA SEGMENT X DB 1 Y DW 2 DATA ENDS END MYPROC