Умения процессоров i8086 и i8088
Процессор Intel 8086 может производить разнообразные операций над
шестнадцатибитными числами в разных представлениях, производить операций над
строками. Здесь представлено как это делать и что умеют эти процессоры.
Содержание:
- Основная информация
- Как вычислять на процессоре
- Регистры общего назначения
- Сегментные регистры
- Регистр состояния
- MOD, REG и R/M ── адресация операндов
- Доступные форматы записи чисел
- Стак
- Прерывания и таблица векторов прерываний
- Вычисляем на процессоре
- Оптимизация
- Окончание
Центральные процессоры из семейства Intel 8086 созданы в общих целях, могут
работать напрямую с памятью до целого мегабайта. Работают с
шестнадцатиразрядными машинными словами. Различие между 8086 и 8088 заключается
лишь в работе шины памяти: 8086 считывает шестнадцатиразрядные данные на чётных
адресах за 1 раз, и поэтому может работать лишь с 16-битными чипами памяти;
8088 всегда считывает данные по одному байту и может работать с
распространёнными 8-битными чипами. Данные в памяти представляются из младшего
байта на базовом адресе и старшего байта на следующем адресе. Такой способ
хранения данных называется little endian.
Оба процессора можно использовать с чипами поддержки предыдущих поколений.
Процессор может брать один операнд из памяти, а другой операнд брать внутри
себя. Внутри процессора операнды хранятся в регистрах. Восемь из них
предназначены для хранения операндов и называются Регистрами общего
назначения, а другие шесть нужны при выполнений программы. Из этих шести
операндов, четыре хранят смещения сегментов и называются Сегментными
регистрами, один держит курс выполнения программы и называется
Указателем инструкций (IP), ещё один запоминает признак результата
команды и по нему делают решения, называется Регистр состояния.
Регистры общего назначения есть следующие:
- A ── Accumulator, Аккумулятор
- D ── Data, данные
- C ── Count, счётчик
- B ── Base, основа
- SP ── Stack Pointer, указатель верхушки стака, операнды надо помещать
в сам стак
- BP ── Base Pointer, указатель основы стака
- SI ── Source Index, указатель места источника
- DI ── Destination Index, указатель места назначения
К первым четырём регистрам можно обращаться тремя способами, которые следует
указывать всегда, как суффикс: X ── ко всему регистру, H ── к его верхней
части, и L ── к его нижней части. Например: AX ── весь регистр A, CL ── нижняя
часть регистра C, наконец DH ── верхняя часть регистра D.
Одним из нововедений процессора 8086 является сегментная модель памяти,
созданная с целью расширить объём адресуемой памяти. Они хранят смещение
соответствующего сегмента, который может быть задан с шагом в 16 байт (1
параграф).
Сегментные регистры есть следующие:
- CS ── Code Segment, хранит место сегмента с программой
- SS ── Stack Segment, хранит место расположения верхушки стака
- DS ── Data Segment, хранит место сегмента данных
- ES ── Extra Segment, хранит место дополнительного сегмента данных
Благодаря сегментной модели памяти программы можно сделать более независимыми
от их расположения в памяти, что может быть использовано при созданий
многозадачных операционных систем.
Сегментные регистры работают следующим образом:
(Пример) Содержимое сегментного регистра вставляется
на четыре бита левее
DS │0111 0100 0000 0000|<─── ── Содержимое сегментного регистра
OFFSET ┼ │0001 1000 0110 0100│ ── Высчитаное смещение операнда
ADDRES ═│0111 0101 1000 0110 0100│ ── Физический адрес, то есть адрес
ячейки памяти, значение которого будет
запрошено
Регистр состояния используется для отражения результата какой-либо операций, а
также определения поведения некоторых команд и процессора. Всего есть девять
признаков.
╔═══╦════════════════╤═══════════════════════════╗
║ИМЯ║ НАЗВАНИЕ │ ЗНАЧЕНИЕ ║
╠═══╩════════════════╧═══════════════════════════╣
║ Результат ║
╟───╥────────────────┬───────────────────────────╢
║CF ║Carry │Перенос ║
║PF ║Parity │Чётность ║
║AF ║Auxiliary carry │Десятичный перенос ║
║ZF ║Zero │Ноль/нуль ║
║SF ║Sign │Знак ║
║OF ║Overflow │Переполнение ║
╟───╨────────────────┴───────────────────────────╢
║ Работа и управление ║
╟───╥────────────────┬───────────────────────────╢
║IF ║Interrupt enable│Обработка прерываний ║
║DF ║Direction │Направление обработки строк║
║TF ║Trap │Пошаговое выполнение ║
╚═══╩════════════════╧═══════════════════════════╝
Эти флаги имеют следующие значения:
- CF
- Флаг переноса хранит значение переноса при сложений или вычитаний
длинных чисел (длинее чем слово). Также он может хранить значение
крайнего бита при смещениях на 1.
- PF
- Флаг чётности установлен, когда количество установленных (не
сброшенных, равных 1) битов в результате чётное. Если их количество не
чётное, то флаг сброшен.
- AF
- Дополнительный флаг переноса хранит значение пятого бита при сложений,
или четввёртого бита при вычитаний. Используется командами
корректировки под двоично кодированный десятичный формат.
- ZF
- Этот флаг устанавливается когда результат равен нулю.
- SF
- Этот флаг устанавливается в соответствие со старшим битом результата.
- OF
- Если он будет установлен, то произошло арифметическое переполнение:
результат оказался слишком большим чтобы записать его на место.
На основе их состояний можно выполнять условные переходы. Последние три
определяют работу процессора и режим работы со строками.
- IF
- Установка этого флага сообщает процессору обрабатывать внешние
блокируемые прерывания.
- DF
- Этот флаг определяет направление обработки строк. Когда он сброшен,
строки обрабатываются с нижних адресов до верхних; а когда он
установлен ── с верхних до нижних.
- TF
- Этот флаг заставляет процессор генерировать прерывание №1 после
выполнения каждой операций. Этот флаг предназначен для отладок.
Часто в командах операнды указываются в этой структуре:
│ Байт 1 │ Байт 2 │ Байт 3 │
│0│1│2│3│4│5│6│7│0│1│2│3│4│5│6│7│0│1│2│3│4│5│6│7│
│MOD│ REG │ R/M │ DISP-LOW │ DISP-HIGH │
Поле MOD определяет режим поля R/M как содержащий адрес к регистру или к
памяти, и в последнем случае также определяет размер поля постоянного смещения
(DISP).
╔═══╦══════════════════════════════╗
║MOD║ R/M и DISP ║
╠═══╬══════════════════════════════╣
║00 ║DISP ═ 0 ║
║01 ║DISP размером в 8 бит ║
║10 ║DISP размером в 16 бит ║
║11 ║R/M адресует регистр (см. REG)║
╚═══╩══════════════════════════════╝
В этом поле записывается номер регистра, с содержимым которого надо
будет работать. Так как не во всех операциях нужны два операнда, он может
содержать продолжение кода операций.
╔═══╦═════╤═════╗
║REG║W ═ 0│W ═ 1║
╠═══╬═════╪═════╣
║000║ AL │ AX ║
║001║ CL │ CX ║
║010║ DL │ DX ║
║011║ BL │ BX ║
║100║ AH │ SP ║
║101║ CH │ BP ║
║110║ DH │ SI ║
║111║ BH │ DI ║
╚═══╩═════╧═════╝
Бит W определяет разрядность операндов, поэтому влияет на адресацию регистров.
В этом поле задают метод, по которому должно быть высчитано смещение в памяти
для одного из операндов.
Формула адреса операнда в поле R/M
╔═══╦═══════╤══════════════╤═══════════════╤═══════════╗
║R/M║ MOD═00│ MOD═01 │ MOD═10 │ MOD═11 ║
╠═══╬═══════╪══════════════╪═══════════════╪═══════════╣
║ ║ │ │ │W ═ 0│W ═ 1║
║000║[BX+SI]│[BX+SI]+DISP 8│[BX+SI]+DISP 16│ AL │ AX ║
║001║[BX+DI]│[BX+DI]+DISP 8│[BX+DI]+DISP 16│ CL │ CX ║
║010║[BP+SI]│[BP+SI]+DISP 8│[BP+SI]+DISP 16│ DL │ DX ║
║011║[BP+DI]│[BP+DI]+DISP 8│[BP+DI]+DISP 16│ BL │ BX ║
║100║[SI] │[SI] +DISP 8│[SI] +DISP 16│ AH │ SP ║
║101║[DI] │[DI] +DISP 8│[DI] +DISP 16│ CH │ BP ║
║110║DISP 16│[BP] +DISP 8│[BP] +DISP 16│ DH │ SI ║
║111║[BX] │[BX] +DISP 8│[BX] +DISP 16│ BH │ DI ║
╚═══╩═══════╧══════════════╧═══════════════╧═══════════╝
Регистр BP можно использовать для работы с данными в сегменте стака.
Вычисление адреса будет стоить некоторое количество тактов, что будет упомянуто
как EA. Эти счёты будут стоить столько:
╔═══════════════════════╤═════════╗
║ ФОРМУЛА │СТОИМОСТЬ║
╠═══════════════════════╪═════════╣
║DISP │ 6 ║
╟───────────────────────┼─────────╢
║BX, BP, SI, DI │ 5 ║
╟───────────────────────┼─────────╢
║BX+, BP+, SI+, DI+DISP │ 9 ║
╟───────────────────────┼─────────╢
║BP+DI, BX+SI │ 7 ║
║BP+SI, BX+DI │ 8 ║
╟───────────────────────┼─────────╢
║BP+DI+DISP, BX+SI+DISP │ 11 ║
║BP+SI+DISP, BX+DI+DISP │ 12 ║
╚═══════════════════════╧═════════╝
Переопределение используемого сегмента будет также стоить 2 такта.
Операнды для обработки могут быть записаны разными способами: без знака, со
знаком, и двоично кодированые десятичные числа (BCD, ДКД).
Последние разделяют на запакованные, по две цифры на байт, и не запакованые, по
одной цифре за байт (такие числа можно легко перевести в текстовый ASCII
формат).
Интерпретация чисел в разных форматах
╔════════╦═══════════╤════════╤═══════════╤════════╗
║ БАЙТ ║БЕЗЗНАКОВОЕ│ЗНАКОВОЕ│НЕ ЗАП. ДКД│ЗАП. ДКД║
╠════════╬═══════════╪════════╪═══════════╪════════╣
║01101001║ 105│ 105│ Неверно│ Неверно║
║11010101║ 213│ -43│ Неверно│ Неверно║
║00000111║ 7│ 7│ 7│ 07║
║10010110║ 150│ ─106│ Неверно│ 96║
╚════════╩═══════════╧════════╧═══════════╧════════╝
Двоично кодированые десятичные числа записывается в четырёхбитном поле, где
верны значения от 0000B (0) до 1001B (9). Запакованный формат определяет два
таких поля в байте, а не запакованный формат определяет только одно поле,
расположенное к нижнему краю байта.
Стак ── это специальная структура в памяти, куда последовательно записывается
информация и потом берётся в обратном порядке. Стак используется для сохранения
данных для возврата с обработчика прерываний или из подпрограммы, а также её
можно использовать в самой программе. Стак идёт с верхних адресов к нижним и
состоит из шестнадцатибитных данных. Когда данные помещаются в стак, указатель
стака SP уменьшается на два, и по его новому адресу он туда записывается. Когда
данные берутся из стака, оно копируется по адресу в указателе стака на место
назначения и указатель уменьшается на два.
Основа стака всега конец его сегмнента. адрес её верхушки хранится в регистре
SP. Также, вы можете использовать регистр BP для хранения адреса своего рода
основы стака, но на его работу он не влияет.
Когда будете определять размер стака, оставьте лишние несколько байт для
системного прерывания.
РАБОТА СТАКА
адрес № Элемента
FFFEh ║Элемент №+2║
FFFCh ║Элемент №+1║ │ Получение данных из стака
FFFAh ║Элемент № 0║─ SP
FFF8h ║Элемент №─1║ │ Помещение данных в стак
FFF6h ║Элемент №─2║
FFF4h ║Элемент №─3║
Выполнение программы может быть прервано прерыванием. Оно может быть вызвано
извне или изнутри. Внутренние прерывания могут быть вызваны процессором (ошибка
в делений) или сииницированы самой программой. Прерывания
извне могут быть блокируемыми или обязательными. Когда в процессор поступает
запрос на прерывание, сначала проверяется состояние бита IF. Он запрашивает код
прерывания, затем помещает в стак регистр признаков и сбрасываются IF и TF. В
стак помещаются CS и IP, код прерывания умножается на 4 и используется для
загрузки этих двух регистров. Тут ещё раз проверяется канал запроса
обязательного прерывания и может быть выполнено прерывание № 1 (значение
признака заранее сохранено). Теперь выполняется программа обработки этого
события. По завершению его из стака восстанавливаются значения регистров
IP, CS и регистр состояния и прерваная программа продолжает своё выполнение.
Таблица векторов находится в самом начале адресного пространства. Каждый вектор
состоит из 2 слов, где последний хранит адрес сегмента с обработчиком, а первый
хранит адрес обработчика внутри сегмента (точка входа). Так-как номер типа
прерывания имеет размер 1 байт, то таблица может содержать до 256 векторов. Из
них первые 5 строго определены, а следующие 27 зарезервированы для будущего
строгого определения. Определения следующие: 0 ── ошибка деления, 1 ──
отладочное прерывание, 2 ── обязательное прерывание, 3 ── команда прерывания в
один байт (точка останова), 4 ── переполнение.
Некоторые биты в машинных инструкциях могут указывать определённые свойства
операндов, и чтобы не раздуть документ, они будут обозначены знаками:
- W
- 0: Операнды имеют размер 1 байт
- 1: Операнды имеют размер 1 слово
- S
- 0: Не расширять константу по знаку
- 1: Расширить знак константы до размера операнда
- D
- 0: Второй операнд расположен в регистре
- 1: Первый операнд и место назначения расположены в регистре
- Z
- 0: Повторять пока не ноль
- 1: Повторять пока ноль
- V
- 0: Сдвинуть операнд на 1 бит
- 1: Сдвинуть операнд на CL бит
На протяжений всего документа используются обозначения. Этот раздел нужен,
чтобы не оставить их без какого-либо объяснения.
- MOD
- Поле режима R/M
- REG
- Поле регистра
- R/M
- Поле регистра/памяти
- SR
- Поле сегментного регистра, где 00=ES, 01=CS, 10=SS, 11=DS
- W, S, Z, D, V
- Однобитовые поля операндов
- DATA-8
- Однобайтная константа
- DATA-SX
- Константа в 1 байт, автоматически расширяемая до слова
- DATA-LO
- Нижняя часть слова константы
- DATA-HI
- Высшая часть слова константы
- DISP-LO
- Нижняя часть поля смещения
- DISP-HI
- Высшая часть поля смещения
- IP-LO
- Нижняя часть нового значения IP
- IP-HI
- Высшая часть нового значения IP
- CS-LO
- Нижняя часть нового значения CS
- CS-HI
- Высшая часть нового значения CS
- IP-INC8
- Однобайтное знаковое значения, прибавляемое к IP
- IP-INC-LO
- Нижняя часть значения, прибавляемое к IP
- IP-INC-HI
- Высшая часть значения, прибавляемое к IP
- ADDR-LO
- Нижняя часть прямого адреса памяти
- ADDR-HI
- Высшая часть прямого адреса памяти
- -
- Бит может содержать что угодно
- XXX
- Первые 3 бита кода операций в команде ESC
- YYY
- Последние 3 бита кода операций в команде ESC
- REG8
- Восьмиразрядный регистр общего назначения
- REG16
- Шестнадцатиразрядный регистр общего назначения
- MEM8
- Восьмиразрядный операнд в памяти
- MEM16
- Шестнадцатиразрядный операнд в памяти
- IMMED8
- Восьмиразрядная константа
- IMMED16
- Шестнадцатиразрядная константа
- SEGREG
- Сегментный регистр
- DEST-STR8
- Строка места назначения с восьмиразрядными элементами
- SRC-STR8
- Исходная строка в восьмиразрядными элементами
- DEST-STR16
- Строка места назначения с шестнадцатиразрядными элементами
- SRC-STR16
- Исходная строка с шестнадцатиразрядными элементами
- SHORT-LABEL
- Метка в диапазоне ±127 байт
- NEAR-PROC
- Процедура в этом же сегменте
- FAR-PROC
- Процедура в другом сегменте кода
- NEAR-LABEL
- Метка в этом же сегменте
- FAR-LABEL
- Метка в другом сегменте кода
- SOURCE-TABLE
- Таблица для перевода командой XLAT
- OPCODE
- Код операций внутри команды ESC
- SOURCE
- Операнд регистра или памяти у ESC
Процессор может выполнять переходы по одному из многочисленных условий. Обычно,
если условие оказывается ложным, то процессор на команду тратит 4 такта, а если
условие верно ── 16 тактов.
Здесь «больше» или «меньше» относятся ко 2 незнаковым
числам, а «выше» и «ниже» относятся ко 2 знаковым
числам соответственно.
01110100│IP-INC8 JE SHORT-LABEL ;Jump on Equal, переход если
равно
JZ SHORT-LABEL ;Jump on Zero, переход если
ноль
01111100│IP-INC8 JL SHORT-LABEL ;Jump on Less, переход если
меньше
JNGE SHORT-LABEL ;Jump on Not Greater of Equal,
переход если не больше или
равно
01111110│IP-INC8 JLE SHORT-LABEL ;Jump on Less or Equal, переход
если меньше или равно
JNG SHORT-LABEL ;Jump on Not Greater, переход
если не больше
01110010│IP-INC8 JB SHORT-LABEL ;Jump on Borrow, переход если
ниже
JNAE SHORT-LABEL ;Jump on Not Above or Equal,
переход если не выше или равно
JC SHORT-LABEL ;Jump on Carry, переход если
есть перенос
01110110│IP-INC8 JBE SHORT-LABEL ;Jump on Borrow or Equal,
переход если ниже или равно
JNA SHORT-LABEL ;Jump on Not Above, переход
если не выше
01111010│IP-INC8 JP SHORT-LABEL ;Jump on Parity, переход если
чётность
JPE SHORT-LABEL ;Jump on Parity Even, переход
если число чётное
01110000│IP-INC8 JO SHORT-LABEL ;Jump on Overflow, переход если
есть переполнение
01111000│IP-INC8 JS SHORT-LABEL ;Jump on Sign, переход если
число отрицательное
01110101│IP-INC8 JNE SHORT-LABEL ;Jump on Not Equal, переход
если не равно
JNZ SHORT-LABEL ;Jump on Not Zero, переход если
число не нулевое
01111101│IP-INC8 JNL SHORT-LABEL ;Jump on Not Less, переход если
не меньше
JGE SHORT-LABEL ;Jump on Greater or Equal,
переход если больше или равнно
01111111│IP-INC8 JNLE SHORT-LABEL ;Jump on Not Less or Equal,
переход если не меньше или
равно
JG SHORT-LABEL ;Jump on Greater, переход если
больше
01110011│IP-INC8 JNB SHORT-LABEL ;Jump on Not Borrow, переход
если не ниже
JAE SHORT-LABEL ;Jump on Above or Equal,
переход если выше или равно
JNC SHORT-LABEL ;Jump on No Carry, переход если
нет переноса
01110111│IP-INC8 JNBE SHORT-LABEL ;Jump on Borrow or Equal,
переход если не ниже или равно
JA SHORT-LABEL ;Jump on Above, переход если
выше
01111011│IP-INC8 JNP SHORT-LABEL ;Jump on No Parity, переход
если нет чётности
JPO SHORT-LABEL ;Jump on Parity Odd, переход
если число нечётное
01110001│IP-INC8 JNO SHORT-LABEL ;Jump on No Overflow
переход если не было
переполнения
01111001│IP-INC8 JNS SHORT-LABEL ;Jump on No Sign, переход если
число положительное
AAA AAD
AAM AAS
ADC ADD
AND CALL
CBW CLC
CLD CLI
CMC CMP
CMPS CWD
DAA DAS
DEC DIV
ESC HLT
IDIV IMUL
IN INC
INT INTO
IRET JA
JAE JB
JBE JC
JCXZ JE
JG JGE
JL JLE
JMP JNA
JNAE JNB
JNBE JNC
JNE JNG
JNGE JNL
JNLE JNO
JNP JNS
JNZ JO
JP JPE
JPO JS
JZ LAHF
LDS LEA
LES LOCK
LODS LOOP
LOOPE LOOPNE
LOOPNZ LOOPZ
MOV MOVS
MOVSB MOVSW
MUL NEG
NOP NOT
OR OUT
POP POPF
PUSH PUSHF
RCL RCR
REP REPE
REPNE REPNZ
REPZ RET
ROL ROR
SAHF SAL
SAR SBB
SCAS SHL
SHR STC
STD STI
STOS SUB
TEST WAIT
XCHG XLAT
XOR
Вы видели умения процессов 8086/8088, однако семейство не ограничевается этим.
В наличий также математический сопроцессор 8087, процессор ввода-вывода 8089 и
разнообразные чипы поддержки.
Смотреть также:
- The 8086 Family User's Manual
- The 8086 Family User's Manual Numerics Suppplement