→ Пошук по сайту       Увійти / Зареєструватися
Знання Асемблер Основи програмування

Способи адресації

Способом, або режимом адресації називають процедуру знаходження операнда для виконуваної команди. Якщо команда використовує два операнди, то для кожного з них має бути заданий спосіб адресації, причому режими адресації першого і другого операнда можуть як збігатися, так і розрізнятися. Операнди команди можуть знаходитися в різних місцях: безпосередньо у складі коди команди, в якому-небудь регістрі, в елементі пам'яті; у останньому випадку існує декілька можливостей вказівки його адреси. Строго кажучи, способи адресації є елементом архітектури процесора, відображаючи закладені в нім можливості пошуку операндів. З іншого боку, різні способи адресації певним чином позначаються в мові асемблера і в цьому сенсі є розділом мови.

Слід зазначити неоднозначність терміну "операнд" стосовно програм, написаних на мові асемблера. Для машинної команди операндами є ті дані (по суті, двійкові числа), з якими вона має справу. Ці дані можуть, як вже наголошувалося, знаходитися в регістрах або в пам'яті. Якщо ж розглядати команду мови асемблера, то для неї операндами (або, краще сказати, параметрами) є ті позначення, які дозволяють спочатку транслятору, а потім процесору визначити місцезнаходження операндів машинної команди. Так, для команди асемблера

mov mem, AX  

як операнди використовується позначення елементу пам'яті mem, а також позначення регістра АХ. В той же час, для відповідної машинної команди операндами є вміст елементу пам'яті і вміст регістра. Було б правильніше говорити про операнди машинних команд і про параметри, або аргументи команд мови асемблера.

По відношенню до команд асемблера було б правильніше використовувати термін "параметри", залишивши за терміном "операнд" позначення тих фізичних об'єктів, з якими має справу процесор при виконанні машинної команди, проте зазвичай ці тонкощі не враховують, і кажучи про операнди команд мови, розуміють насправді операнди машинних команд.

У архітектурі сучасних 32-розрядних процесорів Intel передбачені досить витончені способи адресації; у МП 86 способів адресації менше. У справжньому розділі будуть описані режими адресації, використовувані в МП 86.

У книгах, присвячених мові асемблера, можна зустріти різні підходи до опису способів адресації: не тільки назви цих режимів, але навіть і їх кількість можуть розрізнятися. Зрозуміло, способів адресації існує в точності стільки, скільки їх реалізовано в процесорі; проте, режими адресації можна об'єднувати в групи по різних ознаках, чому і створюється деяка плутанина, у тому числі і в кількості наявних режимів. Ми дотримуватимемося поширеною, але не єдино можливій термінології.

Регістрова адресація. Операнд (байт або слово) знаходиться в регістрі. Цей спосіб адресації застосовний до всіх регістрів процесора, що програмно-адресуються.

inc СН ;Плюс 1 до вмісту СН

push DS ;DS зберігається в стеку

xchg Вх,вр ;ВХ і ВР обмінюються вмістом

mov ES, АХ ;Содержимое АХ пересилається в ES 

Безпосередня адресація. Операнд (байт або слово) указується в команді і після трансляції поступає в код команди; він може мати будь-який сенс (число, адреса, код ASCII), а також бути представлений у вигляді символічного позначення.

mov АН, 40h ;Число 40h завантажується в АН

mov Al,'*' ;Код ASCII символу "*' завантажується в AL

int 21h ;Команда переривання з аргументом 21h

limit = 528 ;Число 528 отримує позначення limit

mov Cx,limit ;Число, позначене limit, завантажується в СХ 

Команда mov, використана в останній пропозиції, має два операнди; перший операнд визначається за допомогою регістрової адресації, другої, - за допомогою безпосередньої.

Важливим застосуванням безпосередньої адресації є пересилка відносних адрес (зсувів). Щоб вказати, що мова йде про відносній адресі даного осередку, а не про її вміст, використовується описувач onset (зсув):

; Сегмент даних

mes db "Урок 1' ;Строка символів

;Сегмент команд

mov Dx,offset mes ;Адрес рядки засилає в DX 

У приведеному прикладі відносна адреса рядка mes, тобто відстань в байтах першого байта цього рядка від початку сегменту, в якому вона знаходиться, заноситься в регістр DX.

Пряма адресація пам'яті. Адресується пам'ять; адреса елементу пам'яті (слова або байта) указується в команді (зазвичай в символічній формі) і поступає в код команди:

;Сегмент даних

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 (хоча для нього теж передбачений свій префікс).

Якщо на початку програми за допомогою директиви assume вказана відповідність сегменту даних сегментного регістра DS

assume Ds:data  

то команди звернення до пам'яті транслюються без якого-небудь префікса, а процесор при виконанні цих команд бере сегментну адресу з регістра DS.

Якщо в директиві assume вказана відповідність сегменту даних регістру ES

assume Es:data 

(в цьому випадку сегмент даних повинен розташовуватися перед сегментом команд), то команди звернення до полів цього сегменту транслюються з додаванням префікса заміни для сегменту ES. При цьому пропозиції програми виглядають звичайним способом; у них як і раніше просто указуються імена полів даних, до яких проводиться звернення.

Проте у ряді випадків префікс заміни сегменту повинен указуватися в програмі в явній формі. Така ситуація виникає, наприклад, якщо дані розташовані в сегменті команд, що типово для резидентних обробників переривань. Для звернення до таких даних можна, звичайно, використовувати регістр DS, якщо заздалегідь набудувати його на сегмент команд, але простіше виконати адресацію через регістр CS, який і так вже настроєний належним чином. Якщо в сегменті команд міститься поле даних з ім'ям mem, то команда читання з цього поля виглядатиме таким чином:

mov Ax,cs:mem  

В цьому випадку транслятор включить в код команди префікс заміни для сегменту CS. Інші приклади команд із заміною сегменту будуть приведені нижче.

До цих пір ми обговорювали адресацію осередків, що містяться в сегментах даних програми. Проте часто буває потрібно звернутися до пам'яті поза межами програми: до векторів переривань, системних таблиць, відеобуферу і так далі Зрозуміло, таке звернення можливе тільки якщо ми знаємо абсолютну адресу осередку, що цікавить нас. В цьому випадку необхідно спочатку набудувати один з сегментних регістрів почато області, що цікавить нас, після чого можна адресуватися до осередків по їх зсувах.

Хай потрібно вивести в лівий верхній кут екрану декілька символів, наприклад, два знаки окликів. Цю операцію можна реалізувати за допомогою наступних команд:

mov Ax,0b800h ;Сегментный адреса відеобуфера

mov Es,ax ;Отправим його в ES

mov byte ptr Es:0 ' ! ' ;Отправим символ на 1-е знакомісце екрану

mov byte ptr Es:2 ' ! ' ;Отправим символ на 2-е знакомісце екрану 

Набудувавши регістр ES на сегментну адресу відеобуфера Bs00h, ми пересилаємо код знаку "!" спочатку за відносною адресою 0 (у самий початок відеобуфера, в байт із зсувом 0), а потім на наступне знакомісце, що має зсув 2 (у непарних байтах відеобуфера зберігаються атрибути символів, тобто колір символів і фону під ними). У обох командах необхідно за допомогою позначення ES: вказати сегментний регістр, який використовується для адресації пам'яті. Зустрівшись з цим позначенням, транслятор включить в код команди префікс заміни сегменту, в даному випадку код 26h.

У приведеному прикладі ми знову зіткнулися з використанням атрибутивного оператора byte ptr, який дозволяє в явній формі задати розмір операнда. Проте якщо раніше цей оператор використовувався, щоб витягувати байт з даного, оголошеного, як слово, то тут його призначення інше. Транслятор, обробляючи команду

mov byte ptr Es:0 ' ! ' 

не має можливості визначити розмір операнда-приймача. Зрозуміло, відеобуфер, як і будь-яка пам'ять, складається з байтів, проте чи треба розглядати цю пам'ять, як послідовність байтів або слів? Команда без явного завдання розміру операнда

mov Es:0 ' ! '  

викличе помилку трансляції, оскільки асемблер не зможе визначити, чи треба транслювати цю пропозицію, як команду пересилки у відеобуфер байта 21h, або як команду пересилки слова 0021h.

Між іншим, на перший погляд може здатися, що в обговорюваній команді достатньо ясно вказаний розмір правого операнда, оскільки символ (в даному випадку "!") завжди займає один байт. Проте транслятор, зустрівши позначення "!", відразу ж перетворить його в код ASCII цього символу, тобто в число 21h, і вже не знає, звідки це число відбулося і який розмір воно має.
Варто ще відзначити, що вказівка в команді описувача word ptr

mov word ptr Es:0'!'  

не викличе помилки трансляції, але приведе до неприємних результатів. В цьому випадку у відеобуфер буде записано слово 002lh, яке заповнить байт 0 відеобуфера кодом 21h, а байт 1 кодом 00h. Проте атрибут 00h позначає чорний колір на чорному фоні, і символ на екрані видний не буде (хоча і буде записаний у відеобуфер).

За бажання можна позбавитися від необхідності вводити описувач розміру операнда. Для цього треба пересилати не безпосереднє дане, а вміст регістра:

mov AL'!' mov Es:0,al  

Тут операндом-джерелом служить регістр AL, розмір якого (1 байт) відомий, і розмір операнда-приймача визначати не треба. Зрозуміло, команда

mov Es:0,ax  

заповнить у відеобуфері не байт, а слово.
Для адресації до відеобуфера в наведеному вище прикладі використовувався сегментний регістр додаткових даних ES. Це цілком природно, оскільки зазвичай регістр DS служить для звернення до полів даних програми, а регістр ES якраз і призначений для адресації всього останнього. Проте при необхідності можна було скористатися для запису у відеобуфер регістром DS:

mov Ax,0b800h ;Сегментный адреса

mov Ds,ax ; відеобуфера в DS

mov byte ptr Ds:0 ' ! ' ;Символ у відеобуфер 

Цікаво, що хоча позначення DS: тут необхідно, транслятор не включить в код команди префікс заміни сегменту, оскільки команда без префікса виконує адресацію за умовчанням через DS.

Якщо, проте, за умовчанням виконується адресація через DS, то чи не можна опустити в останній команді позначення сегментного регістра? Не можна, оскільки позначення DS: число указує, що число є не безпосереднім операндом, а адресою операнда. Команда (неправильна)

mov 6,10  

повинна була б переслати число 10 в число 6, що, зрозуміло, позбавлено сенсу і виконано бути не може. Команда ж

mov Ds:6,10  

пересилає число 10 за відносною адресою 6, що має сенс. Таким чином, позначення сегментного регістра з двокрапкою перед операндом говорить про те, що операнд є адресою. Надалі ми ще зіткнемося з цим важливим правилом.

Ми розглянули три найважливіші способи адресації: регістрову, безпосередню і пряме звернення до пам'яті. Решта всіх режимів адресації відноситься до групи непрямої адресації пам'яті, коли у визначенні адреси елементу пам'яті бере участь один або декілька регістрів процесора. Розглянемо послідовно ці режими.

Регістрова непряма (базова і індексна). Адресується пам'ять (байт або слово). Відносна адреса елементу пам'яті знаходиться в регістрі, позначення якого полягає в прямі дужки. У МП 86 непряма адресація допустима тільки через регістри ВХ, ВР, SI і DI. При використанні регістрів ВХ або ВР адресацію називають базовою, при використанні регістрів SI або DI - індексною.
Перетворимо приведений вище приклад, щоб продемонструвати використання непрямої адресації через регістр.

mov Ax,0b800h ;Сегментный адреса

mov Es,ax ; відеобуфера в ES

mov Bx,2000 ;Смещение до середини екрану

mov byte ptr ES:[ВХ], ' ! ' ;Символ на екран 

Набудувавши ES, ми засилаємо в регістр ВХ необхідний зсув (для різноманітності до середини відеобуфера, який має об'єм точно 4000 байт), і в останній команді засилаємо код у відеобуфер за допомогою непрямої базової адресації через пару регістрів Es:bx з вказівкою заміни сегменту (ES:).

Якщо непряма адресація здійснюється через один з регістрів ВХ, SI або DI, то мається на увазі сегмент, що адресується через DS, тому при адресації через цей регістр позначення DS: можна опустити:

mov Ax,0b800h ;Сегментный адреса

mov Ds,ax ;видеобуфера у DS

mov Bx,2000 ;Смещение до середини екрану

mov byte ptr [ВХ] ' ! ' ;Символ на екран 

До речі, цей фрагмент трохи ефективніший за попереднє в сенсі витрачання пам'яті. Через відсутність в коді останньої команди префікса заміни сегменту він займає на 1 байт менше місця.

Регістри ВХ, SI і DI в даному застосуванні абсолютно рівнозначні, і з однаковим успіхом можна скористатися будь-яким з них:

mov D1,2000 ;Смещение до середини екрану

mov byte ptr [DI] ' ! ' ;Символ на екран 

Не так йде справа з регістром ВР. Цей регістр спеціально призначений для роботи із стеком, і при адресації через цей регістр в режимах непрямої адресації мається на увазі сегмент стека; іншими словами, як сегментний регістр за умовчанням використовується регістр SS.

Зазвичай непряма адресація до стека використовується в тих випадках, коли необхідно звернутися до даних, що містяться в стеку, без вилучення їх звідти (наприклад, якщо до ці дані доводиться прочитувати неодноразово). Приклад такого роду операцій буде приведений при обговоренні наступного режиму адресації.

Порівнюючи приведені вище фрагменти програм, можна відмітити, що використання базової адресації, на перший погляд, знижує ефективність програми, оскільки вимагає додаткової операції - завантаження в базовий регістр необхідної адреси. Дійсно, базова адресація в нашому прикладі не виправдана - у разі прямого звернення до пам'яті замість двох команд

mov Bx,2000 ;Смещение до середини екрану

mov byte ptr ES: [BX], ' ! ' ;Символ на екран 

можна використовувати одну

mov byte ptr Es:2000'!' ;Выведем символ в середину екрану  

Проте команда з базовою адресацією займає менше місця в пам'яті (оскільки в неї не входить адреса осередку) і виконується швидше за команду з прямою адресацією (через те, що команда коротша, процесору вимагається менше часу на її прочитування з пам'яті). Тому базова адресація ефективна в тих випадках, коли за заданою адресою доводиться звертатися багато разів, особливо, в циклі. Виграш виявляється тим більше, чим більше число разів відбувається звернення за вказаною адресою. З іншого боку, можливості цього режиму адресації невеликі, і на практиці частіше використовують складніші способи, які будуть розглянуті нижче.

Регістрова непряма адресація із зсувом (базова і індексна). Адресується пам'ять (байт або слово). Відносна адреса операнда визначається, як сума вмісту регістра BX, BP, SI або DI і вказаної в команді константи, іноді званої зсувом. Зсув може бути числом або адресою. Так само, як і у разі базової адресації, при використанні регістрів BX, SI і DI мається на увазі сегмент, що адресується через DS, а при використанні ВР мається на увазі сегмент стека і, відповідно, регістр SS.

Розглянемо застосування непрямої адресації із зсувом на прикладі прямого виводу у відеобуфер.

mov Ax,0b800h ;Сегментный адреса

mov Es,ax ;видеобуфера у ES

mov DI, 80*2*24 ;Смещение до нижнього рядка екрану

mov byte ptr ES: [DI],'о' ;Символ на екран

mov byte ptr Es:2'[DI],'к ;Запишем символ в наступну позицію

mov byte ptr Es:4'[DI] ! ' ;Запишем символ в наступну позицію 

В даному прикладі як базовий вибраний регістр DI; у нього заноситься базова відносна адреса пам'яті, в даному випадку зсув у відеобуфері на початок останнього рядка екрану. Модифікація цієї адреси з метою отримати зсув по рядку екрану здійснюється за допомогою констант 2 і 4, які при обчисленні процесором виконавської адреси додаються до вмісту базового регістра DI.

Іноді можна зустрітися з альтернативними позначеннями того ж способу адресації, які допускає асемблер. Замість, наприклад, 4[ВХ] можна з таким же успіхом написати [Вх+4], 4+[ВХ] або [ВХ]+4. Така неоднозначність мови нічого, окрім плутанини, не приносить, проте її треба мати на увазі, оскільки з цими позначеннями можна зіткнутися, наприклад, розглядаючи текст деассемблірованной програми.
Розглянемо тепер приклад використання базової адресації із зсувом при зверненні до стека:

;Основна програма

push DS ;В стек завантажуються значення

push ES ;трех регістрів

push SI ;передаваемых підпрограмі

call mysub ;Вызов підпрограми mysub

;що використовує ці параметри

;Підпрограма mysub

mov Bp,sp ;Поместим у ВР поточна адреса вершини стека

mov Ах,2[ВР] ;Читаем у АХ останній параметр (SI)

mov Вх,4[ВР];Читаем у ВХ попередній параметр (ES)

mov Cx,6[BP];Читаем у СХ перший параметр (DS) 

Тут продемонстрований класичний прийом читання вмісту стека без витягання з нього цього вмісту. Після того, як основна, програма зберегла в стеку три параметри, які буде потрібно підпрограмі, командою call викликається підпрограма mysub. Ця команда зберігає в стеку адресу повернення (адреса наступного за call пропозиції основної програми) і здійснює перехід на підпрограму. Стан стека при вході в підпрограму приведений на рис. 2.15.

Ріс.2.15. Стан стека після завантаження в нього трьох параметрів і переходу на підпрограму

Якби підпрограма просто зняла із стека параметри, що знаходяться там, вона насамперед вилучила б із стека адресу повернення, і позбавила б себе можливості повернутися в основну програму (докладніше питання виклику підпрограми і повернення з неї обговорюватимуться в подальших розділах). Тому в даному випадку замість команд pop зручніше скористатися командами mov. Підпрограма копіює у ВР вміст трьох параметрів і переходу на моє SP і використовує потім цю адресу як базового, модифікуючи його за допомогою базової адресації із зсувом.

До речі, ми знову стикаємося тут з тією вельми звичайною ситуацією, коли програміст не має можливості звертатися по наочних символічних адресах, яких в стеку, природно, немає, а вимушений визначати "уручну" зсуву до елементів, що цікавлять його, стека. При цьому необхідно врахувати і алгоритм виконання команди call, яка, зберігаючи в стеку адресу повернення в основну програму, зміщує покажчик стека ще на одне слово.

У нашому фрагментарному прикладі ми не розглядаємо питання повернення в основну програму. Вдумливий читач міг також засумніватися в правильності або, краще сказати, в розумності тексту підпрограми. Адже переносячи параметри із стека в регістри загального призначення, підпрограма затирає їх початковий вміст. Якщо ж вони не містили нічого потрібного, то ними можна було скористатися для передачі параметрів в підпрограму, а не зв'язуватися з мало наочними операціями із стеком. Дійсно, ради стислості ми опустили операції, практично необхідні в будь-якій підпрограмі, - збереження в стеку (знову в стеку!) тих регістрів, які використовуватимуться в підпрограмі. До речі, це відноситься і до регістра ВР. У реальній підпрограмі ці дії слід було виконати, що привело б до зміни зсувів при регістрі ВХ, які набули б значень (з урахуванням збереження 4 регістрів) 10, 12 і 14.

У всіх приведених вище прикладах регістр використовувався для зберігання базової адреси, а зсув, якщо воно було потрібне, указувався у вигляді константи. Можлива і зворотна ситуація, коли як зсув виступає адреса масиву, а в регістрі знаходиться індекс елементу, що адресується, в цьому масиві. Розглянемо відносно реальний приклад такого роду.

Хай нам треба заповнити масив з 10000 слів натуральним рядом чисел. Зарезервуємо в сегменті даних місце під цей масив, а в сегменті команд організовуємо цикл занесення в послідовні слова масиву ряду наростаючих чисел. Нам доведеться скористатися декількома новим командами (inc, add і loop), які надалі будуть розглянуті детальніше.

;Сегмент даних

array dw 10000

;Сегмент команд

mov SI, 0 ;Начальное значення індексу елементу в масиві

mov АХ, 0 ;Первое число-заповнювач

mov Сх,10000;Число кроків в циклі (завжди в СХ)

fill: mov array[SI],ax ;Занесение числа в елемент масиву

inc AX ;Инкремент числа-заповнювача

add Si,2 ;Смещение у масиві до наступного слова

loop fill ;Возврат на мітку fill (СХ разів) 

Цикл починається з команди, поміченою міткою fill (правила утворення імен влучний такі ж, як і для імен полів даних). У цій команді вміст АХ, спочатку рівне 0, переноситься в елемент пам'яті, адреса якої обчислюється, як сума адреси масиву array і вмісту індексного регістра SI, в якому в першому кроці никла теж 0. В результаті в перше слово масиву заноситься 0. Далі вміст регістра АХ збільшується на 1, вміст регістра SI - на 2 (через те, що масив складається із слів), і командою loop здійснюється перехід на мітку fill, після чого тіло циклу повторюється при нових значеннях регістрів АХ і SI. Число кроків в циклі, відлічуване командою loop, визначається початковим вмістом регістра СХ.

Базово-індексна адресація. Адресується пам'ять (байт або слово). Відносна адреса операнда визначається, як сума вмісту наступних пар регістрів:

[ВХ] [SI] (мається на увазі DS:[BX][SI])

[ВХ][DI] (мається на увазі DS:[BX][DI])

[ВР] [SI] (мається на увазі SS:[BP][SI])

[ВР] [DI] (мається на увазі SS:[BP][DI]) 

Це надзвичайно поширений спосіб адресації, особливо, при роботі з масивами. У нім використовуються два регістри, при цьому одним з них має бути базовий (ВХ або ВР), а іншим - індексний (SI або DI). Як правило, в одному з регістрів знаходиться адреса масиву, а в іншому - індекс в нім, при цьому абсолютно байдуже, в якому що. Трансформуємо попередній приклад, ввівши в нього ефективнішу базово-індексну адресацію.

;Сегмент даних

array dw 10000

;Сегмент команд

mov Bx,offset array ;Базовый адреса масиву в

;базовому регістрі

mov SI, 0 ;Начальное значення індексу

;елементу в масиві

mov АХ, 0 ;Первое число-заповнювач

mov Cx,10000 ;Число кроків в циклі

fill: mov [BX][SI],ax ;Отправим число в масив

inc AX ;Инкремент числа-заповнювача

add SI, 2 ;Смещение у масиві до наступного слова

loop fill ;На мітку fill (CX разів) 

Підвищення ефективності досягається за рахунок того, що команда занесення числа в елемент масиву виявляється коротшою (оскільки в неї не входить адреса масиву) і виконується швидше, оскільки цю адресу не треба кожного разу прочитувати з пам'яті.

Базово-індексна адресація із зсувом. Адресується пам'ять (байт або слово). Відносна адреса операнда визначається як сума вмісту двох регістрів і зсуву.

Це спосіб адресації є розвитком попереднього. У нім використовуються ті ж пари регістрів, але отриману з їх допомогою результуючу адресу можна ще змістити на значення вказаної в команді константи. Як і у разі базово-індексної адресації, константа може бути індексом (і тоді в одному з регістрів повинна міститися базова адреса пам'яті), але може бути і базовою адресою. У останньому випадку регістри можуть використовуватися для зберігання складових індексу. Приведемо формальний приклад даного режиму адресації.

Хай в сегменті даних визначений масив з 24 байтів, в якому записані коди латинських і російських символів верхнього ряду клавіатури:

sims db "Qwertyuiop{}'

db "йцукенпшцзх''

Послідовність команд

mov Bx,12 ;Число байтів в рядку

mov SI, 6

mov Dl,syms[BX][SI] 

завантажить в регістр DL елемент з індексом 6 з другого ряду, тобто код ASCII букви Г. Тот же результат можна отримати, завантаживши в один з регістрів не індекс, а адресу масиву:

mov BX, off set sym

mov Si,6

mov DL, 12 [BX] [SI] 

загрузка...
Сторінки, близькі за змістом