Ассемблер Z80
Zilog Z80 — популярный в 80-е годы XX века микропроцессор, на котором строились такие компьютеры, как ZX Spectrum, Amstrad CPC и компьютеры стандарта PCX. После того, как процессор устарел для использования в персональных компьютерах, он ещё продолжал использоваться в малой микропроцессорной технике, такой как автоматические определители номера для проводного телефона (АОНы).
Описание процессора
[править]Z80 — процессор классической фон-неймановской архитектуры с 8-битной шиной данных и 16-битной шиной адреса. Процессор может выполнять команды над 8- и 16-битными числами, адресовать до 65536 байт в памяти и столько же адресов ввода-вывода. Длина команды — переменная, может составлять от 1 до 3-х байт. Процессор поддерживает маскируемые и немаскируемые прерывания, для маскируемого прерывания доступно три режима.
Регистры
[править]Основной набор регистров общего назначения включает 7 8-разрядных регистров: A,B,C,D,E,H и L. Регистры общего назначения объединяются в регистровые пары. Если 8-разрядные регистры, кроме аккумулятора, равнозначны, то каждая из трёх регистровых пар имеет своё назначение. Кроме того, имеются два 16-битных индексных регистра (IX и IY), регистры специального назначения, а также альтернативный набор регистров, полностью равнозначный основному, переключаемый командами EXX и EX AF,AF'.
Аккумулятор
[править]Регистр A является 8-битным аккумулятором — в него помещается результат большинства 8-битных арифметических и логических операций. Объединяется в пару с регистром флагов (F).
Основные регистровые пары
[править]Каждая из регистровых пар, хотя и может использоваться произвольно, имеет свою особую область применения, связанную с типичным для неё набором команд.
- HL
Регистровую пару HL можно рассматривать как 16-битный аккумулятор: результаты 16-битных операций помещаются в неё. Также HL используется для обращения к адресам в памяти (в том числе безусловного перехода по адресу). В блочных операциях HL указывает на источник данных.
- BC
Название регистровой пары BC часто расшифровывают как Backward Counter — обратный счётчик, так как в блочных операциях этот регистр указывает размер блока. Команды DJNZ, INI, INIR, OUTI и OUTIR используют для счёта старший регистр — B. Также регистровая пара BC используется в операциях ввода-вывода для указания 16-битного адреса порта.
- DE
Наименее примечательная из регистровых пар, её название можно расшифровать как DEstination — место назначения, именно так она используется в блочных операциях. Также существует команда для обмена значениями между регистрами HL и DE.
Регистр флагов
[править]Регистр флагов реагирует на результаты арифметических и логических операций, в зависимости от которого меняется значение одного или нескольких бит. Назначение битов (от младшего к старшему):
- C — флаг переноса.
Указывает, привела ли операция к беззнаковому арифметическому переполнению, то есть переходу через 0. Необходим для реализации длинной арифметики. Этот флаг проверяют условные операторы с C (на включенный флаг) и NC (на выключенный).
- N — флаг типа операции.
Определяет, какого типа была предыдущая операция. Влияет только на команду десятичной коррекции.
- P/V — флаг чётности/переполнения.
В арифметических операциях этот флаг реагирует на переполнение знакового целого, то есть на переход от 127 к -128 и обратно. В логических операциях и операциях сдвига этот флаг имеет другое назначение: он показывает, является ли результат операции чётным числом. Также в блочных операциях ставится в 0 при завершении. С этим флагом работают условные операторы с PE и PO
- F3*
Не используется, как правило равен 3-му биту результата.
- H — флаг десятичного переноса.
Означает, что в результате предыдущей операции произошёл перенос между половинами байта. Влияет только на команду десятичной коррекции.
- F5*
Не используется, как правило равен 5-му биту результата.
- Z — флаг нуля.
Означает, что операция завершилась с нулевым результатом. Для операций сравнения этот флаг означает равенство операндов, для блочного поиска — что искомый байт найден. С этим флагом работают операторы с Z и NZ.
- S — флаг знака.
Равен старшему биту последней выполненной операции, что может означать, является ли полученное в результате операции значение положительным или отрицательным. С этим флагом работают операторы с M и P.
Индексные регистры
[править]Встретив в коде префикс DD или FD, процессор в следующей команде будет вместо регистровой пары HL использовать один из индексных регистров: IX или IY соответственно. При этом если происходит обращение к ячейке памяти, процессор ожидает, что следующий байт будет величиной смещения в байтах (со знаком).
Индексные регистры задуманы как чисто 16-битные, однако существуют недокументированные команды взятия одного байта из индексного регистра. При использовании двухбайтного префикса смещение задаётся между префиксом и командой.
Альтернативные (теневые) регистры
[править]С помощью команды EXX можно обменять значения регистров B,C,D,E,H и L с так называемыми альтернативными, или теневыми регистрами, таким образом количество регистров как бы удваивается. Аналогично работает команда EX AF,AF' для аккумулятора и регистра флагов.
Регистры специального назначения
[править]- SP — указатель стека
Указывает на вершину стека. Начало стека никак не отслеживается, как и выход за границы области, предназначенной для стека.
- PC — программный счётчик
Содержит адрес текущей выполняемой команды. Невозможно напрямую получить текущее значение программного счётчика. Команды перехода также можно рассматривать как операции записи в регистр PC
- I — вектор прерывания для режима IM 2.
Содержит старший байт адреса, по которому должен быть осуществлён переход по прерыванию. Младший байт берётся из шины данных в момент прерывания.
- R — регистр регенерации памяти.
Управляет встроенной схемой регенерации динамической памяти. Увеличивается на единицу после каждой выполненной команды. Не следует производить запись в этот регистр во время исполнения обычных программ, однако можно использовать его в утилитах тестирования оперативной памяти.
Основная область команд
[править]Большая часть основной области команд, за исключением команд относительного перехода и переключения набора регистров, унаследованы от процессора intel 8080, таким образом любая программа, написанная для 8080 может выполняться на Z80 без перекомпиляции. Команды основного набора представлены в таблице:
H\L | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | NOP | LD BC, nn | LD (BC),A | INC BC | INC B | DEC B | LD B,n | RLCA | EX AF,AF' | ADD HL,BC | LD A,(BC) | DEC BC | INC C | DEC C | LD C,n | RRCA |
1 | DJNZ d | LD DE, nn | LD (DE), A | INC DE | INC D | DEC D | LD D,n | RLA | JR d | ADD HL,DE | LD A,(DE) | DEC DE | INC E | DEC E | LD E,n | RRA |
2 | JR NZ d | LD HL, nn | LD (nn),HL | INC HL | INC H | DEC H | LD H,n | DAA | JR Z,d | ADD HL,HL | LD HL,(nn) | DEC HL | INC L | DEC L | LD L,n | CPL |
3 | JR NC d | LD SP, nn | LD (nn),A | INC SP | INC (HL) | DEC (HL) | LD (HL),n | SCF | JR C, d | ADD HL,SP | LD A,(nn) | DEC SP | INC A | DEC A | LD A,n | CCF |
4 | LD B,B | LD B,C | LD B,D | LD B,E | LD B,H | LD B,L | LD B,(HL) | LD B,A | LD C,B | LD C,C | LD C,D | LD C,E | LD C,H | LD C,L | LD C,(HL) | LD C,A |
5 | LD D,B | LD D,C | LD D,D | LD D,E | LD D,H | LD D,L | LD D,(HL) | LD D,A | LD E,B | LD E,C | LD E,D | LD E,E | LD E,H | LD E,L | LD E,(HL) | LD E,A |
6 | LD H,B | LD H,C | LD H,D | LD H,E | LD H,H | LD H,L | LD H,(HL) | LD H,A | LD L,B | LD L,C | LD L,D | LD L,E | LD L,H | LD L,L | LD L,(HL) | LD L,A |
7 | LD (HL),B | LD (HL),C | LD (HL),D | LD (HL),E | LD (HL),H | LD (HL),L | HALT | LD (HL),A | LD A,B | LD A,C | LD A,D | LD A,E | LD A,H | LD A,L | LD A,(HL) | LD A,A |
8 | ADD A,B | ADD A,C | ADD A,D | ADD A,E | ADD A,H | ADD A,L | ADD A,(HL) | ADD A,A | ADC A,B | ADC A,C | ADC A,D | ADC A,E | ADC A,H | ADC A,L | ADC A,(HL) | ADC A,A |
9 | SUB A,B | SUB A,C | SUB A,D | SUB A,E | SUB A,H | SUB A,L | SUB A,(HL) | SUB A,A | SBC A,B | SBC A,C | SBC A,D | SBC A,E | SBC A,H | SBC A,L | SBC A,(HL) | SBC A,A |
A | AND A,B | AND A,C | AND A,D | AND A,E | AND A,H | AND A,L | AND A,(HL) | AND A,A | XOR A,B | XOR A,C | XOR A,D | XOR A,E | XOR A,H | XOR A,L | XOR A,(HL) | XOR A,A |
B | OR A,B | OR A,C | OR A,D | OR A,E | OR A,H | OR A,L | OR A,(HL) | OR A,A | CP A,B | CP A,C | CP A,D | CP A,E | CP A,H | CP A,L | CP A,(HL) | CP A,A |
C | RET NZ | POP BC | JP NZ,(nn) | JP (nn) | CALL NZ,(nn) | PUSH BC | ADD A,n | RST 0H | RET Z | RET | JP Z,(nn) | Битовые операции | CALL Z,(nn) | CALL (nn) | ADC A,n | RST 8H |
D | RET NC | POP DE | JP NC,(nn) | OUT (n),A | CALL NC,(nn) | PUSH DE | SUB A,n | RST 10H | RET C | EXX | JP C,(nn) | IN A,(n) | CALL C,(nn) | Операции с IX | SBC A,n | RST 18H |
E | RET PO | POP HL | JP PO,(nn) | EX (SP),HL | CALL PO,(nn) | PUSH HL | AND A,n | RST 20H | RET PE | JP (HL) | JP PE,(nn) | EX DE,HL | CALL PE,(nn) | Расширенные команды | XOR A,n | RST 28H |
F | RET P | POP AF | JP P,(nn) | DI | CALL P,(nn) | PUSH AF | OR A,n | RST 30H | RET M | LD SP,HL | JP M,(nn) | EI | CALL M,(nn) | Операции с IY | CP A,n | RST 38H |
Команда | Флаги[1] SZ5H3P VNC |
Количество тактов | Описание |
---|---|---|---|
Команды пересылки между регистрами | |||
LD R1,n | -------- | 7 | Загружает в регистр R1 следующий за командой байт (n) |
LD (HL),n | -------- | 7 | Загружает в ячейку памяти по адресу, извлечённому из регистровой пары HL следующий за командой байт (n) |
LD R1,R2 | -------- | 4 | Загружает значение из регистра R2 в регистр R1 |
LD (RP),R1 | -------- | 7 | Загружает значение из регистра R1 в ячейку памяти по адресу, извлечённому из регистровой пары RP |
LD R1,(RP) | -------- | 7 | Загружает значение из ячейки памяти по адресу, извлечённому из регистровой пары RP, в регистр R1 |
LD (nn),A | -------- | 13 | Загружает значение из аккумулятора в ячейку памяти по адресу, указанному следующими двумя байтами |
LD A,(nn) | -------- | 13 | Загружает значение из ячейки памяти по адресу, указанному следующими двумя байтами, в аккумулятор |
LD RP,nn | -------- | 10 | Загружает в регистровую пару RP два байта (nn), следующие за командой |
LD SP,HL | -------- | 6 | Загружает адрес указателя стека из регистровой пары HL |
LD (nn),HL | -------- | 16 | Загружает значение из регистровой пары HL по адресу, указанному следующими двумя байтами |
LD HL,(nn) | -------- | 16 | Загружает в регистровую пару HL значение по адресу, указанному следующими двумя байтами |
Арифметические операции | |||
INC R1 | +++++V0- | 4 | Увеличивает значение в регистре R1 на единицу |
INC (HL) | +++++V0- | 11 | Увеличивает значение в ячейке по адресу (HL) на единицу |
INC RP | -------- | 6 | Увеличивает значение в регистровой паре RP на единицу |
DEC R1 | +++++V1- | 4 | Уменьшает значение в регистре R1 на единицу |
DEC (HL) | +++++V1- | 11 | Уменьшает значение в ячейке по адресу (HL) на единицу |
DEC RP | -------- | 6 | Уменьшает значение в регистровой паре RP на единицу |
ADD A,R1 | +++++V0+ | 4 | Прибавляет к значению в аккумуляторе значение из регистра R1 |
ADD A,(HL) | +++++V0+ | 7 | Прибавляет к значению в аккумуляторе значение из ячейки по адресу (HL) |
ADD A,n | +++++V0+ | 7 | Прибавляет к значению в аккумуляторе следующий за командой байт (n) |
ADD HL,RP | --+?+-0+ | 11 | Прибавляет к значению в регистровой паре HL значение из регистровой пары RP |
ADС A,R1 | +++++V0+ | 4 | Прибавляет к значению в аккумуляторе значение из регистра R1 с учётом флага переноса |
ADС A,(HL) | +++++V0+ | 7 | Прибавляет к значению в аккумуляторе значение из ячейки по адресу (HL) с учётом флага переноса |
ADС A,n | +++++V0+ | 7 | Прибавляет к значению в аккумуляторе следующий за командой байт (n) с учётом флага переноса |
SUB A,R1 | +++++V1+ | 4 | Вычитает из значения в аккумуляторе значение из регистра R1 |
SUB A,(HL) | +++++V1+ | 7 | Вычитает из значения в аккумуляторе значение из ячейки по адресу (HL) |
SUB A,n | +++++V1+ | 7 | Вычитает из значения в аккумуляторе следующий за командой байт (n) |
SBC A,R1 | +++++V1+ | 4 | Вычитает из значения в аккумуляторе значение из регистра R1 с учётом флага переноса |
SBC A,(HL) | +++++V1+ | 7 | Вычитает из значения в аккумуляторе значение из ячейки по адресу (HL) с учётом флага переноса |
SBC A,n | +++++V1+ | 7 | Вычитает из значения в аккумуляторе следующий за командой байт (n) с учётом флага переноса |
AND A,R1 | +++1+P00 | 4 | Выполняет конъюнкцию к значению в аккумуляторе значение из регистра R1 |
AND A,(HL) | +++1+P00 | 7 | Выполняет конъюнкцию к значению в аккумуляторе значение из ячейки по адресу (HL) |
AND A,n | +++1+P00 | 7 | Выполняет конъюнкцию к значению в аккумуляторе следующий за командой байт (n) |
XOR A,R1 | +++0+P00 | 4 | Выполняет операцию исключающего «или» к значению в аккумуляторе значение из регистра R1 |
XOR A,(HL) | +++0+P00 | 7 | Выполняет операцию исключающего «или» к значению в аккумуляторе значение из ячейки по адресу (HL) |
XOR A,n | +++0+P00 | 7 | Выполняет операцию исключающего «или» к значению в аккумуляторе следующий за командой байт (n) |
OR A,R1 | +++0+P00 | 4 | Выполняет дизъюнкцию к значению в аккумуляторе значение из регистра R1 |
OR A,(HL) | +++0+P00 | 7 | Выполняет дизъюнкцию к значению в аккумуляторе значение из ячейки по адресу (HL) |
OR A,n | +++0+P00 | 7 | Выполняет дизъюнкцию к значению в аккумуляторе следующий за командой байт (n) |
RLCA | --+0+-0+ | 4 | Вращение аккумулятора влево |
RRCA | --+0+-0+ | 4 | Вращение аккумулятора вправо |
RLA | --+0+-0+ | 4 | Сдвиг аккумулятора влево (умножение на 2) с переносом |
RRA | --+0+-0+ | 4 | Сдвиг аккумулятора вправо (деление на 2) с переносом |
DAA | +++++P-+ | 4 | Десятичная коррекция |
CPL | --+1+-1- | 4 | Инвертирование аккумулятора |
Команды сравнения | |||
CP A,R1 | +++++V1+ | 4 | Сравнивает значение в аккумуляторе и значение из регистра R1. Значения флагов F3 и F5 берутся из второго операнда |
CP A,(HL) | +++++V1+ | 7 | Сравнивает значение в аккумуляторе и значение из ячейки по адресу (HL). Значения флагов F3 и F5 берутся из второго операнда |
CP A,n | +++++V1+ | 7 | Сравнивает значение в аккумуляторе и следующий за командой байт (n). Значения флагов F3 и F5 берутся из второго операнда |
Команды перехода и вызова процедур | |||
JR n | -------- | 12 | Безусловный относительный переход[2] |
JR F,n | -------- | 7+5 | Относительный переход[2] по условию[3] |
DJNZ d | -------- | 8+5 | Команда цикла: уменьшает B на единицу и если он не равен 0 — совершает относительный переход на d[2] |
JP (nn) | -------- | 10 | Безусловный переход к указанному в следующих за командой двух байтах адресу |
JP F,(nn) | -------- | 10 | Переход к указанному в следующих за командой двух байтах адресу по условию[3] |
JP (HL) | -------- | 4 | Безусловный переход к адресу, указанному в регистре HL |
CALL (nn) | -------- | 17 | Переход по указанному адресу, текущий адрес запоминается на стеке |
CALL F,(nn) | -------- | 10+7 | Переход по указанному адресу по условию[3], текущий адрес запоминается на стеке |
RET | -------- | 10 | Возврат к адресу, запомненному на стеке |
RET F | -------- | 5+6 | Возврат к адресу, запомненному на стеке по условию[3] |
RST XXH | -------- | 11 | Переход по предустановленному адресу, текущий адрес запоминается на стеке |
Работа со стеком | |||
PUSH RP | -------- | 11 | Отправка значения регистровой пары RP в стек |
POP RP | -------- | 10 | Получение регистровой пары со стека |
POP AF | ++++++++ | 10 | Получение аккумулятора и регистра флагов со стека |
EX (SP),HL | -------- | 19 | Поменять местами значение регистра HL и значение двух байт на вершине стека |
Ввод-вывод[4] | |||
OUT (n),A | -------- | 11 | Отправить значение аккумулятора в порт. Младший байт адреса передаётся в следующем за командой байте (n), старший — берётся из аккумулятора |
IN A,(n) | -------- | 11 | Получить значение из порта ввода-вывода в аккумулятор. Младший байт адреса передаётся в следующем за командой байте (n), старший — берётся из аккумулятора |
Прочие команды | |||
NOP | -------- | 4 | Ничего не делает |
HALT | -------- | 4 | Останавливает выполнение программы, ожидая прерывания |
DI | -------- | 4 | Запрещает маскируемые прерывания |
EI | -------- | 4 | Разрешает маскируемые прерывания |
SCF | --+0+-01 | 4 | Устанавливает флаг переноса в 1, сбрасывает флаги типа операции и полупереноса. Флаги F3 и F5 берутся из аккумулятора |
CCF | --+?+-0+ | 4 | Флаг переноса копирует во флаг полупереноса и инвертирует. Флаги F3 и F5 берутся из аккумулятора |
EX AF,AF' | ++++++++ | 4 | Меняет аккумулятор и регистр флагов на альтернативные |
EXX | -------- | 4 | Меняет регистры общего назначения на альтернативные |
EX DE,HL | -------- | 4 | Меняет местами регистры DE и HL |
Команды с префиксом ED
[править]H\L | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
4 | IN B,(BC) | OUT (BC),B | SBC HL,BC | LD (nn),BC | NEG | RETN | IM 0 | LD I,A | IN C,(BC) | OUT (BC),C | ADC HL,BC | LD BC,(nn) | NEG* | RETI | IM 0/1* | LD R,A |
5 | IN D,(BC) | OUT (BC),D | SBC HL,DE | LD (nn),DE | NEG* | RETN* | IM 1 | LD A,I | IN E,(BC) | OUT (BC),E | ADC HL,DE | LD DE,(nn) | NEG* | RETN* | IM 2 | LD A,R |
6 | IN H,(BC) | OUT (BC),H | SBC HL,HL | LD (nn),HL | NEG* | RETN* | IM 0* | RRD | IN L,(BC) | OUT (BC),L | ADC HL,HL | LD HL,(nn) | NEG* | RETN* | IM 0/1* | RLD |
7 | IN F,(BC)* | OUT (BC),0* | SBC HL,SP | LD (nn),SP | NEG* | RETN* | IM 1* | IN A,(BC) | OUT (BC),A | ADC HL,SP | LD SP,(nn) | NEG* | RETN* | IM 2* | ||
A | LDI | CPI | INI | OUTI | LDD | CPD | IND | OUTD | ||||||||
B | LDIR | CPIR | INIR | OUTIR | LDDR | CPDR | INDR | OUTDR |
Команда | Флаги[1] SZ5H3P VNC |
Количество тактов | Описание |
---|---|---|---|
Команды пересылки между регистрами | |||
LD (nn),RP | -------- | 20 | Загрузить регистровую пару в память по указанному адресу |
LD RP,(nn) | -------- | 20 | Загрузить в регистровую пару значение из памяти по указанному адресу |
LD I,A | -------- | 9 | Загрузить вектор прерывания из аккумулятора |
LD A,I | +++0+I0- | 9 | Загрузить вектор прерывания в аккумулятор |
LD R,A | -------- | 9 | Загрузить регистр регенерации из аккумулятора |
LD A,R | +++0+I0- | 9 | Загрузить регистр регенерации в аккумулятор |
Арифметические операции | |||
SBC HL,RP | +++?+V1+ | 15 | Вычесть из HL значение RP с учётом переноса |
ADC HL,RP | +++?+V0+ | 15 | Прибавить к HL RP с учётом переноса |
NEG | +++++V1+ | 8 | Поменять знак аккумулятору |
RRD | +++0+P0- | 18 | Обмен полубайтами между аккумулятором и (HL) по принципу Al→(HL)h→(HL)l→Al |
RLD | +++0+P0- | 18 | Обмен полубайтами между аккумулятором и (HL) по принципу Al→(HL)l→(HL)h→Al |
Команды ввода-вывода[4] | |||
IN R1,(BC) | +++0P+0 | 12 | Загрузить в регистр R1 значение из порта ввода по адресу BC |
OUT (BC),R1 | -------- | 12 | Отправить в порт вывода по адресу BC значение из регистра R1 |
Команды работы с прерываниями | |||
RETN | -------- | 14 | Возврат из немаскируемого прерывания. Оповещает контроллер прерываний об окончании процедуры обработки прерываний. |
RETI | -------- | 14 | Возврат из маскируемого прерывания. Оповещает контроллер прерываний об окончании процедуры обработки прерываний. |
IM 0 | -------- | 8 | Режим прерываний «0» — по сигналу INT происходит непосредственное выполнение команды, поступившей на шину данных. |
IM 1 | -------- | 8 | Режим прерываний «1» — по сигналу INT происходит вызов процедуры по фиксированному адресу 38h |
IM 2 | -------- | 8 | Режим прерываний «2» — по сигналу INT происходит вызов процедуры. Старший байт адреса задаётся регистром I, младший читается с шины данных. |
Блочные команды | |||
LDI | --+0+Z0- | 16 | Переместить байт данных из (HL) в (DE), увеличить HL и DE, уменьшить BC |
LDD | --+0+Z0- | 16 | Переместить байт данных из (HL) в (DE), уменьшить HL, DE и BC |
LDIR | --+0+00- | 5+16 | Переместить блок данных из (HL) в (DE) длиной BC, снизу вверх |
LDDR | --+0+00- | 5+16 | Переместить блок данных из (HL) в (DE) длиной BC, сверху вниз |
CPI | +++++Z1- | 16 | Сравнить байт данных из (HL) с A, увеличить HL, уменьшить BC |
CPD | +++++Z1- | 16 | Cравнить байт данных из (HL) с A, уменьшить HL и BC |
CPIR | +++++Z1- | 5+16 | Искать в области памяти от (HL) вверх, длиной BC, значение из аккумулятора |
CPDR | +++++Z1- | 5+16 | Искать в области памяти от (HL) вниз, длиной BC, значение из аккумулятора |
INI[4] | ++++++++ | 16 | Отправить байт данных из порта ввода (BC) в (HL), увеличить HL, уменьшить B |
IND[4] | ++++++++ | 16 | Отправить байт данных из порта ввода (BC) в (HL), уменьшить B и HL |
INIR[4] | ++++++++ | 5+16 | Блочный ввод из портов от (HL) вверх, длиной B. Адрес порта — в BC |
INDR[4] | ++++++++ | 5+16 | Блочный ввод из портов от (HL) вниз, длиной B. Адрес порта — в BC |
OUTI[4] | ++++++++ | 16 | Отправить байт данных из (HL) в порт (BC), увеличить HL, уменьшить B |
OUTD[4] | ++++++++ | 16 | Отправить байт данных из (HL) в порт (BC), уменьшить HL и B |
OUTIR[4] | ++++++++ | 5+16 | Блочный вывод в порты от (HL) вверх, длиной B. Адрес порта — в BC |
OUTDR[4] | ++++++++ | 5+16 | Блочный вывод в порты от (HL) вниз, длиной B. Адрес порта — в BC |
Команды с префиксом CB (сдвиги и битовые операции)
[править]H\L | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | RLC B | RLC C | RLC D | RLC E | RLC H | RLC L | RLC (HL) | RLC A | RRC B | RRC C | RRC D | RRC E | RRC H | RRC L | RRC (HL) | RRC A |
1 | RL B | RL C | RL D | RL E | RL H | RL L | RL (HL) | RL A | RR B | RR C | RR D | RR E | RR H | RR L | RR (HL) | RR A |
2 | SLA B | SLA C | SLA D | SLA E | SLA H | SLA L | SLA (HL) | SLA A | SRA B | SRA C | SRA D | SRA E | SRA H | SRA L | SRA (HL) | SRA A |
3 | SLL B* | SLL C* | SLL D* | SLL E* | SLL H* | SLL L* | SLL (HL)* | SLL A* | SRL B | SRL C | SRL D | SRL E | SRL H | SRL L | SRL (HL) | SRL A |
4 | BIT 0,B | BIT 0,C | BIT 0,D | BIT 0,E | BIT 0,H | BIT 0,L | BIT 0,(HL) | BIT 0,A | BIT 1,B | BIT 1,C | BIT 1,D | BIT 1,E | BIT 1,H | BIT 1,L | BIT 1,(HL) | BIT 1,A |
5 | BIT 2,B | BIT 2,C | BIT 2,D | BIT 2,E | BIT 2,H | BIT 2,L | BIT 2,(HL) | BIT 2,A | BIT 3,B | BIT 3,C | BIT 3,D | BIT 3,E | BIT 3,H | BIT 3,L | BIT 3,(HL) | BIT 3,A |
6 | BIT 4,B | BIT 4,C | BIT 4,D | BIT 4,E | BIT 4,H | BIT 4,L | BIT 4,(HL) | BIT 4,A | BIT 5,B | BIT 5,C | BIT 5,D | BIT 5,E | BIT 5,H | BIT 5,L | BIT 5,(HL) | BIT 5,A |
7 | BIT 6,B | BIT 6,C | BIT 6,D | BIT 6,E | BIT 6,H | BIT 6,L | BIT 6,(HL) | BIT 6,A | BIT 7,B | BIT 7,C | BIT 7,D | BIT 7,E | BIT 7,H | BIT 7,L | BIT 7,(HL) | BIT 7,A |
8 | RES 0,B | RES 0,C | RES 0,D | RES 0,E | RES 0,H | RES 0,L | RES 0,(HL) | RES 0,A | RES 1,B | RES 1,C | RES 1,D | RES 1,E | RES 1,H | RES 1,L | RES 1,(HL) | RES 1,A |
9 | RES 2,B | RES 2,C | RES 2,D | RES 2,E | RES 2,H | RES 2,L | RES 2,(HL) | RES 2,A | RES 3,B | RES 3,C | RES 3,D | RES 3,E | RES 3,H | RES 3,L | RES 3,(HL) | RES 3,A |
A | RES 4,B | RES 4,C | RES 4,D | RES 4,E | RES 4,H | RES 4,L | RES 4,(HL) | RES 4,A | RES 5,B | RES 5,C | RES 5,D | RES 5,E | RES 5,H | RES 5,L | RES 5,(HL) | RES 5,A |
B | RES 6,B | RES 6,C | RES 6,D | RES 6,E | RES 6,H | RES 6,L | RES 6,(HL) | RES 6,A | RES 7,B | RES 7,C | RES 7,D | RES 7,E | RES 7,H | RES 7,L | RES 7,(HL) | RES 7,A |
C | SET 0,B | SET 0,C | SET 0,D | SET 0,E | SET 0,H | SET 0,L | SET 0,(HL) | SET 0,A | SET 1,B | SET 1,C | SET 1,D | SET 1,E | SET 1,H | SET 1,L | SET 1,(HL) | SET 1,A |
D | SET 2,B | SET 2,C | SET 2,D | SET 2,E | SET 2,H | SET 2,L | SET 2,(HL) | SET 2,A | SET 3,B | SET 3,C | SET 3,D | SET 3,E | SET 3,H | SET 3,L | SET 3,(HL) | SET 3,A |
E | SET 4,B | SET 4,C | SET 4,D | SET 4,E | SET 4,H | SET 4,L | SET 4,(HL) | SET 4,A | SET 5,B | SET 5,C | SET 5,D | SET 5,E | SET 5,H | SET 5,L | SET 5,(HL) | SET 5,A |
F | SET 6,B | SET 6,C | SET 6,D | SET 6,E | SET 6,H | SET 6,L | SET 6,(HL) | SET 6,A | SET 7,B | SET 7,C | SET 7,D | SET 7,E | SET 7,H | SET 7,L | SET 7,(HL) | SET 7,A |
Команда | Флаги[1] SZ5H3P VNC |
Количество тактов | Описание |
---|---|---|---|
Команды сдвига | |||
RLC R1 | +++0+P0+ | 8 | Вращение влево |
RLC (HL) | +++0+P0+ | 15 | Вращение влево |
RRC R1 | +++0+P0+ | 8 | Вращение вправо |
RRC (HL) | +++0+P0+ | 15 | Вращение вправо |
RL R1 | +++0+P0+ | 8 | Сдвиг влево с переносом (умножение на 2) |
RL (HL) | +++0+P0+ | 15 | Сдвиг влево с переносом (умножение на 2) |
RR R1 | +++0+P0+ | 8 | Сдвиг вправо с переносом (деление на 2) |
RR (HL) | +++0+P0+ | 15 | Сдвиг вправо с переносом (деление на 2) |
SLA R1 | +++0+P0+ | 8 | Сдвиг влево без переноса (умножение на 2, бит 0 заполняется нулём) |
SLA (HL) | +++0+P0+ | 15 | Сдвиг влево без переноса (умножение на 2, бит 0 заполняется нулём) |
SRA R1 | +++0+P0+ | 8 | Сдвиг вправо без переноса (бит 7 дублируется) |
SRA (HL) | +++0+P0+ | 15 | Сдвиг вправо без переноса (бит 7 дублируется) |
SRL R1 | +++0+P0+ | 8 | Сдвиг вправо без переноса (деление на 2, бит 7 заполняется нулём) |
SRL (HL) | +++0+P0+ | 15 | Сдвиг вправо без переноса (деление на 2, бит 7 заполняется нулём) |
Побитовые операции | |||
SET x,R1 | -------- | 8 | Установить бит x в 1 |
SET x,(HL) | -------- | 15 | Установить бит x в 1 |
RES x,R1 | -------- | 8 | Установить бит x в 0 |
RES x,(HL) | -------- | 15 | Установить бит x в 0 |
BIT x,R1 | ?++1+?0- | 8 | Получить значение бита X |
BIT x,(HL) | ?++1+?0- | 12 | Получить значение бита X |
Команды работы с индексными регистрами (DD для IX,FD для IY)
[править]Индексные регистры предназначены для получения доступа к ячейке памяти с заданным смещением от значения, записанного в регистре. В остальном работа с индексными регистрами аналогична работе с регистровой парой HL. К примеру, если команда под кодом 9E — SBC A,(HL) прибавляет к значению в аккумуляторе значение, находящееся по адресу (HL), то последовательность DD 9E FF означает SBC A,(IX-1). Исключение — команда JP (HL), которая превращается в JP (IX). Команды обращения к отдельным байтам двухбайтных индексных регистров не задокументированы, но в большинстве процессоров доступны. C индексированным значением можно выполнять операции с префиксом CB, но порядок машинных команд должен быть следующий: [префикс индексного регистра] [CB] [смещение] [команда], например DD CB FF 9E = RES 3,(IX-1).
При работе с индексными регистрами ко времени выполнения прибавляется 4 такта на получение префикса и ещё 4 на получение индекса (если он нужен) и ещё 4 на вычисление нового адреса. Таким образом LD IX,nn прибавляет к LD HL,nn только 4 такта (14 против 10), а LD B,(IX+d) — 12 (19 против 7).
Примечания
[править]- ↑ а б в -: флаг не меняется по результатам выполнения; +: флаг меняется в зависимости от результата выполнения;1,0: флаг устанавливается в соответствующее состояние; Для регистра P/V: P — чётность, V — переполнение, Z — BC≠0, I — флаг разрешения прерывания
- ↑ а б в d понимается как однобайтное знаковое целое, которое прибавляется к адресу следующей команды
- ↑ а б в г NZ,NC,PO и P означают сброшенные флаги соответственно нуля, переноса, чётности и знака. Z,C,PE и M — соответственно установленные
- ↑ а б в г д е ё ж з и При разработке устройств на микропроцессоре Z80 многие источники рекомендуют использовать в адресации устройств ввода-вывода только младший байт адреса, так как некоторые команды не позволяют установить произвольное значение старшего байта адреса порта. Тем не менее, в некоторых компьютерах 80-х линии старшего байта адреса для адресации портов всё же использовались, что ограничивало возможность использования некоторых инструкций ввода-вывода только теми портами, в которых старший байт адреса не декодировался.
* Серым цветом отмечены недокументированные команды
Литература
[править]- Документация к процессору Z80
- Rodnay Zaks How to program the Z80. — 0-89588-094-6. — 1981.
Вы можете помочь проекту, исправив и дополнив его. |