- •Тема 2. Архітектура процесора і мова асемблера: Основи програмування на мові асемблера
- •1.1. Команды пересилки даних загального призначення
- •1.2. Команди вводу-виводу в порт
- •1.3. Команди роботи з адресами і покажчиками пам'яті
- •1.4. Команди перетворення даних
- •2.1. Огляд групи арифметичних команд і даних
- •2.2. Цілі двійкові числа
- •2.3. Десяткові числа
1.2. Команди вводу-виводу в порт
Під час обговорення питання про те, де можуть перебувати операнди машинної команди, слід згадати порт вводу-виводу.
Подивіться на рис. 2.3 (лекц. 2). На ньому показана сильно спрощена, концептуальна схема управління обладнанням комп'ютера.
Як видно з рисунка, самим нижнім рівнем є рівень BIOS, на якому робота з обладнанням ведеться безпосередньо через порти. Тим самим реалізується концепція незалежності від устаткування. При заміні устаткування необхідно буде лише підправити відповідні функції BIOS, переорієнтувавши їх на нові адреси і логіку роботи портів.
Принципово керувати пристроями безпосередньо через порти нескладно. Відомості про номери портів, їх розрядності, форматі керуючої інформації наводяться в технічному описі пристрою. Необхідно знати лише кінцеву мету своїх дій, алгоритм, згідно з яким працює конкретний пристрій, та порядок програмування його портів. Тобто, фактично, потрібно знати, що і в якій послідовності потрібно надіслати в порт (при записі в нього) або вводити з нього (при читанні) і як слід трактувати цю інформацію. Для цього досить усього двох команд, які присутні в системі команд мікропроцесора:
in акумулятор, номер порту — ввод в акумулятор з порту з номером (номер порту); out номер порту, акумулятор — вивод вмісту акумулятора в порт з номером (номер порту).
1.3. Команди роботи з адресами і покажчиками пам'яті
При написанні програм на асемблері проводиться інтенсивна робота з адресами операндів, що знаходяться в пам'яті. Для підтримки такого роду операцій є спеціальна група команд, до якої входять такі команди:
lea призначення, джерело — завантаження эффективної адреси; lds призначення, джерело — завантаження покажчика в регістр сегменту даних ds; les призначення, джерело — завантаження покажчика в регістр додаткового сегменту даних es; lgs призначення, джерело — завантаження покажчика в регістр додаткового сегменту даних gs; lfs призначення, джерело — завантаження покажчика в регістр додаткового сегменту даних fs; lss призначення, джерело — завантаження покажчика в регістр сегменту стека ss.
Команда lea схожа на команду mov тим, що вона також проводить пересилку. Проте, зверніть увагу, команда lea проводить пересилку не даних, а ефективної адреси даних (тобто зміщення даних відносно початку сегменту даних) в регістр, вказаний операндом призначення.
Часто для виконання деяких дій в програмі недостатньо знати значення однієї лише ефективної адреси даних, а необхідно мати повний покажчик на дані. Ви пам'ятаєте, що повний покажчик на дані складається з сегментної складової і зміщення. Всі останні команди цієї групи дозволяють отримати в парі регістрів такий повний покажчик на операнд в пам'яті. При цьому ім'я сегментного регістра, в який поміщається сегментна складова адреси, визначається кодом операції. Відповідно, зсув поміщається в регістр загального призначення, вказаний операндом призначення.
Але не все так просто з операндом джерело. Насправді, в команді в якості джерела не можна вказувати безпосередньо ім'я операнда в пам'яті, на який ми б хотіли отримати покажчик.
Заздалегідь необхідно сформувати саме значення повного покажчика в деякій області пам'яті і вказати в команді отримання повної адреси ім'я цієї області. Для виконання цієї дії необхідно пригадати директиви резервування і ініціалізації пам'яті.
При використанні цих директив можливий окремий випадок, коли в полі операндів вказується ім'я іншої директиви визначення даних (фактично, ім'я змінної). В цьому випадку в пам'яті формується адреса цієї змінної. Яка адреса буде сформована (ефективна або повна), залежить від використаної директиви. Якщо це dw, то в пам'яті формується лише 16-бітове значення ефективної адреси, якщо ж dd — в пам'ять записується повна адреса. Розміщення цієї адреси в пам'яті наступне: у молодшому слові знаходиться зсув, в старшому — 16-бітова сегментна складова адреси.
Лістинг 1. Копіювання рядка <1>;---------Prg_8_1.asm--------------- <2> masm <3> model small <4> .data <5> ... <6> str_1 db ‘Асемблер — базова мова комп’ютера’ <7> str_2 db 50 dup (‘ ‘) <8> full_pnt dd str_1 <9> ... <10> .code <11> start: <12> ... <13> lea si,str_1 <14> lea di,str_2 <15> les bx,full_pnt ;повний вказівник на str1 в пару es:bx <16> m1: <17> mov al,[si] <18> mov [di],al <19> inc si <20> inc di <21> ;цикл на мітку m1 до пересилки всіх символів <22> ... <23> end start |
У рядках 13 та 14 в регістри si і di завантажуються значення ефективних адрес str_1 і str_2 змінних.
У рядках 17 та 18 проводиться пересилання чергового байта з одного рядка в інший. Покажчики на позиції байтів в рядках визначаються вмістом регістрів si і di. Для пересилання чергового байта необхідно збільшити на одиницю регістри si та di, що й робиться командами додавання inc (рядки 19, 20). Після цього програму необхідно зациклити до обробки всіх символів рядка.
Необхідність використання команд отримання повного покажчика даних в пам'яті, тобто адреси сегмента і значення зміщення всередині сегменту, виникає, зокрема, при роботі з ланцюжками.
У рядку 15 лістингу 1 в подвійному слові full_pnt формуються сегментна частина адреси і зміщення для змінної str_1. При цьому 2 байти зміщення займають молодше слово full_pnt, а значення сегментної складової адреси - старше слово full_pnt. У рядку 15 командою les ці компоненти адреси поміщаються в регістри bx и es.