ПЕРЕЛІК ДИСЦИПЛІН:
  • Адміністративне право
  • Арбітражний процес
  • Архітектура
  • Астрологія
  • Астрономія
  • Банківська справа
  • Безпека життєдіяльності
  • Біографії
  • Біологія
  • Біологія і хімія
  • Ботаніка та сільське гос-во
  • Бухгалтерський облік і аудит
  • Валютні відносини
  • Ветеринарія
  • Військова кафедра
  • Географія
  • Геодезія
  • Геологія
  • Етика
  • Держава і право
  • Цивільне право і процес
  • Діловодство
  • Гроші та кредит
  • Природничі науки
  • Журналістика
  • Екологія
  • Видавнича справа та поліграфія
  • Інвестиції
  • Іноземна мова
  • Інформатика
  • Інформатика, програмування
  • Юрист по наследству
  • Історичні особистості
  • Історія
  • Історія техніки
  • Кибернетика
  • Комунікації і зв'язок
  • Комп'ютерні науки
  • Косметологія
  • Короткий зміст творів
  • Криміналістика
  • Кримінологія
  • Криптология
  • Кулінарія
  • Культура і мистецтво
  • Культурологія
  • Російська література
  • Література і російська мова
  • Логіка
  • Логістика
  • Маркетинг
  • Математика
  • Медицина, здоров'я
  • Медичні науки
  • Міжнародне публічне право
  • Міжнародне приватне право
  • Міжнародні відносини
  • Менеджмент
  • Металургія
  • Москвоведение
  • Мовознавство
  • Музика
  • Муніципальне право
  • Податки, оподаткування
  •  
    Бесплатные рефераты
     

     

     

     

     

     

         
     
    МОВА МАКРОАССЕМБЛЕРА IBM PC
         

     

    Інформатика, програмування

    МОВА МАКРОАССЕМБЛЕРА IBM PC (Довідковий посібник)

    Укладач: В. Н. Пильщиків (МДУ, ВМК) (січень 1992 р.)

    У посібнику розглядається мова макроассеблера для персональних ЕОМ типу IBM PC (мова MASM, версія 4.0).

    Посібник складається з 4 розділів. У главі 1 розглянуто особливості персональних комп'ютерів типу IBM PC і наведені початкові відомості про мову MASM. У главі 2 описується система команд цих комп'ютерів. Глава 3 присвячена присвячена власне мови MASM. У розділі 4 наведено приклади фрагментів програм та повних програм на MASM для вирішення різних завдань.

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

    Під терміном "ПК" в посібнику розуміється персональний комп'ютер типу IBM PC c мікропроцесором 8088/8086, 80186 або 80286.

    Розділ 1. ОСОБЛИВОСТІ ПК. ВСТУП У MASM.

    1.1. ОПЕРАТИВНА ПАМ'ЯТЬ. РЕГІСТРИ.

    1.1.1 Оперативна пам'ять

    Об'єм оперативної пам'яті ПК - 2 ^ 20 байт (1 Мб). Байти нумеруються починаючи з 0, номер байта називається його адресою. Для посилань на байти пам'яті використовуються 20-розрядні адреси: від 00000 до FFFFF (у 16-річної системі).

    Байт містить 8 розрядів (бітів), кожен з яких може приймати значення 1 або 0. Розряди нумеруються справа наліво від 0 до 7: -----------------< br> | | | | | | | | |
    -----------------< br> 7 6 5 4 3 2 1 0

    Байт - це найменша адресуемая комірка пам'яті. У ПК використовуються і більш великі осередки - слова і подвійні слова. Слово - це два сусідніх байти, розмір слова - 16 бітів (вони нумеруються справа наліво від 0 до 15). Адресою слова вважається адреса її першого байта (з меншим адресою); ця адреса може бути парним і непарним. Подвійне слово - це будь-які чотири сусідніх байти (два сусідніх слова), розмір такої комірки - 32 біта; адресою подвійного слова вважається адреса її першого байта.
    Байти використовуються для зберігання невеликих цілих чисел і символів, слова - для зберігання цілих чисел і адрес, подвійні слова - для зберігання "довгих" цілих чисел і т.зв. адресних пар (сегмент: зсув).

    1.1.2 Регістри

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

    Всі регістри мають розмір слова (16 бітів), за кожним з них закріплено певне ім'я (AX, SP і т.п.). За призначенням і способом використання регістри можна розбити на наступні групи: регістри загального призначення (AX, BX, CX, DX, BP, SI, DI, SP);
    сегментні регістри (CS, DS, SS, ES);
    лічильник команд (IP);
    регістр прапорів (Flags).

    (Розшифровка цих назв: A - accumulator, акумулятор; B - base, база; C - counter, лічильник; D - data, дані; BP - base pointer, покажчик бази; SI - source index, індекс джерела; DI -- destination index, індекс приймача; SP - stack pointer, покажчик стека; CS -

    code segment, сегмент команд; DS - data segment, сегмент даних; SS stack segment, сегмент стека; ES - extra segment, додатковий сегмент; IP - instruction pointer, лічильник команд.)

    Регістри загального призначення можна використовувати у всіх арифметичних і логічних командах. У той же час кожен з них має певну спеціалізацію (деякі команди "працюють" тільки з певними регістрами). Наприклад, команди множення і ділення вимагають, щоб один з операндів знаходився в регістрі AX або в регістрах AX і DX (залежно від розміру операнда), а команди управління циклом використовують регістр CX в якості лічильника циклу. Регістри BX і BP дуже часто використовуються як базові регістри, а SI і DI - як індексні. Регістр SP зазвичай вказує на вершину стека, апаратно підтримуваного в ПК.

    Регістри AX, BX, CX і DX конструктивно влаштовані так, що можливий незалежний доступ до їх старшої та молодшої половин; можна сказати, що кожен з цих регістрів складається з двох байтових регістрів, що позначаються AH, AL, BH і т.д . (H - high, старший; L - low, молодший): ----------- ----------- ----------- -----------< Br> AX | AH | AL | BX | BH | BL | CX | CH | CL | DX | DH | DL |
    ----------- ----------- ----------- -----------< Br> 15 8 7 0

    Таким чином, з кожним із цих регістрів можна працювати як з єдиним цілим, а можна працювати і з його "половинками". Наприклад, можна записати слово в AX, а потім вважати тільки частину слова з регістру AH або замінити тільки частину в регістрі AL і т.д. Такий пристрій регістрів дозволяє використовувати їх для роботи і з числами, і з символами.

    Всі інші регістри не діляться на "половинки", тому вважати чи записати їх вміст (16 бітів) можна тільки цілком.

    Сегментні регістри CS, DS, SS і ES не можуть бути операндами ніяких команд, крім команд пересилання і стекові команд. Ці регістри використовуються тільки для сегментації адрес (див. 1.4).

    Лічильник команд IP завжди містить адресу (зсув від початку програми) тієї команди, яка повинна бути виконана наступної (початок програми зберігається в регістрі CS). Вміст регістра IP можна змінити тільки командами переходу.

    1.1.3 Прапори

    І, нарешті, в ПК є особливий регістр прапорів. Прапор - це біт, що приймає значення 1 ( "прапор встановлений"), якщо виконано деякий умова, і значення 0 ( "прапор скинутий") в іншому випадку. У ПК ис-

    користується 9 прапорів, кожному з них присвоєно певне ім'я (ZF, CF і т.д.). Всі вони зібрані в регістрі прапорів (кожен прапор - це один з розрядів регістра, частина його розрядів не використовується):
    -------------------------------------------------< br> Flags | x | x | x | x | OF | DF | IF | TF | SF | ZF | x | AF | x | PF | x | CF |
    -------------------------------------------------< br> 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

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

    Прапори умов:

    CF (carry flag) - прапорець перенесення. Приймає значення 1, якщо при складанні цілих чисел з'явилася одиниця переносу, не "влазити" в розрядну сітку, або якщо при віднімання чисел без знаку першим з них було менше другий. У командах зрушення в CF заноситься біт, що вийшов за розрядну сітку. CF фіксує також особливості команди множення.

    OF (overflow flag) - прапорець переповнення. Встановлюється в 1, якщо при складання або віднімання цілих чисел зі знаком вийшов результат, по модулю перевершує допустиму величину (сталося переповнення мантиси і вона "залізла" в знаковий розряд).

    ZF (zero flag) - прапор нуля. Встановлюється в 1, якщо результат команди виявився рівним 0.

    SF (sign flag) - прапор знаку. Встановлюється в 1, якщо в операції над знаковими числами вийшов негативний результат.

    PF (parity flag) - прапорець парності. Дорівнює 1, якщо результат чергової команди містить парна кількість двійкових одиниць. Враховується звичайно тільки при операціях вводу-виводу.

    AF (auxiliary carry flag) - прапорець додаткового переносу. Фіксує особливості виконання операцій над двійковій-десятковими числами.

    Прапори станів:

    DF (direction flag) - прапорець напрямку. Встановлює напрямок перегляду рядків у строкових командах: при DF = 0 рядки проглядаються "вперед" (від початку до кінця), при DF = 1 - у зворотному напрямку.

    IF (interrupt flag) - прапорець переривань. При IF = 0 процесор перестає реагувати на що надходять до нього переривання, при IF = 1 блокування переривань знімається.

    TF (trap flag) - прапорець трасування. При TF = 1 після виконання кожної команди процесор робить переривання (з номером 1), чим можна скористатися при налагодженні програми для її трасування.

    1.2. ПРЕДСТАВЛЕННЯ ДАНИХ. Арифметичні операції

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

    шістнадцяткові числа записуються з буквою h на кінці, двійкові

    числа - з буквою b (так прийнято в MASM).

    1.2.1 Представлення цілих чисел.

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

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

    Цілі числа без знака.

    Ці числа можуть бути представлені у вигляді байта, слова чи подвійного слова - в залежності від їх розміру. У вигляді байти представляються цілі від 0 до 255 (= 2 ^ 8-1), у вигляді слова - цілі від 0 до 65535 (= 2 ^ 16-1), у вигляді подвійного слова - цілі від 0 до 4 294 967 295 ( = 2 ^ 32-1). Числа записуються в двійковій системі числення, займаючи всі розряди осередку. Наприклад, число 130 записується у вигляді байтів 10000010b (82h).

    Числа розміром в слово зберігаються в пам'яті в "перевернутому" вигляді: молодшого (праві) 8 бітів числа розміщуються в першому байті слова, а старші 8 бітів - у другому байті (у 16-річної системі: дві праві цифри - в першу байті, дві ліві цифри - у другому байті). Наприклад, число 130 (= 0082h) у вигляді слова зберігається в пам'яті так:
    -----------< br> | 82 | 00 |
    -----------< br> (Зазначимо, однак, що в регістрах числа зберігаються в нормальному вигляді:
    -----------< br> AX | 00 | 82 |
    -----------< br> AH AL)

    "перевернути" подання використовується і при зберіганні в пам'яті цілих чисел розміром в подвійне слово: у першій його байті розміщуються молодші 8 бітів числа, у другому байті - попередні 8 бітів і т.д. Наприклад, число 12345678h зберігається в пам'яті так:
    ---------------------< br> | 78 | 56 | 34 | 12 |
    ---------------------< br>

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

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

    Звичайно, "перевернуте" подання незручно для людей, однак при використанні мови асемблера цю незручність не відчувається: в MASM всі числа записуються в нормальному, неперевернутом вигляді (див. нижче).

    Цілі числа зі знаком.

    Ці числа також подаються у вигляді байти, слова та подвійного слова. У вигляді байти записуються числа від -128 до 127, у вигляді слова числа від -32768 до 32767, а у вигляді подвійного слова - числа від -2147483648 до 2147483647. При цьому числа записуються в додатковому коді: невід'ємне число записується так само, як і беззнакові число (тобто в прямому коді), а негативне число-x (x> 0) представляється беззнакові числом 2 ^ 8-x (для байтів) , 2 ^ 16-x (для слів) або 2 ^ 32-x (для подвійних слів). Наприклад, додатковим кодом числа -6 є байт FAh (= 256-6), слово FFFAh або подвійне слово FFFFFFFAh. При цьому байт 10000000b (= 80h) трактується як -128, а не як +128 (слово 8000h розуміється як -32678), тому лівий біт додаткового коду завжди грає роль знакового: для невід'ємних чисел він дорівнює 0, для негативних - 1.

    Знакові числа розміром в слово і подвійне слово записуються в пам'яті в "перевернутому" вигляді (при цьому знаковий біт виявляється в останньому байті комірки). Але в MASM ці числа, як і беззнакові, записуються в нормальній формі.

    Іноді число-байт необхідно розширити до слова, тобто потрібно отримати таке ж за величиною число, але розміром в слово. Існує два способи такого розширення - без знаку і зі знаком. У будь-якому випадку вихідне число-байт потрапляє в другій (до "перевертання") байт слова, а ось перший байт заповнюється по-різному: при розширенні без знака в нього записуються нульові біти (12h -> 0012h), а при розширенні зі знаком в перший байт записуються нулі, якщо число-байт було невід'ємним, і записується вісім двійкових одиниць у противному випадку (81h -> FF81h). Іншими словами, при розширенні зі знаком в першому байті слова копіюється знаковий розряд числа-байти.

    Аналогічно відбувається розширення числа-слова до подвійного слова.

    1.2.2 Особливості виконання арифметичних опреацій

    У ПК є команди додавання і віднімання цілих чисел розміром в слово і байт. Спеціальних команд для додавання і віднімання подвійних слів немає, ці операції реалізуються через команди додавання і віднімання слів.

    Додавання і віднімання беззнаковаих чисел проводиться за модулем 2 ^ 8

    для байтів і 2 ^ 16 для слів. Це означає, що якщо в результаті складання з'явилася одиниця переносу, не вміщаються в розрядну сітку, то вона відкидається. Наприклад, при складанні байтів 128 і 130 виходить число 258 = 100000010b, тому ліва двійкова одиниця відкидається і залишається число 2 = 10b, яке і оголошується результатом складання. Помилка тут не фіксується, але в прапор переносу CF записується 1 (якщо переносу не було, в CF заноситься 0). "Зловити" таке спотворення суми можна тільки подальшим аналізом прапора CF.

    Спотворення результату відбувається і при віднімання від меншого числа більшого. І тут не фіксується помилка, однак перші числа дається "позика одиниці" (у разі байтів це число збільшується на 256, для

    слів - на 2 ^ 16), після чого і проводиться віднімання. Наприклад, віднімання байтів 2 і 3 зводиться до віднімання чисел 256 +2 = 258 і 3, в результаті чого виходить неправильна різниця 255 (а не -1). Для того щоб можна було виявити таку ситуацію, в прапор переносу CF заноситься 1 (якщо позики не було, в CF записується 0).

    Додавання і віднімання знакових цілих чисел здійснюється за тими ж алгоритмами, що і для беззнакових чисел (у цьому одна з переваг додаткового коду): знакові числа розглядаються як відповідні беззнакові числа, проізодітся операція над цими беззнакові числами і отриманий результат інтерпретується як знакову число. Наприклад, складання байтових чисел 1 і -2 відбувається так: беруться їхні додаткові коди 1 і (256-2) = 254, обчислюється сума цих величин 1 +254 = 255 і вона трактується як знакове число -1 (255 = 256-1) . Якщо при такому складання виникла одиниця переносу, то вона, як завжди, відкидається, а прапор CF отримує значення 1. Проте в даному випадку це відсікання не представляє інтерес - результат операції буде правильним, наприклад: 3 + (-2) => 3 +254 (mod 256) = 257 (mod 256) = 1. Зате тут можлива інша неприємність: модуль суми (її мантиса) може перевершити допустиму межу і "залізти" в знаковий розряд, зіпсували його. Наприклад, при складанні байтових чисел 127 і 2 виходить величина 129 = = 100001001b, що представляє додатковий код числа -127 (= 256-129).

    Хоча результат тут вийшов і неправильним, процесор не фіксує помилку, але зате заносить 1 в прапор переповнення OF (якщо "переповнення мантиси" не було, в OF записується 0). Аналізуючи потім цей прапор, можна "зловити" таку помилку.

    Таким чином, додавання (віднімання) знакових і беззнакових чисел здійснюється за одним і тим же алгоритмом. При цьому ПК не "знає", які числа (зі знаком чи без) він складає; в будь-якому випадку він складає їх як беззнакові числа і в будь-якому випадку формує прапори CF і OF. А ось як інтерпретувати складові і суму, на якій з цих прапорів звертати увагу - це особиста справа автора програми.

    Що стосується множення і ділення знакових і беззнакових чисел, то вони виконуються за різними алгоритмами, різними машинними командами. Однак і у цих операцій є ряд особливостей. При збільшенні байтів (слів) перший співмножники зобов'язаний знаходитися в регістрі AL (AX), результатом ж множення є слово (подвійне слово), кіт?? рої заноситься в регістр AX (регістри DX і AX). Тим самим при збільшенні зберігаються всі цифри твори. При розподілі байтів (слів) перший операнд (ділене) повинен бути словом (подвійним словом) і зобов'язаний знаходитися в регістрі AX (регістрах DX і AX). Результатом поділу є дві величини розміром в байт (слово) - неповна приватне (div) і залишок від ділення (mod); неповне приватне записується в регістр AL (AX), а залишок - в регістр AH (DX).

    1.2.3 Представлення символів і рядків

    На символ відводиться один байт пам'яті, в який записується код символу - ціле від 0 до 255. У ПК використовується система кодування ASCII (American Standard Code for Information Interchange). Вона, природно, не містить кодів російських букв, тому в нашій країні застосовується деякий варіант цієї системи з російськими літерами (зазвичай це альтернативна кодування ГОСТу).

    Деякі особливості цих систем кодування:

    - код пробілу менше коду будь-якої букви, цифри і взагалі будь-якого графічно представимо символу;

    - коди цифр впорядковані за величиною цифр і не містять пропусків, тобто з нерівності код ('0 ') <= код (c) <= код ('9') випливає, що c - цифра;

    - коди великих латинських букв впорядковані згідно з алфавітом і не містять пропусків; аналогічно з малими латинськими літерами;

    - (в альтернативному кодуванні ГОСТу) коди російських букв (як великих, так і малих) впорядковані згідно з алфавітом, але між ними є коди інших символів.

    Рядок (послідовність символів) розміщується в сусідніх байтах пам'яті (у неперевернутом вигляді): код першого символу рядка записується в першому байті, код другу символу - у другому байті і т.п. Адресою рядка вважається адреса її першого байта.

    У ПК рядком вважається також і послідовність слів (зазвичай це

    послідовність цілих чисел). Елементи таких рядків розташовуються в послідовних елементах пам'яті, але кожен елемент представлений в "перевернутому" вигляді.

    1.2.4 Представлення адрес

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

    Справа в тому, що в ПК терміном "адреса" позначають різні речі. Часто під адресою розуміється 16-бітове зміщення (offset) - адреса клітинки, відраховувати від початку сегмента (області) пам'яті, якому належить ця клітинка. У цьому випадку під адреса відводиться слово пам'яті, причому адреса записується в "перевернутому" вигляді (як і числа-слова взагалі).

    В іншому випадку під "адресою" розуміється 20-бітовий абсолютний адреса деякої комірки пам'яті. Через низку причин в ПК така адреса задається не як 20-бітове число, а як пара "сегмент: зсув", де "сегмент" (segment) - це перші 16 бітів початкової адреси сегменту пам'яті, якому належить осередок, а "зсув" - 16-бітовий адреса цього осередку, відраховувати від початку даного сегменту пам'яті (величина 16 * сегмент + зсув даетабсолютний адреса комірки). Така пара записується у вигляді подвійного слова, причому (як і для чисел) в "перевернутому" вигляді: у першому слові розміщується зміщення, а в другому - сегмент, причому кожне з цих слів у свою чергу представлено в "перевернутому" вигляді. Наприклад, пара 1234h: 5678h буде записана так:
    ---------------------< br> | 78 | 56 | 34 | 12 |
    ---------------------< br> зсув сегмент

    1.2.5 Директиви визначення даних

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

    У найпростішому випадку в директиві DB, DW або DD описується одна константа, якій дається ім'я для наступних посилань на неї. По цій директиві асемблер формує машинне подання константи (зокрема, якщо треба, "перевертає" її) і записує в чергову комірку пам'яті. Адреса цієї комірки стає значенням імені: всі входження імені в програму асемблер буде замінювати на цю адресу. Імена, зазначені в директивах DB, DW і DD, називаються іменами змінних (на відміну від міток - імен команд).

    У MASM числа записуються в нормальному (неперевернутом) вигляді в cистемах числення з основою 10, 16, 8 або 2. Десяткові числа записуються як звичайно, за шістнадцяткові числом ставиться буква h (якщо число починається з "цифри" A, B, ..., F, то спочатку обов'язковий 0), за вісімковий числом - буква q або o, за двійковим числом - буква b.

    Приклади: A DB 162; описати константу-байт 162 і дати їй ім'я A
    B DB 0A2h; така ж константа, але з ім'ям B
    З DW -1; константа-слово -1 з ім'ям З
    D DW 0FFFFh; така ж константа-слово, але з ім'ям D
    E DD -1; -1 як подвійне слово

    Константи-символи описуються в директиві DB двояко: або вказується код символу (ціле від 0 до 255), або сам символ в лапках (одинарних чи подвійних); в останньому випадку асемблер сам замінить символ на його код. Наприклад, такі директиви еквівалентні (2A - код зірочки в ASCII):
    CH DB 02Ah
    CH DB '*' CH DB "*"
    Константи-адреси, як правило, задаються іменами. Так, за директивою
    ADR DW CH

    буде відведено слово пам'яті, якому дається ім'я ADR і в який запишеться адреса (зміщення), який відповідає імені CH. Якщо таке ж ім'я описати в директиві DD, то асемблер автоматично додасть до зміщення імені його сегмент і запише зміщення у першу половину подвійного слова, а сегмент - в другу половину. З будь-якої з директив DB, DW і DD можна описати змінну, тобто відвести клітинку, не давши їй початкового значення. У цьому випадку в правій частині директиви вказується знак питання:
    F DW? ; відвести слово і дати йому ім'я F, нічого в цей байт не записувати

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

    G DB 200, -5, 10h,?, 'F'

    Ім'я, вказане в директиві, вважають саме перше з констант. Для посилань на інші в MASM використовуються вирази виду <ім'я> + <ціле>; наприклад, для доступу до байту з числом -5 треба вказати вираз G 1, для доступу до байту з 10h - вираз G 2 і т. д.

    Якщо у директиві DB перераховані тільки символи, наприклад:

    S DB 'a','+',' b'

    тоді цю директиву можна записати коротше, уклавши всі ці символи в одні лапки:

    S DB 'a + b'

    І, нарешті, якщо у директиві описується кілька однакових констант (змінних), то можна скористатися конструкцією повторення

    k DUP (a, b ,..., c)

    що еквівалентна повтореної k раз послідовності a, b ,..., c. Наприклад, директиви V1 DB 0,0,0,0,0
    V2 DW ?,?,?,?,?,?,?,?,?,' a ', 1,2,1,2,1,2,1,2
      можна записати більш коротко таким чином:
    V1 DB 5 DUP (0)
    V2 DW 9 DUP (?), 'A', 4 DUP (1,2)

    1.3. ПОДАННЯ КОМАНД. Модифікація адреси.
      1.3.1 Структура команд. Виконавчі адреси
    Машинні команди ПК займають від 1 до 6 байтів.
      Код операції (КОП) займає один або два перших байтів команди. У ПК настільки багато різних операцій, що для них не вистачає 256 різних КОПів, які можна представити в одному байті. Тому деякі операції об'єднуються в групи і їм дається один і той же КОП, у другому ж байті цей КОП уточнюється. Крім того, у другому байті вказуються типи і спосіб адресації операндів. Решта байти команди вказують на операнди.
      Команди можуть мати від 0 до 3 операндів, у більшості команд один або два операнда. Розмір операндів - байт або слово (рідко подвійне слово). Операнд має бути зазначено у самій команді (це т.зв. безпосередній операнд), або може перебувати в одному з регістрів ПК і тоді в команді вказується цей регістр, або може перебувати в комірці пам'яті і тоді в команді той чи інший спосіб вказується адреса цієї осередки. Деякі команди вимагають, щоб операнд знаходився у фіксованому місці (наприклад, в регістрі AX), тоді операнд явно не вказується в команді. Результат виконання команди поміщається в регістр або комірку пам'яті, з якого (яку), як правило, береться перший операнд. Наприклад, більшість команд з двома операндами реалізують дію
      op1: = op1 _ op2
      де op1 - регістр або комірка, а op2 - безпосередній операнд, регістр або комірка.
      Адреса операнда дозволено модифіковані з одного або двох регістрів. У першому випадку як регістра-модифікатора дозволено використовувати регістр BX, BP, SI або DI (і ніякий інший). У другому випадку один з модифікаторів зобов'язаний бути регістром BX або BP, а інший -
      регістром або SI DI; одночасна модифікація з BX і BP або SI і DI неприпустима. Регістри BX і BP зазвичай використовуються для зберігання бази (початкової адреси) деякої ділянки пам'яті (скажімо, масиву) і тому називаються базовими регістрами, а регістри SI і DI часто містять індекси елементів масиву і тому називаються індексними регістрами. Однак такий розподіл ролей необов'язково, і, наприклад, в SI може знаходитися база масиву, а в BX - індекс елемента масиву.
      У MASM адреса в командах записуються у вигляді однієї з наступних конструкції:
      A, A [M] або A [M1] [M2],
      де A - адреса, M - регістр BX, BP, SI або DI, M1 - регістр BX або BP, а M2 - регістр SI або DI. Під второрм і третьому варіанті A може бути відсутнім, в цьому випадку вважається, що A = 0.
      При виконанні команди процесор насамперед обчислює т.зв. виконавчий (ефективний) адреса - як суму адреси, заданого в команді, і поточних значень зазначених регістрів-модифікаторів, причому всі ці величини розглядаються як невід'ємні і підсумовування
      ведеться за модулем 2 ^ 16 ([r] означає вміст регістра r):
      A: Aісп = A
      A [M]: Aісп = A + [M] (mod 2 ^ 16)
      A [M1] [M2]: Aісп = A + [M1] + [M2] (mod 2 ^ 16)
      Отриманий таким чином 16-розрядний адреса визначається т.зв. зсув - адреса, відраховувати від початку деякого сегмента (області) пам'яті. Перед зверненням до пам'яті процесор ще додає до зміщення початковий адресу цього сегменту (він зберігається в деякому сегментному регістрі), в результаті чого виходить остаточний 20-розрядний адреса, за якою і відбувається реальне звернення до пам'яті (див. 1.4).
    1.3.2 Формати команд
    У ПК формати машинних команд досить різноманітні. Для прикладу наведемо лише основні формати команд з двома операндами.
      1) Формат "регістр-регістр" (2байта):
      ------------- ----------------< Br>   | КОП | d | w | | 11 | reg1 | reg2 |
      ------------- ----------------< Br> 7 2 1 0 7 6 5 3 2 0
      Команди цього формату описують зазвичай дію reg1: = reg1_reg2 або
      reg2: = reg2_reg1. Поле КОП першого байта вказує на операцію (_), яку треба виконати. Біт w визначає розмір операндів, а біт d вказує, в якій із регістрів записується результат:
      w = 1 - слова d = 1 - reg1: = reg1_reg2
      = 0 - байти = 0 - reg2: = reg2_reg1
      У другому байті два лівих біта фіксовані (для даного формату), а трехбітовие поля reg1 і reg2 вказують на регістри, що беруть участь в операції, згідно наступної таблиці:

      reg w = 1 w = 0 reg w = 1 w = 0
    ----------------- ----------------< Br>  000 AX AL 100 SP AH
     001 CX CL 101 BP CH
     010 DX DL 110 SI DH
     011 BX BL 111 DI BH

    2) Формат "регістр-пам'ять" (2-4 байти):
      ------------- ------------- -------------------< Br>   | КОП | d | w | | mod | reg | mem | | адреса (0-2 байти) |
      ------------- ------------- -------------------< Br>   Ці команди описують операції reg: = reg_mem або mem: = mem_reg. Біт w першого байта визначає розмір операндів (див. вище), а біт d вказує, куди записується результат: в регістр (d = 1) або в комірку пам'яті (d = 0). Трехбітовое поле reg другому байти вказує операнд-регістр (див. вище), двухбітовое поле mod визначає, скільки байтів в команді займає операнд-адреса (00 - 0 байтів, 01 - 1 байт, 10 - 2 байти), а трехбітовое поле mem вказує спосіб модифікації цієї адреси. У наступній таблиці вказані правила обчислення виконавчого адреса в залежності від значень полів mod і mem (a8 - адреса розміром в байт, a16
      - Адреса розміром в слово):

    mem mod | 00 01 10
     -------------------------------------------------- ----< br> 000 | [BX] + [SI] [BX] + [SI] + a8 [BX] + [SI] + a16
    001 | [BX] + [DI] [BX] + [DI] + a8 [BX] + [DI] + a16
    010 | [BP] + [SI] [BP] + [SI] + a8 [BP] + [SI] + a16
    011 | [BP] + [DI] [BP] + [DI] + a8 [BP] + [DI] + a16
    100 | [SI] [SI] + a8 [SI] + a16
    101 | [DI] [DI] + a8 [DI] + a16
    110 | a16 [BP] + a8 [BP] + a16
    111 | [BX] [BX] + a8 [BX] + a16
      Зауваження. Якщо в команді не задано адресу, то він вважається нульовим. Якщо адреса задано у вигляді байт (a8), то він автоматично розширюється зі знаком до слова (a16). Випадок mod = 00 і mem = 110 вказує на відсутність регістрів-модифікаторів, при цьому адреса должет мати розмір слова (адресний вираз [BP] асемблер транслює в mod = 01 і mem = 110 при a8 = 0). Випадок mod = 11 відповідає формату "регістр-регістр".
      3) Формат "регістр-безпосередній операнд" (3-4 байти): ----------- ------------- ---------- ----------------< br>

    | КОП | s | w | | 11 | КОП "| reg | | непосред.операнд (1-2 б) |

    ----------- ------------- ----------------------- ---
      Команди цього формату описують операції reg: = reg_immed (immed - безпосередній операнд). Біт w вказує на розмір операндів, а поле reg - на регістр-операнд (див. вище). Поле КОП в першому байті визначає лише клас операції (наприклад, клас додавання), уточнює ж операцію поле КОП "з другого байта. Безпосередній операнд може займати 1 або 2 байти - залежно від значення біта w, при цьому операнд-слово записується в команді в "перевернутому" вигляді. Задля економії пам'яті в ПК передбачений випадок, коли в операції над словами безпосередній операнд може бути заданий байтом (на цей випадок вказує 1 в бите s при w = 1), і тоді перед виконанням операції байт автоматично розширюється (зі знаком) до слова.
      4) Формат "пам'ять-безпосередній операнд" (3-6 байт):
     ----------- -------------- -------------- ----------- -------< br> | КОП | s | w | | mod | КОП "| mem | | адреса (0-2б) | | непоср.оп (1-2б) |
    ----------- -------------- -------------- ----------- -------< br>   Команди цього формату описують операції типу mem: = mem_immed. Зміст всіх полів - той же, що і в попередніх форматах.
      Крім розглянутих в ПК використовуються й інші формати команди з двома операндами; так, передбачений спеціальний формат для команд, один з операндів яких фіксований (зазвичай це регістр AX). Мають свої формати і команди з іншим числом операндів.
    1.3.3 Запис команд в MASM
    Зі сказаного ясно, що одна й та сама операція в залежності від типів операдов записується у вигляді різних машинних команд: наприклад, у ПК є 28 команд пересилання байтів і слів. У той же час в MASM
      всі ці "родинні" команди записуються однаково: наприклад, всі команди пересилання мають одну і ту ж символьну форму запису:
      MOV op1, op2 (op1: = op2)
      Аналізуючи типи операндів, асемблер сам вибирає потрібну машинну команду.

    У загальному випадку команди записуються в MASM наступним чином:
      мітка: мнемокод операнди; коментар
      Мітка з двокрапкою, а також крапку з комою і коментар можуть бути відсутні. Мітка грає роль імені команди, її можна використовувати у командах переходу на цю задачу. Коментар не впливає на зміст команди, а лише пояснює її.
      Мнемонічні назви операцій повністю перераховані в розділі 2. Операнди, якщо є, перераховуються через кому. Основні правила
      запису операндів наступні.
      Регістри вказуються своїми іменами, наприклад:
      MOV AX, SI; обидва операнда - регістри
      Безпосередні операнди задаються константними виразами (їх значеннями є константи-числа), наприклад:
      MOV BH, 5; 5 - безпосередній операнд
      MOV DI, SIZE X; SIZE X (число байтів, займаних змін; ної X) - безпосередній операнд
      Адреса описуються адресними виразами (наприклад, іменами змінних), які можуть бути модифіковані з одного або двох регістрів; наприклад, у таких командах перший операнди задають адреса:
      MOV X, AH
      MOV X [BX] [DI], 5
      MOV [BX], CL
      Під час запису команд в символьної формі необхідно уважно стежити за правильним зазначенням типу (розміру) операндів, щоб не було помилок. Тип звичайно визначається за зовнішнім виглядом одного з них, наприклад:
      MOV AH, 5; пересилка байта, тому що AH - байтовий регістр
      MOV AX, 5; пересилання слова, тому що AX - 16-бітовий регістр
    ; (операнд 5 може бути байтом і словом, за ним, не можна визначити розмір пересилається величини)
      MOV [BX], 300; пересилання слова, тому що число 300 не може бути; байтом
      Якщо за зовнішнім виглядом можна однозначно визначити тип обох операндів, тоді ці типи повинні збігатися, і?? аче асемблер зафіксує помилку. Приклади:
      MOV DS, AX; обидва операнда мають розмір слова
      MOV CX, BH; помилка: регістри CX і BH мають різні розміри
      MOV DL, 300; помилка: DL - байтовий регістр, а число 300 не; може бути байтом
      Можливі ситуації, коли за зовнішнім виглядом операндів не можна визначити тип жодного з них, як, наприклад, у команді
      MOV [BX], 5
      Тут число 5 може бути і байтом, і словом, а адреса з регістра BX може вказувати і на байт пам'яті, і на слово. У подібних ситуаціях асемблер фіксує помилку. Щоб уникнути її, треба уточнити тип одного з операндів за допомогою оператора з назвою PTR:
      MOV BYTE PTR [BX], 5; пересилка байта
      MOV WORD PTR [BX], 5; пересилання слова
      (Оператори - це різновид виразів мови MASM, аналогічні функціям.)
      Оператор PTR необхідний і в тому випадку, коли треба змінити тип, запропонований імені при його описі. Якщо, наприклад, X описано як ім'я змінної розміром в слово:
      X DW 999
      і якщо треба записати в байтовий регістр AH значення тільки першого байта цього слова, тоді скористатися командою
      MOV AH, X
      не можна, тому що її операнди мають різний розмір. Цю команду слід записати трохи інакше:
      MOV AH, BYTE PTR X
      Тут конструкція BYTE PTR X означає адреса X, але вже розглядається не як адресу слова, а як адреса байта. (Нагадаємо, що з одного і того ж адреси може починатися байт, слово і подвійне слово; оператор PTR
      уточнює, осередок якого розміру ми маємо на увазі.)
      І ще одне зауваження. Якщо в символьної команді, що оперує зі словами, вказаний безпосередній операнд розміром в байт, як, наприклад, у команді
      MOV AX, 80h
      то виникає деяка неоднозначність: що буде записано в регістр AX - число 0080h (+128) або 0FF80h (-128)? У подібних ситуаціях асемблер формує машинну команду, де операнд-байт розширений до слова, причому розширення відбувається зі знаком, якщо операнд був записаний як від'ємне число, і без знака в інших випадках. Наприклад:
      MOV AX, -128; => MOV AX, 0FF80h (A: =- 128)
      MOV AX, 128; => MOV AX, 0080h (A: = +128) MOV AX, 80h; => MOV AX, 0080h (A: = +128)

    1.4. СЕГМЕНТІРОВНІЕ
      1.4.1 Сегменти пам'яті. Сегментні регістри.
    Перші моделі ПК мали оперативну пам'ять об'ємом 2 ^ 16 байт (64Кб) і тому використовували 16-бітові адреси. У подальших моделях пам'ять була збільшена до 2 ^ 20 байт (1Мб = 1000Кб), для чого вже потрібні 20-бітові адреси. Однак у цих ПК заради збереження наступності були збережені 16-бітові адреси: саме такі адреси зберігаються в регістрах і вказуються в командах, саме такі адреси виходять в результаті модмфікаціі з базових та індексних регістрів. Як же вдається 16-бітовими адресами посилатися на 1Мб пам'яті?
      Ця проблема вирішується за допомогою сегментації адрес (неявного базування адрес). У ПК вводиться поняття "сегмент пам'яті". Так називається будь-яка ділянка пам'яті розміром до 64Кб і з початковим адресою, кратним 16. Абсолютний (20-бітовий) адреса A будь-якої комірки пам'яті можна
      представити як суму 20-бітового початкового адреси (бази) B сегмента, якому при

         
     
         
    Реферат Банк
     
    Рефераты
     
    Бесплатные рефераты
     

     

     

     

     

     

     

     
     
     
      Все права защищены. Reff.net.ua - українські реферати ! DMCA.com Protection Status