Имеются 3 группы команд.
Первая группа: ADD, SUB,CMP, AND, TEST, OR, XOR
Эти типы операндов поддержаны:
REG, memory
memory, REG
REG, REG
memory, immediate
REG, immediate
REG: AX, BX, CX, DX, AH, AL, BL, BH, CH, CL, DH, DL, DI, SI, BP, SP.
memory: [BX], [BX+SI+7], variable, etc...
immediate: 5, -24, 3Fh, 10001101b, etc...
После операции между операндами, результат всегда сохраняется в первом операнде. Команды CMP и TEST затрагивают флажки только и не хранят результат (эта команда используется, чтобы принять решения в течение выполнения программы).
Эти команды затрагивают эти флажки только: CF, ZF, SF, OF, PF, AF.
ADD - Добавьте второй операнд к сначала.
SUB - Вычтите второй операнд к сначала
CMP - Вычтите второй операнд от сначала только для флажков
AND - Логический И между всеми битами двух операндов. Эти правила применяются:
1 AND 1 = 1
1 AND 0 = 0
0 AND 1 = 0
0 AND 0 = 0
Поскольку Вы видите, что мы добираемся 1 только, когда оба бита - 1.
TEST - Тот же самый как И но только для флажков
OR - Логический ИЛИ между всеми битами двух операндов. Эти правила применяются:
1 OR 1 = 1
1 OR 0 = 1
0 OR 1 = 1
0 OR 0 = 0
Поскольку Вы видите, что мы добираемся 1 каждый раз, когда по крайней мере один из битов - 1.
XOR - Логический XOR (исключительный ИЛИ) между всеми битами двух операндов. Эти правила применяются:
1 XOR 1 = 0
1 XOR 0 = 1
0 XOR 1 = 1
0 XOR 0 = 0
Поскольку Вы видите, что мы добираемся 1 каждый раз, когда биты отличаются от друг друга.
Вторая группа: MUL, IMUL, DIV, IDIV
Эти типы операндов поддержаны:
REG
memory
REG: AX, BX, CX, DX, AH, AL, BL, BH, CH, CL, DH, DL, DI, SI, BP, SP.
memory: [BX], [BX+SI+7], variable, etc...
MUL and IMUL Команды затрагивают эти флажки только: CF, OF
Когда результат - по размеру операнда, эти флажки установлены в 1, когда результат удовлетворяет в размере операнда, эти флажки установлены в 0.
Для DIV и IDIV Флажки неопределены.
MUL - Без знака умножаются:
Когда операнд - byte:
AX = AL * operand.
Когда операнд - word:
(DX AX) = AX * operand.
- IMUL – Число со знаком умножаются:
Когда операнд - byte:
AX = AL * operand.
Когда операнд - word:
(DX AX) = AX * operand.
DIV - Без знака делятся:
Когда операнд - byte:
AL = AX / operand
AH = remainder (modulus). .
Когда операнд - word:
AX = (DX AX) / operand
DX = remainder (modulus). .
IDIV – Число со знаком делится:
Когда операнд - byte:
AL = AX / operand
AH = remainder (modulus). .
Когда операнд - word:
AX = (DX AX) / operand
DX = remainder (modulus). .
Третья группа: INC, DEC, NOT, NEG
Эти типы операндов поддерживают:
REG memory
REG: AX, BX, CX, DX, AH, AL, BL, BH, CH, CL, DH, DL, DI, SI, BP, SP.
memory: [BX], [BX+SI+7], variable, etc...
INC, DEC Команды затрагивают только эти флажки: ZF, SF, OF, PF, AF.
NOT Команда не затрагивает никакие флажки
NEG Команда воздействует только на эти флажки:CF, ZF, SF, OF, PF, AF.
NOT - Полностью изменит каждый бит операнда
NEG - Делает операнд отрицательным (дополнение two's). Фактически это полностью изменяет каждый бит операнда и затем добавляет 1 к этому. Например 5 станет -5, и -2 станет 2
Проведение арифметических операции сложения, вычитания, умножения, деления, вычисления специальных функций рассмотрим на примерах соответствующих подпрограмм.
Подпрограмма 8.16
Адрес Машинный Метка Мнемокод Комментарии
код
0800 21 000В MAIN LXI Н, 0В00 написать в регистры Н, L адрес первого слагаемого
0803 06 05 MVI В, 0.5 нагрузить в регистр В количество слагаемых
0805 CD 0908 CALL ADDB вызвать подпрограмму сложения
0808 СF RST 1 прервать выполнение программы
0809 АF ADDB XRA А очистить аккумулятор
080А 4F MOV С, А очистить, счетчик переносов
080В 86 СNТ ADD M прибавить к содержимому аккумулятора число из массива слагаемых
080С D2 1008 INC TRM если переноса нет, то идти ну TRM
080F ОС INR С увеличить содержание регистра С на 1
0810 23 TRM INХ H указать на следующий адрес слагаемого
0811 05 DCR В уменьшить содержимое счетчика слагаемых
0812 D2 0В08 JNC CNT если не все слагаемые, то идти на СNT
0815 С9 RET
Программа сложения массива однобайтных чисел с получением двухбайтного результата — подпрограмма MAIN (подпрограмма 8.16). Слагаемые должны быть расположены в последовательных адресах памяти. Входными параметрами с подпрограммы ADDB являются адрес первого слагаемого, записанный в регистрах Н, L. и число слагаемых, записанное в регистре В. Выходным параметром программы MAIN является сумма, старший байт которой записан в регистре С, а младший — в аккумуляторе А.
Рис. 8.11. Алгоритм подпрограммы сложения (а) и умножения (б)
Алгоритм программы сложения состоит и том, что после прибавления каждого элемента массива определяется переполнение аккумулятора (разряд С-1), и если это имеет место, то содержимое регистра С увеличивается на 1. Таким образом, за счет суммирования единиц переноса получается старший байт суммы (рис. 8.11, а).
Микро-ЭВМ может проводить арифметические операции с числами с двойной или большей длиной машинного слова. Так как МП 8086 имеет 8-разрядное АЛУ, то операции с такими числами должны проводиться по байтам начиная с младших байтов. Так, операция сложения чисел 17F5 + 3411 будет проводиться в следующем виде:
Старший байт Флаг С Младший байт Числа
00101111 11110101 17F5
+ + +
00110100 00010001 3411
+ 1 1
01001100 00000110 4С06
Операция вычитания чисел 6F5C— 13С5 будет осуществляться в таком виде:
Старший байт Флаг С Младший байт Числа
01101111 01011100 6F5С
- - -
00010011 11000101 13С5
— 1 1
01011011 10010111 5В97
Из приведенных примеров видно, что при суммировании (вычитании) младших байтов чисел необходимо применять команду ADD (SUB), а для сложения (вычитания) остальных — команду ADC (SBB), которая будет учитывать состояние разряда регистра С признаков МП БИС.
Программа нахождения разности чисел, имеющих одинаковую длину,— программа 8.17. Входные параметры: регистр С — длина чисел (в байтах), регистры Н, L — адрес младшего байта вычитаемого, регистры D, Е — адрес младшего байта уменьшаемого. Каждое из чисел записывается в последовательных адресах памяти начиная с младших байтов. Результат заносится в область памяти, отведенную под вычитаемое. В том случае, если уменьшаемое меньше вычитаемого, будет подаваться звуковой сигнал.
Программа 8.17
Адрес Машинный Метка Мнемокод Комментарий код
0900 AF SBN XRA А очистить аккумулятор и флаг С
0901 1А CNT LDAX D записать в аккумулятор уменьшаемое
0902 9Е SBB М вычесть из содержимого аккумулятора вычитаемое
0903 77 MOV M, А записать разность на место вычитаемого
0904 23 INX Н указать на следующий байт вычитаемого
0905 13 INX D указать на следующий байт уменьшаемого
0906 0D DCR С уменьшить содержимое счетчика длины числа
0907 С2 0109 JNZ CNT если не последний (старший байт числа), то идти на CNT
090А D0 RNC если байт старший и результат без заема (С = 0), то возврат
0908 CD 1200 CALL BEEP если был заем (С = 1), подать сигнал
090Е CF RST 1 прервать выполнение программы
Выполнение команд MOV M, A; INX D не воздействует на разряд С. В программе SBN подпрограмма звукового сигнала (ВЕЕР) начинается с адреса 0012. При исследовании программы SBN необходимо перед началом выполнения ее осуществить начальную установку всех входных параметров.
Лекция 45
Умножение чисел. Существует несколько алгоритмов умножения чисел. При первом алгоритме умножение можно заменить многократным сложением, например 14-3 = = 14+14+14. Существенный недостаток этого способа — значительная длительность процесса вычисления. При втором алгоритме умножение осуществляется в столбец. Этот алгоритм применим и для умножения двоичных чисел, например
0110 = 610
0011 = 310
0000
00010010 = 1810
При вычислении результата по второму алгоритму необходимо осуществить многократное суммирование со сдвигом влево множимого при одновременной проверке содержимого разрядов множителя начиная со стороны его младшего разряда. При этом если в очередном разряде множителя записана 1, то множимое прибавляется к сумме и сдвигается влево на один разряд, а если в разряде записан 0, то произойдет только сдвиг множимого. Сдвиг множимого влево можно заменить сдвигом суммы вправо. По этому алгоритму (рис. 8.11, б) работает подпрограмма умножения двух однобайтных чисел с получением двухбайтного результата (подпрограмма 8.18). Начальный адрес подпрограммы — 04Е1; входные параметры: регистр D — множимое, регистр Е — множитель. Результат перемножения записывается в регистры В, С.
Подпрограмма 8.18
Адрес Машинный Метка Мнемокод Комментарий
код
04Е1 010000 MPL LXI B, 0000 очистить содержимое регистров В, С
04Е4 3Е 01 MVI А, 01 загрузить в аккумулятор указатель разряда
04Е6 А7 ANA А очистить флаг С
04Е7 F5 MPL 1 PUS H PSW сохранить указатель разряда в стеке
04Е8 A3 ANA E проверить содержимое очередного разряда множителя
04Е9 78 MOV А, В загрузить в аккумулятор старший байт суммы
04ЕА СА ЕС04 JZ MPL2 если в очередном разряде записан 0, идти на MPL 2
04ED 82 ADD D прибавить множимое к сумме
04ЕЕ IF MPL 2 RAR сдвинуть сумму вправо (младший бит ® С)
04EF 47 MOV В, А сохранить содержимое аккумулятора в регистре В
04F0 79 MOV А, С загрузить в аккумулятор младший байт суммы
04F1 IF RAR сдвинуть число в аккумуляторе вправо (С ® старший бит)
04F2 47 MOV С, А сохранить содержимое аккумулятора в регистре С
04F3 F1 POP PSW получить из стека указатель разряда
O4F4 17 RAL указатель на следующий разряд
04F5 D2 Е704 JNC MPL1 если разряд не последний, продолжать на MPL 1
04F8 С9 RET если разряд последний, возврат
Деление чисел. Деление двоичных чисел, как и чисел, представленных в любой другой системе счисления, основывается на последовательном вычитании делителя из делимого и остатков от деления. Однако двоичное деление реализуется проще, так как использование только двух цифр (0 и 1) исключает в каждом цикле деления необходимость определения числа делителей, содержащихся в текущем значении делимого или остатка (достаточно только сравнить их).
Схема алгоритма деления двоичных чисел приведена на рис. 8.12. Программа DIVB построена по этому алгоритму (программа 8.19). Входными параметрами этой программы являются делимое (в регистре Е) и делитель (в регистре D); выходными параметрами — частное (в регистре Н) и останов (в регистре С).
Рис. 8.12. Схема алгоритма подпрограммы деления двух восьмиразрядных чисел
Программа 8.19
Адрес Машинный Метка Мнемокод Комментарий
код
0900 21 0800 DIVB LXIH. 0008 загрузить счетчик битов (регистр L) и очистить регистр частного Н
0903 0Е 00 MVI С, 00 очистить регистр промежуточного делимого
0905 7В МХТ В MOV A, E загрузить делимое в аккумулятор
0906 17 RAL сдвинуть старший бит в разряд С
0907 5F MOV E, А возвратить делимое в регистр Е
0908 79 MOV А, С загрузить в аккумулятор промежуточное делимое из регистра С
0909 17 RAL сдвинуть разряд в младший бит
090А 92 SUB D вычесть из содержимого аккумулятора делитель
090В D2 0F 09 JNC NOADD если С = 1. восстановить содержимое аккумулятора
090Е В2 ADD D
090F 4F NOADD MOV С, А возвратить промежуточное данное в регистр С
0910 3F CMC инвертировать разряд С
0911 7С MOV A, H сдвинуть разряд С в младший бит регистра частного Н
0912 17 RAL
0913 67 MOV H, А
0914 2D DCRL проверены ли все восемь разрядов?
0915 С2 0509 JNZ МХТВ если нет, продолжать
0918 CF RST1 если да, прервать выполнение программы
Вычисление специальных функций. Для вычисления специальных функций (sinх, cosx, tgx, lnx, ) применяются специальные алгоритмы. Функции sin x, cos х, ln x можно вычислить, воспользовавшись их разложением в ряд:
Sin X = x - для любого x (рад);
cos х = 1 - для любого х (рад);
ln(1+x) = х - для 0 < x ≤ 1.
Число членов ряда определяется из условия получения требуемой точности.
Для вычисления функции с точностью до целых чисел можно применить алгоритм, основанный на том, что квадрат числа можно определить сложением последовательности нечетных чисел:
Число Сумма нечетных чисел Результат
1 1 = 1
2 1+3 = 22
3 1+3 + 5 = З2
4 1+3 + 5 + 7 = 42
5 1+3 + 5 + 7 + 9 = 52
Исходя из приведенного примера видно, что какое число необходимо возвести в квадрат, такое же количество последовательных нечетных чисел начиная с 1 необходимо сложить.
Вычисление специальных функций по приведенным выражениям занимает длительное время и обеспечивает низкую точность. Это обусловлено сравнительно небольшой длиной машинного слова и ограниченным быстродействием МП 8086. Поэтому в тех случаях, когда ставятся жесткие требования по быстродействию и точности, применяется вычисление функций с помощью таблиц. Проиллюстрируем этот метод на примере программы вычисления квадрата числа х (программа 8.20).
Программа 8.20
Адрес Машинный Метка Мнемокод Комментарий
код
0900 2600 SQ: MVI Н, 0 очистить регистр Н
0902 11 000А LXI D SQTB загрузить начальный адрес таблицы
0905 19 DAD D получить адрес элемента
0906 66 MOV H, M загрузить его в регистр Н
0907 CF RST 1 прервать выполнение программы
0А00 00 SQTB 00
0А01 01 01
0А02 04 04
0А03 09 09
0А04 10 10 таблица квадратов чисел
0А05 19 19
0А06 24 24
0А07 31 31
0А08 40 40
0А09 81 81
0АОА 64 64
Программа SQ определяет квадрат чисел от 0 до 10 включительно. Входной параметр программы — число х. Оно записывается в регистр L. Выходной параметр — значение х2 в регистре Н.
; This sample gets the number
; from the user, and calculates
; factorial for it.
; Supported input from 0 to 8
; inclusive!
#make_COM#
include 'emu8086.inc'
ORG 100h
start:
; get first number:
CALL PTHIS
DB 13, 10, 'Enter the number: ', 0
CALL scan_num
; factorial of 0 = 1:
MOV AX, 1
CMP CX, 0
JE print_result
; move the number to BX:
; CX will be a counter:
MOV BX, CX
MOV AX, 1
MOV BX, 1
calc:
MUL BX
CMP DX, 0
JNE overflow
INC BX
LOOP calc
print_result:
; print result in AX:
CALL PTHIS
DB 13, 10, 'Factorial: ', 0
CALL PRINT_NUM_UNS
JMP exit
overflow:
CALL PTHIS
DB 13, 10, 'The result is too big!', 13, 10, 'Use values from 0 to 8.', 0
JMP start
exit:
RET
;=================================
; here we define the functions
; from emu8086.inc
; SCAN_NUM reads a
; number from the user and stores
; it in CX register.
DEFINE_SCAN_NUM
; PRINT_NUM prints a signed
; number in AX.
; PRINT_NUM_UNS prints an unsigned
; number in AX (required by
; PRINT_NUM):
DEFINE_PRINT_NUM
DEFINE_PRINT_NUM_UNS
; PTHIS prints NULL terminated
; string defined just after
; the CALL PTHIS instruction:
DEFINE_PTHIS
;=================================
END
Лекция 46
Дата добавления: 2016-07-05; просмотров: 1677;