Міністерство освіти і науки України
Національний технічний університет України
«Київський політехнічний інститут ім. І. Сікорського»
Кафедра автоматизації проектування енергетичних процесів і систем
Лабораторна робота № 5
з дисципліни «Операційні системи»
«Система команд. Арифметичні команди. Обчислення цілочисельних арифметичних виразів з використанням команд MUL, IMUL, DIV, IDIV, ADD, ADC, INC, SUB, SBB, DEC, NEG, CBW, CWD»
Варіант 20
Робота студентки 1 курсу групи ТР-15, Чубукової Анастасії
Перевірила д.т.н., проф. Левченко Л.О.
КИЇВ 2022Мета: Програмування блоку обчислення арифметичних виразів на прикладі реалізації математичних формул з використанням арифметичних команд асемблера за індивідуальними завданнями.
Завдання:
1. Підготуйте теоретичну частину щодо використання команд, призначених для цілочисельних арифметичних виразів.
2. Підготуйте і налагодьте програму для обчислення простих формул за зразком. Продемонструйте роботу програми під керуванням налагоджувача, прокоментуйте вміст обчислюваних змінних.
Завдання за варіантом:
/
Теоретична частина
6.1 Команди переміщення даних
6.1.1 MOVe operand Пересилання операнда
MOVe operand to/from system registers Пересилання операнда у системні регістри (або з них)
Схема команди: MOV приймальник, джерело
Призначення: пересилання даних між регістрами або регістрами та пам’яттю. Команда має обмеження:
копіювання здійснюється з другого операнда у перший;
значення другого операнда не змінююється;
обидва оператора не можуть бути з пам’яті;
лише один з операндів може бути сегментним, приймальником не може бути регістр CS; не можна пересилати сегментні регістри: MOV ES, DS
Треба розписати:
MOV AX, DS
MOV ES, AX
не можна напряму ініціалізувати сегмент даних
DSEG SEGMENT
………………………
MOV DS, DSEG
Треба розписати:
MOV AX, DSEG
MOV DS, AX
довжина обох операндів повинна бути однаковою.
Команда Mov має розширену можливість: для випадку, коли довжина операндів різна використовується директива заначення типу: Тип PTR вираз
Оператор PTR може використовуватися з елементами даних, мітками інструкцій. Він використовує специфікатори типів Byte, Word, Dword, Tbyte для явного зазначення типу DB, DW, DD, DQ, DT для змінних. Він також використовує специфікатори типів NEAR, FAR, PROC для явного зазначення відстані до мітки перреходу. Таким чином, тип – це специфікатор типу, наприклад, BYTE, а вираз – це змінна або константа.
6.2 Арифметичні команди
6.2.1 Команда складання ADD (ADDition)
Синтаксис: ADD приймальник, джерело
Символьний код: ADD регістр/пам’ять, регістр/пам’ять/безпосереднє значення
Призначення: складання двох операндів джерела та приймальника розмірністю байт, слово або подвійне слово, записати результат складання за адресою першого операнда, встановити прапорці.
Ця операція є коректною при використанні операндів: регістр-регістр, регістр-пам’ять, пам’ять-пам’ять, пам’ять-безпосереднє значення.
Виконання команди додавання впливає на стан прапорців:
CF (Carry)– перенесення (зі старшого знакового розряду; наприклад, для байта в 9-му розряді при виконанні команди додавання з’явилася 1), PF (Parity)– парність, AF (Auxiliary)- допоміжне перенесення, ZF (Zero)– нуль, SF (Sign)– мінус, OF (Overflow)– переповнювання.
Команда ADD використовується для складання двох цілочисельних операндів. Якщо результат складання виходить за межі першого операнда (виникає переповнювання), то врахувати цю ситуацію слід шляхом аналізу прапорця CF і подальшого можливого застосування команди ADC. Наприклад, складемо значення в регістрі АХ і області пам'яті CHН. При складанні слід врахувати можливість переповнювання.
ADD AX, CНН ; додати значення з області пам’яті СНН до регістру АХ
ADD AX, CН ; додати регістр до регістру, результат записати в АХ.
ADD EBX, DBLWORD ; додати подвійне слово з пам’яті до регістру.
ADD BL, 10 ; додати 10 до молодшої частини регістра ВХ.
6.2.2 Команда складання двох операндів з урахуванням перенесенням з молодшого розряда ADC (ADDition with Carry)
Синтаксис: ADС приймальник, джерело.
Символьний код: ADС регістр/пам’ять, регістр/пам’ять/безпосереднє значення
Впливає на прапорці AF, CF, OF, PF, SF, ZF
Результат заноситься у перший операнд, в залежності від результату встановлюються прапорці.
Логіка роботи команди: <приймальник>=<приймальник>+<джерело>+<CF>
Команда ADC використовується при складанні багаторозрядних двійкових чисел. Її можна використовувати як самостійно, так і спільно з командою ADD. При спільному використанні команди ADC з командою ADD складання молодших байтів/слів/подвойних слів здійснюється командою ADD, а вже старші байти/слова/подвойні слова складаються командою ADC, що враховує перенесення з молодших розрядів в старші. Тобто команда ADC додає вміст прапорця перенесення CF (0 або 1) до першого операнда - приймальника, а потім додає до приймальника другий операнд – джерело.
6.2.3 Команда віднімання SUB (SUBtract)
Синтаксис: SUB операнд_1, операнд_2
Символьний код: SUB регістр/пам’ять, регістр/пам’ять/безпосереднє значення
Впливає на прапорці AF, CF, OF, PF, SF, ZF
Команда призначена для віднімання цілочислених операндів або для віднімання молодших частин значень багатобайтних операндів.
Віднімання здійснюється за методом складання з двійковим доповненням: для другого операнду встановлюється додатковий код (біти інвертуються +1), а потім відбувається складання з першим операндом. Операнд_2 віднімається від операнда_1, результат записується в операнд_1.
Команда SUB діє як приймальник = приймальник – джерело
SUB BL, 10; з регістру BL відняти значення 10, результат занести в BL
Виконання команди віднімання впливає на стан прапорців:
CF – перенесення (зі старшого знакового розряду; наприклад, для байта в 9-му розряді при виконанні команди додавання з’явилася 1), PF – парність, AF - допоміжне перенесення, ZF – нуль, SF – мінус, OF – переповнювання.
При відніманні прапорець CF діє як ознака зайняття.
6.2.4 Команда віднімання із зайняттям SBB (SuBtract with Borrow) або віднімання з перенесенням
Синтаксис: SBB операнд_1, операнд_2
Символьний код: SBB регістр/пам’ять, регістр/пам’ять/безпосереднє значення
Команда призначена для виконання цілочисленого віднімання старших частин значень багатобайтних операндів з урахуванням можливого попереднього зайняття при відніманні молодших частин значень цих операндів, коли виконувалося попереднє віднімання командами SBB та SUB (за станом прапорця перенесення CF).
Команда SBB спочатку віднімає вміст прапорця CF з операнда_1 та віднімає з операнда_1 операнд_2: приймальник = приймальник - джерело - перенесення.
6.2.5 Команда множення двох цілих двійковихчисел без урахування знаку MUL (MULtiply)
Команда перемножує два цілих числа без знаку.
Синтаксис: MUL множник_1
Символьний код: MUL регістр/пам’ять.
Команда MUL сприймає старший біт в якості біта даних , а не як біт знаку.
Алгоритм роботи команди залежить від формату операнду команди і вимагає явної вказівки місцеположення тільки одного співмножника, який може бути розташований в пам'яті або в регістрі (перший співмножник). Місцеположення другого співмножника фіксовано і залежить від розміру першого співмножника:
якщо операнд, вказаний в команді, — байт, то другий співмножник повинен розташовуватися в AL;
якщо операнд, вказаний в команді, — слово, то другий співмножник повинен розташовуватися в АХ;
якщо операнд, вказаний в команді, — подвійне слово, то другий співмножник повинен розташовуватися в EAX.
Результат множення поміщається також у фіксоване місце, яке визначається розміром співмножників:
при перемноженні байтів результат поміщається в АХ;
при перемноженні слів результат поміщається в пару DX:AX (молодші розряди - в AX, старші - в DX) і встановлюються прапорці переповнення и перенесення;
при перемноженні подвійних слів результат поміщається в пару ЕDX:EAX (молодші розряди - в ЕAX, старші - в ЕDX) і встановлюються прапорці переповнення и перенесення;
Контролювати розмір результату зручно, використовуючи прапорці CF або OF (прапорці AF, PF, SF, ZF –не визначено). Після виконання команди MUL прапорці CF і OF дорівнюються 0, якщо старша половина множення дорівнюється нулю; інакше обидва ці прапорці дорівнюються 1.
Множення і ділення це одні з найповільніших операцій процесорів сімейства 80х86 (особливо 8086 і 8088). Множення і ділення на константи, що часто зустрічаються, швидше відбувається при зсуві розрядів.
6.2.6 Команда множення двох цілих двійкових чисел з урахуванням знаку IMUL (Integer MULtiply)
Команда виконує цілочисельне множення операндів з урахуванням їх знакових розрядів. Команда сприймає старші(перші ліворуч) біти чисел в якості знаків (0 – позитивне число, 1 – негативне число). Для виконання цієї операції необхідно наявність двох співмножників. Розміщення і задання їх місцеположення в команді залежить від форми вживаної команди множення, яка, у свою чергу, визначається моделлю мікропроцесора. Так, для мікропроцесора i8086 можлива тільки однооперандна форма команди, для подальших моделей мікропроцесорів додатково можна використовувати двох- і трьохоперандні форми цієї команди.
Синтаксис: ІMUL множник_1
ІMUL множник_1, множник_2
ІMUL результат, множник_1, множник_2
Символьний код: ІMUL регістр/пам’ять
ІMUL регістр, безпосереднє значення (для 80286 і вище)
ІMUL регістр, регістр, безпосереднє значення (для 80286 і вище)
ІMUL регістр, регістр/пам’ять (для 80386 та вище)
Алгоритм роботи залежить від форми команди (однооперандна, двохоперандна або трьохопреандна):
Як і для команди MUL, вважається, що 2-й співмножник розташовується в регістрі AL (для операнда в команді - байта), в AX (для операнда в команді – слова), в EAX (для операнда –подвійне слово). Результат множення для команди з одним операндом розташовується в AX (при перемноженні двох байтів), в пару DX:AX (при перемноженні слів), в пару EDX:EAX (при перемноженні подвійних слів). Три інших формати використовують будь-який 16- або 32-розрядний регістр загального призначення, розміри елементів даних повинні бути однаковими.
Перший операнд (регістр) містить співмножник (множимое), саме в ньому з’являється результат множення, 2- операнд – множник (множитель), який має безпосереднє значення.
Перший операнд (регістр) вказує, де повинен знаходитися результат множеня; другий операнд (регістр або адреса пам’яті) містить співмножник (множимое), третій операнд містить безпосереднє значення.
Перший операнд (регістр) містить співмножник (множимое), саме у ньому з’являється результат; другий операнд (регістр або адреса пам’яті) – множник.
Команда imul встановлює в нуль прапорці OF і CF, якщо розмір результату відповідає регістру призначення. Якщо ці прапори відмінні від нуля, то це означає, що результат дуже великий для відведених йому регістром призначення рамок і необхідно вказати більший за розміром регістр для успішного завершення даної операції множення.
Інші прапорці AF, PF, SF, ZF є невизначеними.
6.2.7 Команда беззнакового ділення DIV (DIVide unsigned)
Команда призначена для ділення двох двійкових беззнакових чисел.
Синтаксис: DIV дільник
Символьний код: DIV регістр/пам’ять
Алгоритм роботи:
Для команди необхідно задати два операнди — ділене і дільника, беззнакове ділене ділить націло дільник. Ділене задається неявно і розмір його залежить від розміру дільника, який вказується в команді:
якщо дільник розміром в байт, то ділене повинно бути розташовано в регістрі АХ. Після операції частка поміщається в AL, а залишок — в AH;
якщо дільник розміром в слово, то ділене повинно бути розташовано в парі регістрів DX:AX, причому молодша частина діленого знаходиться в АХ. Після операції частка поміщається в АХ, а залишок — в DX;
якщо дільник розміром в подвійне слово, то ділене повинно бути розташовано в парі регістрів EDX:EAX, причому молодша частина діленого знаходиться в EAX. Після операції частка поміщається в EAX, а залишок — в EDX. Ділення на нуль викликає переривання.
6.2.8 Команда знакового цілочисельного ділення ІDIV (Integer DIVide signed)
Команда призначена для ділення двох двійкових чисел зі знаком, ділить знакове ділене націло на знаковий дільник. Команда ІDIV сприймає в якості знаку старші (перші ліворуч) біти (1- від’ємне число, 0 – позитивне число). Ділення на нуль викликає переривання.
Синтаксис: ІDIV дільник
Смвольний код: DIV регістр/пам’ять
Алгоритм роботи: Для команди необхідно задати два операнди — ділене і дільник. Ділиме задається неявно, і розмір його залежить від розміру дільника, місцезнаходження якого вказується в команді:
якщо дільник розміром в байт, то ділене повинно бути розташовано в регістрі АХ. Після операції частка поміщається в AL, а залишок — в AH;
якщо дільник розміром в слово, то ділене повинно бути розташовано в парі регістрів DX:AX, причому молодша частина діленого знаходиться в ах. Після операції частка поміщається в АХ, а залишок — в DX;
якщо дільник розміром в подвійне слово, то ділене повинно бути розташовано в парі регістрів EDX:EAX, причому молодша частина діленого знаходиться в eax. Після операції частка поміщається в EAX, а залишок — в EDX;
Впливає на стан прапорців AF, CF, OF, PF, SF, ZF.
Для збільшення розрядності знакового діленого використовується інструкція CBW (Convert Word to Doubleword) та MOVSX - команди перетворення слова у подвійне слово.
Виконання завдання
Код програми
; Лабораторна робота 6
; Виконала Чубукова А. О., гр. ТР-15, дата 04.06.2022
; Арифметичні команди
; Обчислення формули z = (2*c/d + 2)/(d - a*a - 1)
.model small ;модель пам’яті для ехе-файлів
.stack 100h ;виділяємо PSP 256 байт
.data ;початок сегменту даних
a dw 1 ;вихідні числа
c dw 8
d dw 4
message db 'Error! Division by zero$'
z dw ? ;невідома змінна
k dw ? ;допоміжні змінна для обчислень
n dw ?
.code ;початок сегменту коду
begin: ;точка входу
mov ax, @data
mov ds, ax
;k = a*a
mov ax, a
imul a
mov k, ax
;k = d - a*a
mov ax, d
sbb ax, k
mov k, ax
;Перевірка чи знаменник не дорівнює 0
cmp k, 1
je @error
;k = (d - a*a - 1)
dec ax
mov k, ax
;n = 2 * c / d
mov ax, 2 ;ax = 2
imul c ;ax *= c
cwd
idiv d ;ax /= d
adc ax, 2 ;ax += 2
mov n, ax
cwd
idiv k
mov z, ax
push ax
cmp ax, 0
jns @plus ;перевірка(число додатнє чи від’ємне)
mov ah, 02h
mov dl, '-' ;якщо число від’ємне, виводимо знак "-"
int 21h
pop ax
neg ax
@plus:
xor cx, cx ;лічильник остач
mov bx, 10 ;завантажуємо основу 10-ї системи числення
@dvsn:
xor dx, dx ;остача при ділені
div bx ;виконуємо ділення на 10
push dx ;результат у зворотньому порядку утворює число у новій системі счислення
inc cx ;збільшуємо лічильник
test ax, ax ;перевіряємо, чи ціла частина = 0
jnz short @dvsn ;ділимо, поки ціла частина не дорівнює 0
mov ah, 02h ;виводимо остачу
@print:
pop dx ;дістаємо зі стеку збережені числа
add dl, 30h ;переводимо їх в ASCII-коди
int 21h
loop @print ;повторюємо, поки СХ не дорівнює 0
jmp @end
@error:
mov ah, 09h ;вивід повідомлення про помилку, якщо знаменник рівний 0
mov dx, offset message
int 21h
@end: ;коректно завершуємо нашу програму, виходимо
mov ah, 4ch
int 21h
end begin ;кінець програми
Cтворення файлу *.exe в DOSBox:
/
Вигляд TD після запуску виконуваного файлу lab6.exe:
/
Після цього необхідно виконати програму натиснувши F9 і перейти у DOSBox комбінацією ALT+F5, щоб переглянути отриманий результат. На рисунку показано результат для таких значень: а=1, с=8, d=4.
/
Виконавши такі самі дії можна перевірити яким буде вивід, коли знаменник дорівнює нулю (наприклад при а=1, с=3, d=2):
/
Висновок: Під час виконання даної лабораторної роботи було освоєно такі арифметичні команди: MUL, IMUL, DIV, IDIV, ADD, ADC, INC, SUB, SBB, DEC, NEG, CBW, CWD. Крім цього виконано обчислення цілочислених арифметичних виразів відповідно до варіанту з використанням даних команд.