2.1. АРИФМЕТИЧЕСКИЕ КОНСТРУКЦИИ 2.1.1. Сложение без учета флага переноса.
1. Прибавить к аккумулятору содержимое ячейки памяти. ADD A, (ADDR) LD HL, ADDR - указание на адрес
ADD A,(HL) - сложение
2. Десятиричное прибавление числа к аккумулятору. DADD A,N ADD A,N - сложение
DAA - перевод в десятиричную
форму
3. Десятиричное прибавление содержимого регистра к аккумулятору.
DADD A,reg ADD A,reg - сложение
DAA - перевод в десятиричную
форму
4. Прибавить 16-битное число к содержимому рег.пары HL. ADD HL, NN LD rp, NN - загрузка числа в ВС или DE.
ADD HL,rp - сложение
5. Прибавить 16-битное число к содержимому индексного регистра.
ADD xy,NN LD rp,NN - загрузка числа
ADD xy,rp - сложение
Регистровой парой может быть либо ВС либо DE.
6. Прибавить к регистру HL содержимое адреса двух смежных ячеек памяти.
ADD HL,(ADDR) LD rp,(ADDR) - загрузка числа
ADD HL,rp - сложение
7. То же, но для индексного регистра.
ADD xy, (ADDR) LD rp, (ADDR) - загрузка числа
ADD xy,rp - сложение
8. Прибавить содержимое ячеек памяти ADDR1, ADDR1+1 к содержимому ячеек памяти ADDR2, ADDR2+1.
ADD (ADDR2) , (ADDR1) LD HL, (ADDR2 ) - взять содержимое ADDR2
LD DE, (ADDR1) - взять содержимое ADDR1 ADD HL,DE - сложить их
LD (ADDR2) , HL - поместить сумму в ADDR2
9. Прибавить 16-битное число к содержимому адреса.
ADD (ADDR) , NN LD HL, (ADDR) - взять содержимое адреса
LD DE,NN - взять число
ADD HL,DE - сложить их
LD (ADDR) , HL - поместить сумму в адрес. 2.1.2. Сложение с учетом флага переноса.
10. Прибавить содержимое адреса к аккумулятору с учетом переноса.
ADC A, (ADDR) LD HL, ADDR - указание на адрес
ADC A, (HL) - сложение с учетом переноса
11. Прибавить к аккумулятору содержимое флага (переноса) .
ADC A,0
12. Десятиричное прибавление числа к аккумулятору с учетом флага переноса.
DADC A,N ADC A, N
DAA
13. Десятиричное прибавление содержимого регистра к аккумулятору с учетом флага переноса.
DADC A,reg ADC A,reg
DAA
14. Прибавление 16-битного числа к HL с учетом переноса. ADC HL,NN LD rp,NN
ADC HL, rp
15. Прибавление к регистру HL содержимого адреса с учетом переноса
ADC HL, (ADDR) LD rp, (ADDR)
ADC HL, rp
2.1.3. Команды вычитания без учета двоичного займа.
16. Вычесть содержимое адреса из аккумулятора. SUB (ADDR) LD HL, ADDR
SUB (HL)
17. Десятиричное вычитание числа из аккумулятора DSUB N SUB N
DAA
18. Десятиричное вычитание содержимого регистра из аккумулятора.
DSUB reg SUB reg
DAA
19. Вычесть содержимое регистровой пары из HL.
SUB HL,rp AND A - сброс флага переноса
SBC HL,rp - само вычитание
Необходимость во введении этой конструкции вызвана тем, что простого вычитания содержимого регистровой пары из HL без учета флага переноса в системе команд Z-80 нет. Приходится применять SBC, но предварительно обнулять флаг переноса.
2.1.4. Обратное вычитание.
20. Вычесть аккумулятор из числа, и результат поместить в аккумулятор.
SUB N,A NEG - изменение знака аккумулятора
ADD A,N - сложение (вместо вычитания)
ИЛИ
LD reg,A - запомнили аккумулятор LD A, N - ввели число в аккумулятор SUB reg - вычитание
21. Вычесть аккумулятор из регистра и результат поместить в аккумулятор.
SUB reg,A NEG
_ ADD A, reg
22. Десятиричное вычитание аккумулятора из числа. DSUB N,A LD reg,A - запомнили аккумулятор
LD A,N - ввели число
SUB reg - вычитание
DAA - перевод в десятиричную форму
23. Десятиричное вычитание аккумулятора из регистра. DSUB reg,A LD reg1,A
LD A,reg SUB reg1 DAA
2.1.5. Вычитание с двоичным займом (с учетом флага переноса)
24. Вычесть содержимое адреса из аккумулятора. SBC A, (ADDR) LD HL, ADDR - указали на адрес
SBC A, (HL) - вычитание с учетом флага C
25. Вычесть состояние флага С из аккумулятора.
SBC A,0
2 6.Десятиричное вычитание числа из аккумулятора с учетом C DSBC A, N SBC A, N
DAA
27. Десятиричное вычитание содержимого регистра из аккумулятора с учетом флага переноса.
DSBCV A,reg SBC A,reg
DAA
28. Вычитание двойного числа из HL с учетом флага переноса .
SBC HL, NN LD rp,NN
SBC HL,rp
2.1.6. Команды увеличения (инкремент) .
29. Выполнить инкремент для содержимого заданного адреса. INC (ADDR) LD HL, ADDR
INC (HL)
30. Инкремент аккумулятора с включением флага С, если в результате получается 0.
ADD A,1
О В отличие от команды INC команда ADD влияет на флаг пере
носа .
31. Десятиричный инкремент аккумулятора.
ADD A,1 DAA
32. Десятиричный инкремент регистра.
LD A,reg ADD A,1 DAA
LD reg,A
Необходимость переброски через аккумулятор вызвана тем, что команда DAA может применяться только к аккумулятору.
33. Инкремент содержимого двух смежных ячеек памяти. LD HL,(ADDR) INC HL
LD (ADDR) , HL
ИЛИ
LD HL,(ADDR) INC (HL) JR NZ,END INC HL INC (HL) DEC HL END: NOP
ПРИМЕЧАНИЕ:
а) В команде JR NZ,S мы вместо числа дали метку END. В реальной программе здесь, конечно же, надо будет подставить число, указывающее на сколько байтов вперед или назад надо перейти. Отметим, что применение метки позволяет не утруждать себя вычислением величины этого перехода. Все АССЕМБЛЕРы понимают назначение меток и, если Вы пишете свою программу в АССЕМБЛЕРе, то можете сильно упростить себе жизнь. Если же Вы программируете в маш. кодах вручную, то придется выполнить подсчет.
б) Мы привели два варианта выполнения требуемой команды. На глаз видно, что второй вариант значительно длиннее, т. е. занимает больше места в памяти. Интересно оценить быстродействие первого и второго вариантов. Для этого Вам может помочь наш может длиться 33 цикла или 51 цикл, в зависимости от того, произошло ли переполнение младшего байта после его приращения. Поскольку переполнение может произойти только в одном случае из 256, то наиболее вероятна ветвь, которая длится 33 цикла. Таким образом, мы имеем наглядный пример того, как программист может выбирать разные решения в зависимости от того, что ему важнее -экономия памяти или скорость работы.
котором приведено время выполнения каждой измеренное в тактовых циклах
"Справочник... " в команды процессора
LD HL, (ADDR) |
(16) |
LD |
HL, ADDR |
(10) |
(10) |
INC HL |
( 6) |
INC |
(HL) |
(11) |
(11) |
LD (ADDR) , HL |
(16) |
JR |
NZ, END |
(12) |
( 7) |
|
|
INC |
HL |
- |
( 6) |
|
38 |
INC |
(HL) |
- |
(11) |
|
|
DEC |
HL |
- |
( 6) |
33 51
Итак, первый вариант длится 38 тактовых циклов, а второй
2.1.7. Команды уменьшения (декремент) .
34. Уменьшить содержимое заданного адреса. DEC (ADDR) LD HL, ADDR
DEC (HL)
35. Декремент аккумулятора с включением флага С, если происходит двоичный заем.
SUB 1
36. Декремент аккумулятора с включением флага С, если двоичный заем не происходит.
ADD A, FF
37. Десятиричный декремент аккумулятора.
SUB 1
DAA
38. Десятиричный декремент регистра.
LD A,reg
SUB 1
DAA
LD reg,A
39. Декремент 16-битного числа, расположенного по адресу ADDR и ADDR+1.
LD HL,(ADDR)
DEC HL
LD (ADDR) , HL
40. Декремент 16-битного регистра с включением флага Z (флага нуля) , если в результате получается 0.
DEC rp
LD A,rpl - проверка на 0 с
OR rph выставлением флагов
41. Умножение аккумулятора на 2.
ADD A,A
42. Умножение аккумулятора на 3.
LD reg,A - запомнили аккумулятор
ADD A, A - умножили аккумулятор на 2
ADD A,reg - прибавили к результату содержимое аккумулятора еще раз.
43. Умножение аккумулятора на 4.
ADD A,A ADD A,A
Те же приемы могут быть применены и для умножения на другие малые целые числа.
44. Умножение содержимого регистра на 2.
SLA reg
45. Умножение содержимого регистра на 4.
SLA reg SLA reg
Примечание: поскольку инструкция SLA - двухбайтная, все же быстрее перемещать содержимое регистра в аккумулятор и выполнять умножение через однобайтную команду ADD A, A. Вычисления выполняются почти в три раза быстрее.
46. |
Умножить |
на 2 |
содержимое |
регистра HL. |
|
|
ADD |
HL, HL |
|
47 . |
Умножить |
на 3 |
содержимое |
регистра HL. |
|
|
LD |
rph, H |
- запомнили старший |
|
|
LD |
rpl, L |
- запомнили младший |
|
|
ADD |
HL, HL |
- умножили на 2 |
|
|
ADD |
HL, rp |
- умножили на 3 |
48. |
Умножить |
на 2 |
содержимое |
индексного регистра |
|
|
ADD |
xy, xy |
|
49. |
Умножить |
на 2 |
16-битное |
число, находящееся в |
адресе. |
|
|
|
|
|
|
LD |
HL,ADDR |
- указание на адрес |
|
|
SLA |
(HL) |
- умножили на 2 младший байт |
|
|
INC |
HL |
- перешли к старшему байту |
|
|
RL |
(HL) |
- умножили на 2 старший байт |
Обратите внимание на то, что при умножении старшего байта мы использовали команду RL, а не SLA. Это необходимо, чтобы "прихватить" и содержимое флага переноса, т. к. при умножении на 2 младшего байта мог ведь возникнуть и перенос единицы, которую надо учесть в старшем байте.
Второй вариант этой конструкции: LD xy,ADDR SLA (XY+0) RL (XY+1)
2.1.9. Команды деления.
50. Деление аккумулятора пополам (без знака).
SRL A
51. То же, но со знаком.
SRA A
52. Деление аккумулятора на 4 (без знака) .
SRL A SRL A
ИЛИ ТО ЖЕ САМОЕ, НО БЫСТРЕЕ RRA RRA
AND 3F
В результате ротации два младших бита перейдут в старшие. Теперь надо их очистить, что и делается маскированием их командой AND 0011 1111. Обратите внимание, что 0011 1111В = 3FH.
53. Деление на 2 16-битного содержимого адреса.
LD xy,ADDR
SRL (xy+1) - деление старшего байта
RR (XY+0) - деление младшего байта с
"прихватыванием" флага С.
54. Деление содержимого регистра на 2 (без знака) .
SRL rph RR rpl
55. То же, но со знаком.
SRA rph RR rpl
56. Сравнить аккумулятор с числом. Включить в результате биты в тех позициях, где они отличаются.
XOR N
57. Сравнить регистровую пару rp с HL. Если rp больше, включить флаг переноса, в противном случае - выключить.
CP rp, HL AND A - сброс флага С
SBC HL, rp
58. Сравнить HL с двухбайтным числом. CP HL, NN AND A
LD rp,NN SBC HL, rp
59. Сравнить содержимое регистровой пары с двухбайтным числом, находящимся по заданному адресу.
CP rp,(ADDR) AND A
LD HL,rp LD rp,(ADDR) SBC HL, rp
60. То же, но для индексного регистра.
CP xy, (ADDR) PUSH xy - переброска содержимого в HL
POP HL при посредстве стека
AND A
LD rp,(ADDR) _ SBC HL, rp
61. Сравнить указатель стека с 16-битным числом. CP SP, NN LD HL, 0 - очистка HL
ADD HL,S P - переброска SP в HL
LD rp,-NN ADD HL, rp
62. Сравнить указатель стека с 16-битным числом, находящимся в указанном адресе.
CP SP,(ADDR) LD HL,0
ADD HL , S P LD rp,(ADDR) AND A SBC HL, rp
2.1.11. Изменение знака (в двоичной дополнительной форме)
63. Изменение знака регистра.
- обнуление аккумулятора
- формирование -reg в аккум-ре
- формирование -reg в регистре
SUB A SUB reg LD reg A
LD A,reg NEG
LD reg,A
64. Изменение знака в заданном адресе.
SUB A
LD HL,ADDR SUB (HL) LD (HL),A
ИЛИ
LD HL,ADDR LD A,(HL) NEG
LD (HL),A
65. Изменение знака регистровой пары.
инвертировали старший байт
- инвертировали младший байт
- прибавили 1 для получения результата.
LD A,rph CPL
LD rph,A LD A,rpl CPL
LD rpl, A INC rp
LD HL, 0 AND A SBC hl, rp
66. Изменение знака 16-битного числа, находящегося в указанном адресе.
NEG (ADDR) LD HL,0
LD rp,(ADDR) AND A SBC HL, rp LD (ADDR) , HL
67. Дополнение до 99. (Т.е. вычисление 99 -"А")
LD reg,A LD A,99 SUB reg
Давать команду DAA здесь не нужно, поскольку если к началу операции в аккумуляторе находилось правильное BCD-число, то и 99 минус аккумулятор тоже будет правильным BCD-числом.
68. Дополнение до 100.
NEG DAA
2.1.12. Команды преобразований.
69. Преобразовать содержимое аккумулятора в 16-битное число без знака и записать его в регистровой паре.
LD rpl,A
LD rph,0
70. То же, но со знаком.
Напомним, что в двоичной дополнительной форме, которая применяется для записи целых чисел со знаком, старший (седьмой, он же левый) бит является знаковым.
LD rpl,A
знаковый бит переносится во флаг переноса С. в аккумуляторе остается ноль минус флаг С.
LD rph,A
71. Преобразование содержимого заданного адреса в 16-битную форму со знаком.
LD HL,ADDR - указание на адрес
LD A, (HL) - взяли число
ADD A,A - перевод знакового бита в С
SBC A,A - формирование знакового байта
INC HL - указание на старший байт
LD (HL) ,A - установка старшего байта
72. Приведение аккумулятора по младшему биту. Если младший бит равен нулю, то в аккумуляторе выставляется 0, а если он равен единице, то FF.
RRA - младший бит переносится в С
SBC A,A - формирование (0 минус флаг С)
73. Приведение аккумулятора по знаку. Если в аккумуляторе положительное число, то в нем выставляется 0, а если отрицательное, то FF.
ADD A,A - знаковый бит переносится в C
SBC A, A