- •Регістри загального призначення процесора 8086
- •Р егістри спеціального призначення процесора 8086
- •Набір інструкцій процесора
- •Xchg ах, bx ; Міняємо місцями вміст ах і bx
- •Визначення даних
- •Виклик функцій bios і операційної системи
- •Директиви segment, assume, end і .386
- •Приклад визначення сегменту:
- •X db ? ; байт пам'яті, початкове значення якого не визначено
- •Управління пам'яттю процесора
- •Типи адресації 8086
- •Типи адресації 80386
- •Контроль над програмним потоком
- •Команди переходу після зіставлення чисел з урахуванням знака:
Типи адресації 80386
В процесорі 80386 для запису ефективної адреси можна використовувати будь-який 32-бітовий регістр загального призначення як базовий, а також будь-який регістр загального призначення окрім ESP як індексний. Так само з'явилася можливість множення індексного регістра на 2, 4 або 8, що полегшує роботу з масивами даних і два додаткові сегментні регістри – FS і GS.
Оскільки як базовий і індексний регістр можуть використовуватися одні і ті ж регістри загального призначення, для визначення сегменту за умовчанням важливу роль грає порядок проходження. Спочатку йде базовий регістр, потім – індексний. При базовому регістрі EBP або ESP сегмент за умовчанням – SS, у всій решті випадків – DS.
Як видно, ефективна адреса може виходити за рамки 64 Кілобайтів. Але, на жаль, для сумісності з 8086, в реальному режимі не можна переходити цю межу.
Приклади адресації 80386:
MOV BX [ebx + ecx + 1] ; базовий регістр, індексний регістр і константа
MOV DX, gs:[edi] ; тільки індексний регістр
MOV SI [eax + 2*eax] ; базовий регістр, індексний регістр і множник
Контроль над програмним потоком
Процесор виконує інструкції, прочитуючи їх з пам'яті за адресою CS:IP одну за іншою. Але іноді виникає необхідність перейти до іншої частини програми, яка знаходиться за певною адресою. Тобто, необхідно змінити IP. Прямо записати значення в цей регістр неможливо, для цього використовуються так звані інструкції переходу.
Розглянемо команду безумовного переходу JMP
JMP <адрес>
Інструкція JMP здійснює перехід за вказаному як параметр адресою. Ця адреса може бути визначений міткою в програмі, вмістом регістра або пам'яті і навіть просто числом. Якщо перехід здійснюється усередині сегменту CS (NEAR-адреса), то параметр може бути або 16-бітовим числом – зсувом усередині сегменту, або 8-і або 16-бітовим зсувом щодо адреси поточної інструкції. Якщо перехід здійснюється в інший сегмент (FAR), то адреса повинна бути заданий 32-бітовою парою сегмент: зсув. При написанні програми адресу поточної інструкції можна вказати за допомогою символу $, а зсув якої-небудь мітки або змінної усередині сегменту, в якому вона знаходиться, – за допомогою приставки offset.
Приклади безумовних переходів:
DATA SEGMENT
adr1 DW offset L1 ; зсув мітки від початку CODE
adr2 DD L1 ; повна адреса (сег.: зсув)
DATA ENDS
CODE SEGMENT
...
JMP L1 ; прямий перехід на мітку L1
JMP adr1 ; непрямий перехід на мітку L1 (NEAR)
JMP adr2 ; непрямий перехід на мітку L1 (FAR)
MOV BX, 10
JMP BX ; перехід за адресою CS:10
JMP $+2 ; перехід на L1 (розмір JMP = 2 байти)
L1: JMP 1030h:3492h ; прямий FAR-перехід
...
CODE ENDS
Для того, щоб здійснювати перехід не завжди, а тільки по виконанню певної умови, існують команди умовного переходу. Ці команди виконують перехід за адресою відносно поточної інструкції в межах ±128 байт, у разі певної комбінації прапорів.
J** <метка або відносний адрес>
Команди переходу залежно від установки певного прапора:
Команда |
Розшифровка |
Умова переходу |
Прапори |
Синоніми |
Антонім |
JC |
Jump if carry |
наявність перенесення |
CF = 1 |
JB, JNAE |
JNC |
JNC |
Jump if not carry |
відсутність перенесення |
CF = 0 |
JNB, JAE |
JC |
JZ |
Jump if zero |
нульовий результат |
ZF = 1 |
JE |
JNZ |
JNZ |
Jump if not zero |
ненульовий результат |
ZF = 0 |
JNE |
JZ |
JS |
Jump if sign |
негативний результат |
SF = 1 |
- |
JNS |
JNS |
Jump if not sign |
позитивний результат |
SF = 0 |
- |
JS |
JO |
Jump if overflow |
переповнювання |
= 1 |
- |
JNO |
JNO |
Jump if not overflow |
немає переповнювання |
= 0 |
- |
JO |
JP |
Jump if parity |
парний результат |
PF = 1 |
JPE |
JNP |
JPE |
Jump if parity even |
Парний результат |
PF = 1 |
JP |
JPO |
JNP |
Jump if not parity |
непарний результат |
PF = 0 |
JPO |
JP |
JPO |
Jump if parity odd |
непарний результат |
PF = 0 |
JNP |
JPE |
Найбільш часто команди J** використовуються в парі з інструкцією порівняння CMP. Ця інструкція виконує операцію SUB (віднімання) своїх операндів, модифікуючи прапори, але не зберігає результат.
CMP <операнд A> <операнд B>
J** <метка або відносний адрес>
Команди переходу після зіставлення чисел без урахування знака:
Команда |
Розшифровка |
Умова переходу |
Прапори |
Синоніми |
Антонім |
JA |
Jump if above |
А > B |
CF=0, ZF=0 |
JNBE |
JNA |
JNBE |
Jump if not below or equal |
А не <= B |
CF=0, ZF=0 |
JA |
JBE |
JAE |
Jump if above or equal |
А >= B |
CF = 0 |
JNC, JNB |
JNAE |
JNB |
Jump if not below |
А не < B |
CF = 0 |
JNC, JAE |
JB |
JB |
Jump if below |
А < B |
CF = 1 |
JC, JNAE |
JNB |
JNAE |
Jump if not above or equal |
А не >= B |
CF = 1 |
JC, JB |
JAE |
JBE |
Jump if below or equal |
А <= B |
CF=1 | ZF=1 |
JNA |
JNBE |
JNA |
Jump if not above |
А не > B |
CF=1 | ZF=1 |
JBE |
JA |
JE |
Jump if equal |
А = B |
ZF = 1 |
JZ |
JNE |
JNE |
Jump if not equal |
А не = B |
ZF = 0 |
JNZ |
JE |