Ілюстрований самовчитель з Assembler. Арифметичні команди асемблера

Команда ADC(Add with Carry) належить до групи команд цілісної(або двійковій)арифметики (Binary Arithmetic Instructions) і виробляє ціле додавання двох знакових або беззнакових операндів ( DESTі SRC) та прапора перенесення EFLAGS.CF. Перший операнд ( операнд-призначення, DEST) може бути змінною в регістрі або в пам'яті ( , r16, r32 , r/m8, r/m16, r/m32). Другий операнд ( операнд-джерело, SRC) - Безпосереднім значенням ( imm8, imm16, imm32), змінної у регістрі чи пам'яті. При цьому обидва операнди одночасно не можуть бути змінними в пам'яті.

Результат складання командою ADCпоміщається на місце першого операнда ( DEST). Прапори в регістрі EFLAGS встановлюються відповідно до отриманого результату.

При додаванні безпосереднього значення imm8або imm16з двобайтним або чотирибайтним операндом безпосередня величина насамперед знакорозширюється до розміру першого операнда, і тільки після цього виконується додавання.

Команда ADCзазвичай використовується в багатобайтних або багатослівних ( multi-word) операціях складання. У такому разі вона йде слідом за командою ADD, яка повертає суму молодших розрядів багатобайтних (багатослівних) операндів, дозволяючи при складанні старших розрядів враховувати перенесення. Наприклад:

mov edx, 0; EDX = 0
mov eax, 0FFFFFFFFh; перший 32-бітовий доданок поміщаємо в EAX
add eax, 0FFFFFFFFh; другий 32-бітовий доданок - 0x FFFFFFFFh, виробляємо додавання двох 32-бітових операндів
adc edx, 0; EDX = EDX + CF, враховуємо перенесення
; EDX:EAX = 0000000lh:FFFFFFFEh - отриманий 64-бітовий результат

Команда ADCдозволяє маніпулювати цілими операндами як в беззнаковий формат, так і в формат зі знаком. При складанні даних зі знаком прапор знак EFLAGS.SF відображатиме знак отриманого результату. Прапор переповнення EFLAGS.OF встановиться в 1, якщо при складанні цілих значень зі знаком , представлених у зворотному коді або в додатковому коді , відбулося переповнення (перенесення зі старшого значущого розряду, якому відповідає біт, що передує розряду знака), тобто отриманий результат перевищує доступний розмір операнда -призначення ( DEST). По суті, це аналогічно до того, як прапор EFLAGS.CF відображає переповнення (перенесення) при додаванні беззнакових операндів. Наприклад, при додаванні двох 32-бітових значень, представлених у зворотному коді, це може виглядати наступним чином:

mov eax, operand1; EAX = operand1, перший 32-бітовий доданок поміщаємо в EAX
add eax, operand2; робимо додавання двох 32-бітних операндів у зворотному коді
into; перехід до обробника переривання у разі переповнення

adc eax, 0; EAX = EAX + CF, враховуємо перенесення (необхідно для складання у зворотному коді)
; EAX = operand1 + operand2 - результат додавання у зворотному коді
jns m1; перехід, якщо результат позитивний
xor eax, 7FFFFFFFh; перетворення негативного значення в EAX до прямого коду
m1:; EAX - результат складання в прямому коді

Прапор допоміжного(або додаткового)перенесення EFLAGS.AF допомагає маніпулювати даними у двійково-десятковому форматі ( упакований BCD-формат). Він встановлюється, якщо при додаванні виникає перенесення з молодшого зошита до старшого зошита молодшого байта результату. Використовуючи команду DAA відразу ж за командою ADC, можна зробити так звану десяткову корекціюрезультату складання та отримати суму в такому ж упакованому BCD-форматі, як і вихідні доданки.

Команда ADCз операндом-призначенням ( DEST), що є змінною пам'яті, може використовуватися спільно з префіксом блокування LOCK , який забезпечить атомарне виконання команди.

Команди складання - ADD, ADC

Команди ADD (add - скласти) і ADC (add with carry- скласти з перенесенням) можуть складати як 8-, і 16-бітові операнди.

Команда ADD складає вміст операнда-джерела та операнда-приймача і поміщає результат в операнд-приймач.

Формат команди: ADD приймач, джерело

У символічній нотації її дії можна описати так: приймач:= приймач + джерело (до приймача записується сума вмісту приймача та джерела).

Команда ADC робить те саме, що і команда ADD, але складає не два, а три доданки: приймач, джерело та прапор переносу.

Формат команди: ADC приймач, джерело + CF

У символічній нотації її дії можна описати як:

приймач: = приймач + джерело + вміст прапора перенесення.

Перенесення при додаванні двійкових чисел аналогічне переносу при додаванні десяткових чисел у стовпчик. Коли ЕОМ складає двійкові числа та сума не міститься в операнді-приймачі, то генерується перенесення. Як відомо, 8-бітовий регістр може містити значення без знака в діапазоні від 0 до 255. Якщо ми, наприклад, виконаємо двійкове додавання чисел 250 і 10, то отримаємо наступний результат:

1111 1010; двійкове уявлення числа 250.

0000 1010 ; двійкове уявлення числа 10.

100000100; двійкове подання суми, що дорівнює 260.

Результат є вірним, але займає 9 двійкових бітів. Якщо використовувалися 8 - бітові регістри, то молодші 8 бітів будуть занесені в регістр-приймач, а дев'ятий біт - прапор переносу CF.

Тепер зрозуміло, чому мікропроцесор 8086 має дві різні команди додавання. Одна з них (ADD) може складати значення, що надаються байтами або словами, а також молодші частини значень підвищеної точності. Інша команда (ADC) використовується для додавання старших частин значень підвищеної точності.

Операнди, що складаються, можуть перебувати в пам'яті, регістрі або мати безпосереднє значення. Наприклад:

ADD АХ, MEM_WORD; додати вміст осередку пам'яті до регістру,

ADD MEM_WORD,AX; або навпаки, додати вміст регістру до осередку пам'яті.

ADD AL, 10; додати константу до вмісту регістру.

ADD MEM_BYTE,8H; скласти константу та вміст осередку пам'яті.

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

Команди ADD та ADC можуть впливати на наступні шість прапорів:

прапор перенесення CF дорівнює 1, якщо результат додавання не міститься в операнді-приймачі, в іншому випадку він дорівнює 0;

прапор парності PF дорівнює 1, якщо результат має парне число бітів зі значенням 1, інакше він дорівнює 0;

AF дорівнює 1, якщо результат додавання десяткових чисел вимагає корекції;

прапор нуля ZF дорівнює 1, якщо результат дорівнює 0;

прапор знак SF дорівнює 1, якщо результат від'ємний (старший біт дорівнює 1), інакше він дорівнює 0;

прапор переповнення OF дорівнює 1, якщо доданок двох чисел одного знака перевищує діапазон допустимих значень приймача у зворотному коді, а сам приймач змінює при цьому знак. Інакше прапор OF дорівнює 0.

Команда збільшення значення приймача на одиницю – INC

Команда INC(increment - збільшити) додає 1 до вмісту регістру або комірки пам'яті, але на відміну команди ADD не впливає на прапор переносу CF. Формат команди: INC приймач.

Команда INC зручна збільшення значень лічильників у циклах команд. Її можна використовувати і для збільшення значення індексного регістру при доступі до послідовно розташованих осередків пам'яті. Операнд інтерпретується як без знака.

Наприклад:

INC CX; збільшити значення 16-бітового

INC AL; чи 8-бітового регістру на одиницю.

INC MEM_BYTE; збільшити значення байта

INC MEM_WORD; чи слова пам'яті на одиницю.

Не допускається використовувати як операнда безпосереднє значення.

Команди віднімання - SUB, і віднімання із позикою SBB

Команди SUB(substract - відняти) та SBB(substract with borrow - відняти з позикою) аналогічні відповідно до команд складання ADD і ADC, тільки при відніманні прапор переносу CF діє як ознака позики. Формат команди: SUB приймач, джерело;

Команда SUB віднімає операнд-джерело з операнда-приймача і поміщає результат у приймач, у символічній нотації:

приймач: = приймач - джерело.

Команда SBBробить те саме, але додатково віднімає з приймача значення прапора переносу CF:

SUB приймач, джерело - СF;

Приймач: = приймач – джерело – вміст прапора перенесення.

Як і у випадку додавання, команди SUB та SBB виконують дві окремі функції. Перша команда віднімає числа розміром у байт або слово, а також молодші біти чисел підвищеної точності (молодша частина числа розташована в регістрі АХ, а старша частина в регістрі DX). Друга команда віднімає старші біти чисел підвищеної точності. Наприклад, команда SUB AX, CX; віднімає вміст регістру СГ із вмісту регістру АХ і повертає результат у регістр АХ.

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

SUB АХ, CX; Відняти молодші 16 біт;

SBB BX, DX; потім старші 16 біт.

Тут ми віднімаємо з 32-бітового числа, поміщеного в регістри АХ і ВХ, 32-бітове число, що знаходиться в регістрах СГ і DX. При відніманні вмісту регістру DX з вмісту регістру ВХ команда SBB враховує можливість позики при виконанні першого віднімання.

SUB АХ, MEM; Відняти з регістра вміст комірки пам'яті.

SUB MEM, AX; Відняти з комірки пам'яті регістр.

SUB AL,1O; Відняти константу з регістру.

SUB MEM_BYTE,OFh; Відняти константу з комірки пам'яті.

Не можна безпосередньо віднятивміст одного осередку пам'яті з іншого або використовувати безпосереднє значення як приймач.

Команди SUB та SBB можуть впливати на шість прапорів таким чином:

· Встановлюють прапор перенесення CF в 1, якщо потрібна позика, в іншому випадку він дорівнює 0;

· Встановлюють прапор парності PF в 1, якщо результат віднімання має парне число бітів зі значенням 1, інакше він дорівнює 0;

· Встановлюють допоміжний прапор перенесення AF в 1, якщо результат віднімання десяткових чисел вимагає корекції, інакше він дорівнює 0;

· Встановлюють прапор нуля ZF в 1, якщо результат дорівнює 0, інакше він дорівнює 0;

· Встановлюють прапор знак SF в 1, якщо результат від'ємний (старший біт дорівнює 1), інакше прапор дорівнює 0;

· Встановлюють прапор переповнення OF в 1, якщо при відніманні результат перевищує діапазон значень приймача у зворотному коді, а сам приймач змінює знак.

Прапори SF і OF мають сенс тільки при відніманні чисел зі знаком, а прапор AF- тільки при відніманні десяткових чисел.

Команда зменшення вмісту приймача - DEC

Команда DEC приймач(decrement-зменшити) віднімає 1 із вмісту регістру або комірки пам'яті, але при цьому (на відміну від команди SUB) не впливає на прапор переносу CF.

Команда DEC часто використовується в циклах для зменшення значення лічильника, поки воно не стане нульовим або негативним. Її можна використовувати також для зменшення значення індексного регістра або покажчика при доступі до послідовно розташованих осередків пам'яті. Наприклад:

DEC CX; Зменшити значення 16-бітового,

DEC AL; або 8-бітового регістру.

DEC MEM_BYTE; Зменшити значення байтової,

DEC MEM_WORD; або ніби комірки пам'яті.

Команди поділу - DIV, IDIV

Команда DIV(divide – розділити) виконує розподіл чисел без знака, а команда IDIV(integer divide - розділити цілі числа) виконує розподіл чисел зі знаком. Ці команди мають формат:

DIV джерело; де джерело- дільник розміром байт або слово,

IDIV джерело;що знаходиться в регістрі загального призначення або в осередку пам'яті.

Зверніть увагу на таке:

1. Подільне по відношенню до дільника повинно мати подвійний розмір.

2. Ділене завжди повинно знаходитися в регістрі АХ (при розподілі на 8-бітове число) або в регістрах DX і АХ (при розподілі на 16-бітове число).

3. Результати команди повертаються так:

· Якщо операнд-джерело є байт, то приватне повертається в регістр AL, а залишок в регістр АН;

· Якщо операнд-джерело є слово, то приватне повертається в регістр АХ, а залишок - в регістр DX.

Обидві команди залишають стан прапорів невизначеними, але якщо приватне не міститься в регістрі-приймачі (AL або АХ), мікропроцесор генерує переривання типу 0 (розподіл на 0).

4. Переповнення результату поділу виникає за таких умов:

· Дільник дорівнює 0;

· При розподілі байтів без знака ділене щонайменше в 256 разів перевищує дільник;

· при розподілі слів без знака ділене щонайменше в 65 536 разів перевищує дільник;

· При розподілі байтів зі знаком приватне лежить поза діапазоном -128 до +127;

· при розподілі слів зі знаком приватне лежить поза діапазоном від

32768 до 32767.

Наведемо кілька типових прикладів операцій розподілу:

DIV BX; Розділити DX:AX на ВХ без знака.

DIV MEM_BYTE; Розділити АХ на байт пам'яті без знака.

IDIV DL; Розділити АХ на DL зі знаком.

IDIV MEM WORD; Розділити DX:AX на слово пам'яті зі знаком.

Команди DIV і IDIV неможливо прямо розділити на безпосереднє значення, оскільки процесор неспроможна визначити тип даних дільника.

Команди множення – MUL, IMUL

Команда MUL(multiply-помножити) множить числа без знака, a IMUL(integer multiply-множити) множить цілі числа зі знаком. Множина і множник в обох команд мають бути дані одного типу, тобто байти, слова, подвійні слова і т.д.

Ці команди мають наступний формат:

MUL джерело; де джерело- Регістр загального призначення,

IMUL джерело; або комірка пам'яті розміром байт або слово.

В якості першого операнда (множинного) команди MUL та IMUL використовують вміст регістру AL (при операціях над байтами) або регістра АХ (при операціях над словами). Твір має подвійний розмір і повертається так:

· множення байтів-Повертає 16-бітове твір в регістри АН (старший байт) та AL (молодший байт);

· множення слів-Повертає 32-бітове твір в регістри DX (старше слово) і АХ (молодше слово). Таким чином, розмір твору n- бітних співмножників дорівнює 2n.

ADC Цілочисленне додавання з перенесенням

Команда adcздійснює додавання першого та другого операндів, додаючи до результату значення прапора переносу CF. Вихідне значення першого операнда (приймача) втрачається, заміщаючись результатом складання. Другий операнд не змінюється. Як перший операнда команди adc

Операнди можуть бути байтами або словами та представляти числа зі знаком або без знака. Команда adc(разом із командою add) зазвичай використовується для складання 32-розрядних чисел. Команда впливає на прапори OF, SF, ZF, AF, PF та CF.

Приклад 1:

Mov AX, 1125h adc AX, 2C25h; AX=3D4Bh, якщо CF був = 1; AX=3D4Ah, якщо CF був = 0

Приклад 2:

; У полях даних: numlow dw 0FFFFh; Молодша частина 2-го доданку numhigh dw 000Sh; Старша частина 2-го доданку; Число 0005FFFFh = 393215; У програмному сегменті: mov AX,000Sh; Молодша частина 1-го доданку mov BX,0002h; Старша частина 1-го доданку; Число 00020005h = 131077 add АХ, numlow; Додавання молодших частин. АХ = 4, CF = 1 adc BX, numhigh; Додавання старших частин з перенесенням. ВХ: АХ = 0008: 0004h. ;Кількість 00080004h=524292

Допустимо використання 32-бітових операндів та додаткових режимів адресації 32-розрядних процесорів. Команда adcз 32-розрядними операндами може використовуватися до складання 64-розрядних цілих чисел.

приклад:

; У полях даних mem321 dd 0FFFFFFFFh; Молодша частина 1-го доданку mem32h dd 98765432h; Старша частина 1-го доданку; У програмному сегменті mov EAX,1; Молодша частина 2-го доданку mov EBX,0; Старша частина 2-го доданку add EAX, mem321; Складаємо молодші половини; Сума = 100000000h> 32 біт; EAX = 000000h, перенесення adc EBX, mem32h; Складаємо старші половини та перенесення. EBX=90000001h; Сума: 9876543300000000h

ADD Цілочисленне додавання

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

Операнди можуть бути байтами або словами та представляти числа зі знаком або без знака. Команду add можна використовувати для складання як звичайних цілих чисел, так і двійково-десяткових (з використанням регістру АХ для збереження результату). Якщо складаються невпаковані двійково-десяткові (BCD) числа, після команди addслід використати команду ааа; якщо складаються упаковані числа, то команду daa. Команда впливає на прапори OF, SF, ZF, AF, PF та CF.

Приклад 1:

Mov BX,lFFEh mov CX,3 add BX,CX; BX = 2001h, CX = 0003h

Приклад 2:

Mov AX, 25h add AX, 12h; AX=0037h

Приклад 3:

; У полях даних: mem dw 128; B програмному сегменті: add mem,100; mem = 228

ADC Цілочисленне додавання з перенесенням

Команда adc здійснює додавання першого і другого операндів, додаючи до результату значення прапора переносу CF. Вихідне значення першого операнда (приймача) втрачається, заміщаючись результатом складання. Другий операнд не змінюється. В якості першого операнда команди adc можна вказувати регістр (крім сегментного) або комірку пам'яті, як другий - регістр (крім сегментного), комірку пам'яті або безпосереднє значення, проте не допускається визначати обидва операнди одночасно як комірки пам'яті. Операнди можуть бути байтами або словами та представляти числа зі знаком або без знака. Команда adc (разом з командою add) зазвичай використовується для додавання 32-розрядних чисел. Команда впливає на прапори OF, SF, ZF, AF, PF та CF.

Приклад 1

Mov AX,1125h adc AX,2C25h ;AX=3D4Bh, якщо CF був = 1 ;AX=3D4Ah, якщо CF був = 0
Приклад 2; У полях даних: numlow dw 0FFFFh; Молодша частина 2-го доданку numhigh dw 000Sh; Старша частина 2-го доданку; Число 0005FFFFh = 393215; У програмному сегменті: mov AX,000Sh; 0; Старша частина 1-го доданку; Число 00020005h = 131077 add АХ, numlow; Додавання молодших частин. АХ=4, CF=1 adc BX, numhigh ;Складання старших частин з;переносом.ВХ:АХ=0008:0004h. ;Кількість 00080004h=524292
Допустимо використання 32-бітових операндів та додаткових режимів адресації 32-розрядних процесорів. Команда adc з 32-розрядними операндами може використовуватися для додавання 64-розрядних цілих чисел. Приклад 3; У полях даних mem321 dd 0FFFFFFFFh; Молодша частина 1-го доданку mem32h dd 98765432h; Старша частина 1-го доданку; У програмному сегменті mov EAX,1; Молодша частина 2-го доданку mov EBX,0; Старша частина 2-го доданку add EAX, mem321; Складаємо молодші половини; Сума = 100000000Ь> 32 біт; ;Складаємо старші половини;і перенесення. EBX=90000001h ;Сума: 9876543300000000h
ADD Цілочисленне додавання

Команда add здійснює складання першого та другого операндів. Вихідне значення першого операнда (приймача) втрачається, заміщаючись результатом складання. Другий операнд не змінюється. В якості першого операнда команди add можна вказувати регістр (крім сегментного) або осередок пам'яті, як другий - регістр (крім сегментного), осередок пам'яті або безпосереднє значення, проте не допускається визначити обидва операнда одночасно як осередки пам'яті. Операнди можуть бути байтами або словами та представляти числа зі знаком або без знака. Команду add можна використовувати для складання як звичайних цілих чисел, так і двійково-десяткових (з використанням регістру АХ для збереження результату). Якщо складаються невпаковані двійково-десяткові (BCD) числа, після команди add слід використовувати команду ааа; якщо складаються упаковані числа, команду daa. Команда впливає на прапори OF, SF, ZF, AF, PF та CF. Приклад 1

Mov BX,lFFEh mov CX,3 add BX,CX ;BX=2001h, CX=0003h
Приклад 2 mov AX,25h add AX,12h ;AX=0037h
Приклад 3; У полях даних: mem dw 128; B програмному сегменті: add mem, 100; mem = 228
Приклад 4 mov AX,0507h ;BCD розпакований 57 add AL,05h ;BCD 5, AX=050Ch aaa ;AX=0602h, BCD 62
Приклад 5 mov AL,57h ;BCD упаковане 57 add AL,05h ;BCD 5, AL=5Ch daa ;AL=62h, BCD 62

Допустимо використання 32-бітових операндів та додаткових режимів адресації 32-розрядних процесорів. приклад

Mov EAX, 98765432h add EAX, 11111111h ; EAX=A9876543h
AND Логічне І

Команда and здійснює логічне (побітове) множення першого операнда другого. Вихідне значення першого операнда (приймача) втрачається, заміщаючись результатом множення. В якості першого операнда команди and можна вказувати регістр (крім сегментного) або комірку пам'яті, як другий - регістр (крім сегментного), комірку пам'яті або безпосереднє значення, проте не допускається визначати обидва операнди одночасно як комірки пам'яті. Операнди можуть бути байтами чи словами. Команда впливає на прапори SF, ZF та PF. Правила побітового множення:

Перший операнд-біт 0101 Другий операнд-біт 0011 Біт результату 0001 Приклад 1 mov AX,0FFEh і AX,5555h ;AX=0554h Приклад 2; У полях даних: mem dw 0С003h; У програмному сегменті: mov AX,700Eh and AX,mem; AX=4002h

Допустимо використання 32-бітових операндів та додаткових режимів адресації 32-розрядних процесорів. приклад

Mov EDX, 0FA8 8 0 0 4 lh and EDX,0FF00000Fh ; EDX = FA000001h
386P+ ARPL
Корекція запитуваного рівня привілеїв селектора

Команда aprl порівнює селектор із зразком, що містить максимально допустимий рівень привілеїв (зазвичай використовується селектор CS) і встановлює значення, що перевіряється відповідно до меншого з двох рівнів привілеїв. Якщо зміна рівня не знадобилася, прапор ZF скидається, якщо знадобилося - встановлюється. В якості першого операнда команди aprl може використовуватися 16-розрядний регістр або слово пам'яті з селектором, що перевіряється; як другий операнда - 16-розрядний регістр з селектором-зразком. 386+ BOUND
Перевірка індексу масиву на вихід за межі масиву

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

Асемблер- Асемблер для чайників

Асемблер для чайників.(#2) (C) Михайло Спіцин 1995Прапори Регістр "F" процесора називається прапоровим. Що це таке? Прапор - це змінна, яка може мати два стани, - встановлено (одно одиниці) і скинуто (рівно нулю). Тому регістр "F" можна як набір восьми прапорних бітів. Ми можемо використовувати лише чотири з них: прапор нуля, прапор перенесення, прапор знака та прапор парності-переповнення.Арифметичні операції. Арифметика - наука дуже корисна, ми постійно щось вважаємо: складаємо, віднімаємо, ділимо, множимо. Про те, як це зробити на асемблері, ми зараз і поговоримо. Почнемо ми з найпростішого, додамо одиницю до чогось, наприклад до регістру "А": ****************************** ** LD A,NUBER INC A RET ******************************** Як бачите, це дуже просто, для цього існує команда "INC" - інкремент (збільшення на одиницю), після неї йде операнд, тобто. який-небудь регістр або реєстрова пара: ******************************** INC A INC HL INC H INC DE INC E INC IY INC E INC (HL) INC (IX+N) INC (IY+N) ****************************** ** Якщо Вам потрібно збільшити на одиницю якийсь осередок пам'яті, то слід вчинити так: ***************************** *** LD HL, ADDRES LD IX, ADDRES INC (HL) INC (IX + 0) RET RET *************************** ***** Перший варіант працює швидше і зручніший, якщо робота йде з одним осередком пам'яті, але якщо ви працюєте в таблиці, то це не економічно і некрасиво. Порівняйте: нам потрібно збільшити на одиницю перший, п'ятий і десятий байти у таблиці: ******************************** LD HL, TABL+1 LD IX, TABL INC (HL) INC (IX+1) LD HL, TABL+5 INC (IX+5) INC (HL) INC (IX+10) LD HL, TABL+10 RET INC (HL) RET ******************************** Все, що сказано вище про збільшення на одиницю, справедливе і для декременту, тобто. для зменшення на одиницю: ******************************** DEC A DEC HL DEC L DEC E DEC BC DEC D DEC IY DEC C DEC IX DEC B DEC (HL) DEC (IX+N) DEC (IX+N) ********************* *********** А тепер припустимо, що нам треба збільшити регістр "A" не на одиницю, а скажімо, на десять: ***************** *************** LD A,NUMBER ADD A,10 RET ************************** ****** Складати можна регістр "A" з числом та іншими регістрами та з коміркою пам'яті, адресованої регістровими парами "HL", "IX" та "IY". Також можна складати регістрові пари з "HL", "IX" та "IY". (PureBasic - файлова система) ******************************** ADD A,N ADD A,(HL) ADD A ,A ADD A,(IX+N) ADD A,B ADD A,(IY+N) ADD A,C ADD HL,HL ADD A,D ADD HL,BC ADD A,E ADD HL,DE ADD A,H ADD HL,SP ADD IX,IX ADD IX,BC ADD IX,DE ADD IX,SP ****************************** ** Як бачите, набір команд досить великий. При виконанні цієї команди може виникнути помилка: ******************************** LD A,45 LD B,230 ADD A ,B RET ******************************** Сума "А" та "В" перевищила 255 і тому в "А виявиться не 275, а 20 (регістр "А" не гумовий); щоб ми знали, що відбулося переповнення, процесор встановлює прапор перенесення в одиницю. Залишається лише перевірити його. Подібно до того, як у "INC" є "DEC", у "АDD" теж є "парочка", це "SUB", і вона має свої особливості. Команда "SUB" працює тільки з реєстром "А", тому при написанні мнемоніки цієї команди "А" опускається: ********************* *********** SUB N SUB C SUB A SUB H SUB B SUB D SUB E SUB (HL) SUB (IX+N) SUB (IY+N) ********* *********************** Команда впливає на прапор переносу так само, як і "АDD". Окрім пари команд "ADD" та "SUB" існують ще одна пара. Команди " ADC " і " SBC " працюють із урахуванням прапора перенесення, тобто. при додаванні або відніманні до результату додається (віднімається) значення прапора перенесення. Для встановлення прапора перенесення є дві спецкоманди - це "SCF" та "CCF". "SCF" – встановити прапор переносу в одиницю. "CCF" - встановити прапор переносу в нуль. ******************************** ADC A,N SBC A,N ADC A,A SBC A,A ADC A ,H SBC A,H ADC A,L SBC A,L ADC A,D SBC A,D ADC A,E SBC A,E ADC A,B SBC A,B ADC A,C SBC A,C ADC A,( HL) SBC A, (HL) ADC A, (IX + N) SBC A, (IX + N) ADC A, (IY + N) SBC A,) IY + N) ADC HL, HL SBC HL, HL ADC HL ,BC SBC HL,BC ADC HL,DE SBC HL,DE ADC HL,SP SBC HL,SP **************************** **** А тепер приклади роботи команд "ADC" та "SBC" : ******************************* * LD A,10 LD A,10 LD B,5 LD B,5 CCF CCF SBC A,B ADC A,B RET RET A=5 B=5 A=15 B=5 ********* *********************** Замість двох команд "CCF" і "SBC A,B" можна поставити просто "SUB B", результат буде той же . ******************************** LD A,10 LD A,10 LD B,5 LD B,5 SCF SCF SBC A,B ADC A,B RET RET A=4 B=5 A=16 B=5 **************************** **** Як видно з результатів, прапор перенесення значно впливає на результат операції. При відніманні він віднімається від результату, а при додаванні додається до результату. За операціями складання та віднімання розказано майже все, тепер ми поговоримо про поділ і множення. На жаль, SPECCY не має команд розподілу та множення, але ці команди можна становити з кількох інших. Наприклад, нам потрібно перемножити вміст двох регістрів - "А" і "C": ***************************** *** LD A,10 LD C,5 LD B,A XOR A LOOP ADD A,C DJNZ LOOP RET ************************* ******* У прикладі зустрічаються дві нові команди - "XOR A" та "DJNZ LOOP". "XOR A" обнуляє регістр "А", а команда "DJNZ LOOP" повторює всі команди, з команди, поміченою міткою (наприклад "LOOP"), до команди "DJNZ" (після неї повинна стояти та ж мет- ка, що і на початку циклу); число повторень задається у регістрі "В". Використовуючи те, що множення M на N - це додавання числа М саме з собою N разів, Ви можете розібратися з прикладом, наведеним вище. Можна використовувати це властивість і для поділу. Спробуйте зробити це самі. Наступного разу поговоримо про команди порівняння та роботи з бітами.________________________________

Інші статті номера:





Top