системне програмування
Практична робота № 3
Машинні коди. Байт Способу Адресації.
В загальному, формат машинної команди можна представити наступним чином:
Префікс
Перепризначення сегменту
Код Операції
Байт способу адресації
Адреса
Дані
0/1
0/1
Завжди присутній
1
0/1
0,1,2
0,1,2
Позначення 0/1 означає відсутність/присутність даного поля в машинному коді або і його розмір в байтах.
Існують команди розмірності 1,2,3,4 байти.
Поле “Префікс” – для команд повтору рядкових операцій
REP/REPE/REPZ/REPNZ – повторює рядкову операцію визначену кількість разів безумовно, або по стану прапорця. Використовуються в якості префікса перед рядковими командами типу CMPS(порівняння рядків), MOVS(переміщення рядів). Наприклад:
MOV CX,20
Встановлення лічильника на 20 байт
LEA DI, STRING2
Адреса “куди” пересилати (відносно значення в регістрі ES)
LEA SI, STRING1
Адреса “звідки” пересилати (відносно значення в регістрі DS)
REP MOVSB
Переслати дані (породжений машинний код: CS:0101 F3
CS:0102 A4)
Значення в лічильнику команд не змінюється поки в CX не буде 0, а декремент відбувається автоматично.
Поле “Перепризначення сегменту” – присутній в командах, що використовують додаткове перевизначення сегментних регістрів.
Поле “Код Операції” (далі - КО) визначає яка саме дія буде виконуватися (+/-/MOV...)
Поле “Байт способу адресації” (БСА) :
Відсутній у таких випадках:
команда не має операндів;
один операнд регістр другий - безпосередні дані;
один операнд – адреса пам’яті, другий – регістр AX або AL (для акумулятора є спрощені команди, тому адресація інша);
в командах переходів (JMP);
в командах прямого вводу-виводу (IN-OUT).
Присутній, коли є непряма, пряма адресація.
Способи адресації
Розрізняють такі види адресації:
Регістрова – всі операнди знаходяться в регістрах процесора;
Безпосередня – один з операндів є безпосередньо числом(даними);
Пряма – в одному з операндів команди вказується ім’я певної змінної (мітка), адреса в регістрі;
Непряма:
Базова
Індексна
Базово-індексна
Команди з прямою адресацією пам’яті працюють швидше, оскільки не потребують додаткового додавання при визначенні фізичної адреси
При непрямій адресації посилання на операнд визначається через базовий або індексний регістр, константи, змінні зміщення та прості змінні. Квадратні дужки, що визначають операнди при такій адресації діють як знак плюс.
Схема формування адреси при непрямій адресації:
Ці операнди можна комбінувати в довільній послідовності. Але не можна одночасно використовувати два базові регістри або два індексні регістри. Відповідно, можна побудувати 16 різних записів адресації.
При формуванні фізичної адреси базовий регістр BX у виді [BX] використовується разом з сегментним регістром DS, а базовий регістр BP у виді [BP] використовується разом з сегментним регістром SS. Індексні регістри SI та DI передбачають використання сегментного регістру DS.
Приклади адресації
{припустимо маємо наступні визначення для сегментів і даних}
DOSSEG
.MODEL SMALL
.STACK 100h
.DATA
HeM DB 'Hello, world',13,10,'$'
.CODE
mov ax,@data
mov ds,ax
mov ah,9
mov dx,OFFSET HeM
int 21h
Команда
Спосіб адресації
Результат
Машинний код
mov ds,ax
Регістрова
ds=5254
8ED8
mov si,7
mov di,11d
mov bp,0
mov bx,0
Безпосередня
si=0007
di=000B
bp=0000
bx=00000
BE0700
BE0B00
BD0000
DD0000
mov al,HeM
mov al,[HeM]
mov al,HeM+7
Пряма
al=48
al=48
al=77
A00000
A00000
A00700
mov al,[bp]
mov al,[bx]
Базова
al=64
al=48
8A4600
8A07
mov al,HeM[si]
mov al,[HeM+si]
mov al,[HeM][si]
mov al,[HeM].si
mov al,HeM.[si]
mov al,HeM.si
Індексна
al=77
8A840000
mov al,[bp][di]
mov al,[bx][si]
mov al,[bx+di+7]
mov al,[bp][si+HeM].7
Базово-індексна
al=00
al=6C
al=0A
al=00
8A03
8A00
8A4107
8A820007
mov ah,4ch
int 21h
END
Повертаючись до БСА, і враховуючи наведені способи адресації, зупинимось детальніше на форматі цього поля. Звернемо також, увагу на два останні біти КО, оскільки вони впливають на формування способу адресації.
1 0
7 6 5 4 3 2 1 0
...
d
w
mod
reg
r/m
КО
БСА
d –біт, що вказує напрям потоку між операндами.
w – визначає розмір операндів.
mod – двобітовий код, що вказує на тип адреси.
reg – трибітовий вказівник регістра
r/m – трибітовий вказівник регістру/пам’яті.
Позначення для регістрів:
Біти
w=0
w=1
000
AL
AX
001
CL
CX
010
DL
DX
011
BL
BX
100
AH
SP
101
CH
BP
110
DH
SI
111
BH
DI
Для сегментних регістрів :
00
ES
01
CS
10
SS
11
DS
Значення поля mod:
mod
Призначення
00
Біти r/m задають абсолютну адресу, а байт зміщення відсутній
01
Біти r/m задають абсолютну адресу, і присутній один байт зміщення
10
Біти r/m задають абсолютну адресу, і присутні два байти зміщення
11
Біти r/m задають регістр
Значення поля r/m:
Три біти r/m разом з бітами mod повністю визначають спосіб адресації.
r/m
mod = 00
mod = 01
mod = 10
mod=11
mod=11
w=0
w=1
000
BX+SI
BX+SI+ зміщення (1b)
BX+SI+ зміщення (2b)
AL
AX
001
BX+DI
BX+DI+ зміщення (1b)
BX+DI+ зміщення (2b)
CL
CX
010
BP+SI
BP+SI+ зміщення (1b)
BP+SI+ зміщення (2b)
DL
DX
011
BP+DI
BP+DI+ зміщення (1b)
BP+DI+ зміщення (2b)
BL
BX
100
SI
SI+ зміщення (1b)
SI+ зміщення (2b)
AH
SP
101
DI
DI+ зміщення (1b)
DI+ зміщення (2b)
CH
BP
110
ПРЯМА
BP+ зміщення (1b)
BP+ зміщення (2b)
DH
SI
111
BX
BX+ зміщення (1b)
BX+ зміщення (2b)
BH
DI
Приклади розшифрування машинних кодів.
Команда
Код
16-кова
2-кова
MOV AH,00
В4
10110 100 00000000
MOV AX,00
В8
10111 000 00000000
ADD BX,AX
03D8
0000 0011 11 011 000
MUL BX
F6E3
1111 0110 11 100 011
Визначення даних в мові Assembler
Сегмент даних призначений для визначення констант, робочих полів і областей для вводу/виводу. У відповідності з існуючими директивами в асемблері дозволене визначення даних різної довжини: наприклад, директива DB визначає байт, а директива DW визначає слово. Елемент даних може містити безпосереднє значення або константу, визначену як символьний рядок або як числове значення. Іншим способом визначення константи є безпосереднє значення, тобто вказане прямо в команді, наприклад: MOV AL,20H У цьому випадку шістнадцяткове число 20 стає частиною машинного об’єктного коду. Безпосереднє значення обмежене одним байтом або одним словом, але таке використання є більш ефективним, аніж застосування константи.
Директиви визначення даних
Асемблер забезпечує два способи визначення даних: по-перше, через задання довжини даних і, по-друге, за їх значенням.
Розглянемо основний формат визначення даних:
[ім’я] Dn вираз
- Ім’я елемента даних не є обов’язковим але якщо в програмі є посилання на деякий елемент, те це робиться за допомогою імені.
- Для визначення елементів даних є наступні директиви:
DB (байт)
DW (слово – 2 байти)
DD (подвійне слово – 4 байти),
DQ (8 байт)
DT (10 байт).
Вираз може містити константу, наприклад: FLD1 DB 25,
або знак питання для невизначеного значення, наприклад: FLDB DB ?
Вираз може містити кілька констант, розділених комами й обмеженими тільки довжиною рядка:
FLD3 DB 11, 12, 13, 14, 15, 16, ...
Асемблер визначає ці константи у вигляді послідовності сусідніх байт. Звертання за FLD3 вказує на першу константу 11, за FLD3+1 - на другу 12. (FLD3 можна представити як FLD3+0).
Наприклад команда MOV AL,FLD3+3 завантажує в регістр AL значення 14 (шістнадцяткове 0E).
Вираз допускає також повторення константи в наступному форматі:
[ім’я] Dn кількість повторень DUP (вираз) ...
Наступні три приклади ілюструють повторення:
DW 10 DUP(?) ;Десять невизначених слів
DB 5 DUP(14) ;П’’ять байт, що містять 14h
DB 3 DUP(4 DUP(8));Дванадцять вісімок
Вираз може містити символьний рядок або числову константу.
Символьні рядки
Символьний рядок використаються для опису даних, таких як, наприклад, імена людей або заголовки сторінок. Вміст рядка виділяється одинарними лапками, наприклад, ‘PC’ або подвійними лапками - "PC". Асемблер переводить символьні рядки в об’єктний код у звичайному форматі ASCII.
Символьний рядок визначається тільки директивою DB, в якій вказується більше двох символів у нормальній послідовності зліва направо. Отже, директива DB є єдиним можливим форматом для визначення символьних даних.
Числові константи
Числові константи використаються для арифметичних величин і для aдрес пам’яті. Для опису константи лапки не ставляться. Асемблер перетворить всі числові константи в шістнадцятковий формат і записує байти в об’єктному коді в зворотної послідовності - справа наліво. Нижче показані різні числові формати.
Десятковий формат. Десятковий формат допускає десяткові цифри від 0 до 9 і позначається останньою буквою D, що можна не вказувати, наприклад, 125 або 125D. Незважаючи на те, що асемблер дозволяє кодування в десятковому форматі, він перетворить ці значення в шістнадцятковий об’єктний код. Наприклад, десяткове число 125 перетвориться в. 7Dh.
Шістнадцятковий формат. Шістнадцятковий формат допускає шістнадцяткові цифри від 0 до F і позначається останньою буквою H. оскільки асемблер думає, що з букви починаються ідентифікатори, те першою цифрою шістнадцяткової константи повинна бути цифра від 0 до 9. Наприклад, 2EH або 0FFFH, які асемблер перетворить відповідно в 2E і FF0F (байти в другому прикладі записуються в об’єктний код у зворотній послідовності).
Двійковий формат. Двійковий формат допускає двійкові цифри 0 і 1 і позначається останньою буквою B. Двійковий формат звичайно використається для більше чіткого подання бітових значень у логічних командах AND, OR, XOR і TEST. Десяткове 12, шістнадцяткове C і двійкове 1100B усі генерують один і той же код:
Вісімковий формат. Вісімковий формат допускає вісімкові цифри від 0 до 7 і позначається останньою буквою Q або O, наприклад, 253Q.
Директива визначення байта (DB)
Один байт виражається двома шістнадцятковими цифрами. Найбільше додатне число в одному байті це 7F, всі "більші" числа від 80 до FF представляють від’ємні значення. У десятковому виразі ці межі визначаються числами +127 і -128.
Приклад використання:
Адреса
Значення
Ім’я
Директива
Дані
коментар
0000
??
Label1
DB
?
Не ініціалізовано
0001
50 65 72 73 6F 6E 61 6C 20
43 6F 6D 70 75 74 65 72
Label2
DB
‘Personal Computer’
Символьний рядок
0012
20
Label3
DB
32
Десяткова константа
0013
20
Label4
DB
20h
Шістнадцяткова константа
0014
20
Label5
DB
0010 0000b
Двійкова константа
0015
50 43
Label6
DB
‘PC’
Символьний рядок
Директива визначення слова (DW)
Директива DW визначає елементи, які мають довжину в одне слово (два байти). . Два байти представляються чотирма шістнадцятковими цифрами. Найбільше позитивне шістнадцяткове число у двох байтах це 7FFF; всі "більші" числа від 8000 до FFFF представляють від’ємні значення. У десятковому форматі ці межі визначаються числами +32767 і -32768. Для директиви DW асемблер перетворить константи в шістнадцятковий об’єктний код, але записує його в зворотній послідовності.
Символьний вираз в DW обмежений двома символами, які асемблер представляє в об’єктному коді так, що, наприклад, ‘PC’ стає ‘CP’. Для визначення символьних рядків директива DW має обмежене застосування.
Приклад використання
Адреса
Значення
Ім’я
Директива
Дані
коментар
0000
0001
??
??
Label1
DW
?
Не ініціалізовано
0002
0003
43
50
Label2
DW
‘PC’
Символьний рядок
0004
0005
3C
7F
Label3
DW
32572
Десяткова константа
0006
0007
F0
FF
Label4
DW
0FFF0h
Шістнадцяткова константа
0008
0009
20
00
Label5
DW
0010 0000b
Двійкова константа
000A
000B
000C
000D
000E
000F
03
00
05
00
07
00
Label6
DW
3,5,7
Три константи
0010
0004 R
Label7
DW
Label3
Адресна константа
0012
0006
Label8
DW
Label5- Label2
Різниця адрес
Директива визначення подвійного слова (DD)
Директива DD визначає елементи, які мають довжину в два cлова (чотири байти). Числовий вираз може містити одну або більше констант, кожна з яких має максимум чотири байти (вісім шіст. цифр). Найбільше додатне шіст. число в чотирьох байтах це 7FFFFFFF; всі "більші" числа від 80000000 до FFFFFFFF представляють від’ємні значення. У десятковому форматі ці межі становлять +2147483647 і -2147483648. Для директиви DD асемблер перетворить константи в шістнадцятковий об’єктний код, але записує його в зворотній послідовності.
Директива визначення DQ та директива визначення DТ є аналогічними до DW та DD, з відповідними довжинами даних.
Безпосередні операнди
Команда MOV AX,0123H пересилає безпосередню шістнадцяткову константу 0123 у регістр AX. Трибайтний об’єктний код для цієї команди є B82301, де B8 означає "переслати безпосереднє значення в регістр AX", a наступні два байти містять саме значення. Багато команд мають два операнди: перший може бути регістр або адреса пам’яті, а другий - безпосередня константа.
Використання безпосереднього операнду більш ефективне ніж визначення числової константи в сегменті даних і організація посилання на неї в операнді команди MOV
Довжина безпосередніх операндів
Довжина безпосередньої константи залежить від довжини першого операнду. Наприклад, якщо безпосередній операнд є двобайтовим, а регістр AL має тільки один байт: MOV AL,0123H (помилка), то асемблер повідомить про помилку, однак, якщо безпосередній операнд коротший, ніж операнд, що одержує, наприклад: ADD AX,25H (немає помилки) то асемблер розширює безпосередній операнд до двох байт, 0025 і записує об’єктний код у вигляді 2500.
Формати безпосередніх даних
Безпосередня константа може бути шістнадцятковою, наприклад, 0123h; десятковою, наприклад, 291 (яку асемблер перетворить в 0123h); або двійковою, наприклад, 100100011В (яка перетвориться в 0123h).
Нижче наведений список команд, які допускають використання безпосередніх операндів:
Команди пересилання й порівняння: MOV, CMP.
Арифметичні команди: ADC, ADD, SBB, SUB.
Команди зсувів: RCL, RCR, ROL, ROR, SHL, SAR, SHR.
Логічні команди: AND, OR, TEST, XOR.
Директива EQU
Директива EQU не визначає елемент даних, але визначає значення, що може бути використане для підстановки в інших командах. Припустимо, що в сегменті даних закодовано наступну директиву EQU:
TIMES EQU 10
Ім’я, у цьому випадку TIMES, може бути представлено будь-яким припустимим в асемблері ім’ям. Тепер, у якій би команді або директиві не використалося слово TIMES асемблер підставить значення 10. Наприклад, асемблер перетворить директиву
FIELDA DB TIMES DUP (?)
в директиву
FIELDA DB 10 DUP (?)
Ім’я, пов’язане з деяким значенням за допомогою директиви EQU, може використатися в командах, наприклад:
COUNTR EQU 05
.......є
MOV CX,COUNTR
Асемблер заміняє ім’я COUNTR у команді MOV на значення 05, створюючи операнд з безпосереднім значенням, так, ніби було закодовано MOV CX,05 ;Асемблер підставляє 05.
Перевага директиви EQU полягає в тоту, що багато команд можуть використати значення, визначене іменем COUNTR. Якщо це значення повинне бути змінене, то зміні підлягає лише одна директива EQU. Природно, що використання директиви EQU доцільне лише там, де підстановка має сенс для асемблера. У директиві EQU можна використати символічні імена:
1. TP EQU TOTALPAY
2. MPY EQU MUL
Перший приклад припускає, що в сегменті дані програми визначене ім’я TOTALPAY. Для будь-якої команди, що містить операнд TP, асемблер замінить його на адресу TOTALPAY. Другий \ приклад показує можливість використання в програмі слова MPY замість звичайного мнемокоду MUL.