Міністерство освіти і науки УкраїниНаціональний технічний університет України
«Київський політехнічний інститут ім. І. Сікорського»
Кафедра автоматизації проектування енергетичних процесів і систем
Лабораторна робота №6
з дисципліни «Операційні системи»
«Система команд. Арифметичні команди. Обчислення цілочисельних арифметичних виразів з використанням команд MUL, IMUL, DIV, IDIV, ADD, AD»
Варіант №16
КИЇВ-2022
Мета: програмування блоку обчислення арифметичних виразів на прикладі реалізації математичних формул з використанням арифметичних команд асемблера за індивідуальними завданнями.
Теоретична частина:
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
довжина обох операндів повинна бути однаковою.
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.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.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.7 Команда беззнакового ділення DIV (DIVide unsigned)
Команда призначена для ділення двох двійкових беззнакових чисел.
Синтаксис: DIV дільник (делитель)
Смвольний код: DIV регістр/пам’ять
Алгоритм роботи:
Для команди необхідно задати два операнди — ділимого(делимого) і дільника(делителя), беззнакове ділиме ділить націло дільник. Ділиме задається неявно і розмір його залежить від розміру дільника, який вказується в команді:
якщо дільник розміром в байт, то ділиме повинно бути розташовано в регістрі АХ. Після операції частка (частное) поміщається в AL, а залишок — в AH;
якщо дільник розміром в слово, то ділиме повинно бути розташовано в парі регістрів DX:AX, причому молодша частина ділимого знаходиться в АХ. Після операції частка поміщається в АХ, а залишок — в DX;
якщо дільник розміром в подвійне слово, то ділиме повинно бути розташовано в парі регістрів EDX:EAX, причому молодша частина ділимого знаходиться в EAX. Після операції частка поміщається в EAX, а залишок — в EDX.
Наприклад, DIV BH ; байт
DIV CX ; слово
DIV ECX ; подвійне слово
Ділення на нуль викликає переривання.
Завдання:
Підготуйте теоретичну частину щодо використання команд, призначених для цілочисельних арифметичних виразів.
Підготуйте і налагодьте програму для обчислення простих формул за зразком. Продемонструйте роботу програми під керуванням налагоджувача, прокоментуйте вміст обчислюваних змінних.
Відповідно до варіантів підготуйте програми, що реалізують формули. Обчисліть вирази у знакових форматах довжиною 8 та 16 біт, використовуючи вищенаведені арифметичні операції. Виконайте тестові перевірки. Проаналізуйте результат.
Завдання згідно до варіанту: (c/d + 3*a/2)/(c - a + 1)
Код для завдання 16 варіанту з коментарями:
; Хавкін А.Д. гр. ТР-15 , 16 варіант
; Арифметичні команди
; Обчислення формули rez = (c/d + 3*a/2)/(c - a + 1)
.MODEL small
.Stack 100h
Datas segment
c dw 8 ; значення змінної c
a dw 4 ; значення змінної а
d dw 2 ; значення змінної d
k dw ? ; допоміжна змінна
l dw ? ; допоміжна змінна
rez dw ? ; змінна для результату
temp1 dw ? ; допоміжна змінна для обчислень
temp2 dw ? ; допоміжна змінна для обчислень
chis dw ? ; змінна для чисельника головного виразу (c/d + 3*a/2)
znam dw ? ; змінна для знаменника головного виразу (c - a + 1)
mess db "Error! Division by zero.$" ;повідомлення, якщо є ділення на 0
Datas ends
Codes segment
Assume cs:Codes, ds:Datas
start:
MOV ax, Datas ;ініціалізація регістру ds
mov ds, ax ;адресою сегмента даних
;if (c - a + 1) == 0->error , у випадку якщо є ділення на 0
mov ax, c ;c → ax
cwd ;команда перетворення слова у подвійне слово
sub ax,a ;c - а → ax
add ax,1 ;c - а + 1 → ax
cmp ax,0 ;перевіряємо, чи ах=0
je @err ;якщо так, то виводимо повідомлення про помилку
mov znam, ax;аx → znam
;c/d
mov ax,c ;c → ax
idiv d ;c/d → ax
mov temp1,ax ;аx → temp1
;3*a/2
mov ax, a ;а → ax
mov k, 3 ;3 → k
mov l, 2 ;2 → l
imul k ;a * k → ax
idiv l ;а * k / l → ax
cmp ax,0 ;перевіряємо, чи ах=0
je @err ;якщо так, то виводимо повідомлення про помилку
mov temp2,ax ;аx → temp2
;(c/d + 3*a/2)
mov ax,temp1 ;temp1 → ax
add ax, temp2 ;temp1 - temp2 → ax
mov chis,ax ;аx → chis
;(c/d + 3*a/2)/(c + a - 1)
mov ax,chis ;chis → ax
cwd ;команда перетворення слова у подвійне слово
idiv znam ;chis / znam → ax
mov rez, ax ;ax → rez
xor ax, ax ; обнуляємо регістр ах
mov ax, rez ;rez → ax
push ax ;зберігаємо в стек
cmp ax, 0 ;порівнюємо ах з 0
jns @plus ;перевіряємо число позитивне чи від’ємне
mov dl, '-'
mov ah, 02h ;число від’ємне, виводимо знак «-»
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 ;ділимо, поки ціла частина не дорівнює нулю
mov ah, 02h;виводимо остачу
@vivod: pop dx;дістаємо зі стеку збережені числа
add dl, 30h ;переводимо їх в ASCII-коди
int 21h
loop @vivod;повторюємо, поки СХ не дорівнює 0
jmp @end;вихід
@err: mov dx, offset mess;виведення повідомлення
mov ah, 09h ;про помилку
int 21h
@end: mov ax, 4c00h;коректно завершуємо нашу програму, виходимо
int 21h
Codes ends
end start
Створення *.EXE файлу та відкриття його у TD:
/
Вигляд TD після запуску lab6.exe :
/
Виконаємо програму покроково за допомогою F7 та перевіряємо проміжні результати у регістрі ax. Вигляд TD після проходження програми повністю:
/
Виведення в консольному режимі отриманого результату:
/
Вивело 2 з обраними вхідними даними, Результат було перевірено з обчисленнями за допомогою калькулятора, розбіжностей і помилок не знайдено.
Лістинг:
/
/
/
Висновок: У даній лабораторній роботі було освоєно та застосовано на пркатиці команди MUL, IMUL, DIV, IDIV, ADD, ADC, INC, SUB, SBB, DEC, NEG, CBW, CWD. За допомогою цих команд було запрограмовано блок обчислення арифметичних виразів за варіантом індивідуального завдання. Також було додатково використано команди CMP, PUSH, JMP. Зроблено звіт та надіслано викладачу.