Москва 2001 г тайный язык информатики Чарльз Петцольд ббк 32. 973. 26–018



Pdf көрінісі
бет17/26
Дата07.04.2020
өлшемі3,29 Mb.
#61783
1   ...   13   14   15   16   17   18   19   20   ...   26
Байланысты:
Petcold Kod-Taynyy-yazyk-informatiki.535358


Код

Команда

8B

ADC A,E



9B

SBB A,E


8C

ADC A,H


9C

SBB A,H


8D

ADC A,L


9D

SBB A,L


8E

ADC A,[HL]

9E

SBB A,[HL]



8F

ADC A,A


9F

SBB A,A


Допустим, в аккумуляторе записан байт 35h, а в регистре B —

байт 22h. После выполнения команды:

SUB A,B

аккумулятор содержит байт 13h.



Если в регистре А записан байт 35h, в регистре H — 10h, в

регистре L — 7Ch, а в ячейке памяти по адресу 107Ch — байт

4Ah, то выполнение команды:

ADD A,[HL]

приведет к сложению содержимого аккумулятора (35h) и со-

держимого ячейки памяти, адресуемой парой регистров H и L,

т. е. 4Ah. Результат (7Fh) будет помещен в аккумулятор.

С помощью команд ADC и SBB микросхема 8080 способна

складывать и вычитать числа, разрядность которых равна 16,

24, 32 и т. д. Например, если два 16-битовых числа записаны в

пары регистров BC и DE, то для их сложения и помещения

результата в пару регистров ВС вам понадобится такая после-

довательность команд:

MOV A,C


; Младший байт

ADD A,E


MOV C,A

MOV A,B


; Старший байт

ADC A,D


MOV B,A

Для сложения используются две команды: ADD для младшего

байта и ADC для старшего. Бит переноса, который может по-

явиться в результате первого сложения, учитывается при вто-

ром сложении. Одно из слагаемых всегда обязательно распо-

лагается в аккумуляторе, поэтому даже в такой короткой про-

(продолжение)


333

Два классических микропроцессора

грамме команда MOV используется четырежды. Вообще в про-

граммах для 8080 команды MOV всегда представлены в изо-

билии.


Настало время поговорить о флажках процессора 8080. В

главе 17 мы использовали два флажка — переноса и нуля. В

микросхеме 8080 их на 3 больше — добавляются флажки зна-

ка (Sign), четности (Parity) и вспомогательного переноса

(Auxiliary Carry). Для хранения всех флажков предназначен

особый 8-битовый регистр —  слово состояния программы

(Program Status Word, PSW). Команды LDA, STA и MOV на зна-

чения флажков не влияют. Команды ADD, SUB, ADC и SBB

изменяют значения флажков следующим образом.

Флажок знака устанавливается в 1, если старший бит ре-



зультата равен 1 (результат отрицателен).

Флажок нуля устанавливается в 1, если результат равен 0.



Флажок четности устанавливается в 1, если результат че-



тен, т. е. четно число 1 в двоичном представлении резуль-

тата. В 0 флажок четности устанавливается, если результат



нечетен. Проверку четности иногда используют для конт-

роля корректности результата, хотя в программировании

8080 этот флажок практически не применялся.

Флажок переноса устанавливается в 1, если выполнение



команды ADD или ADC привело к переносу, а также если

выполнение команды SUB или SBB не привело к его появ-

лению (в компьютере из главы 17 поведение флажка пере-

носа подчинялось другим правилам).

Флажок дополнительного переноса устанавливается в 1,



если выполнение команды DAA (о ней чуть позже) приве-

ло к переносу из младшей тетрады в старшую.

С помощью двух команд значение флажка переноса можно

изменить непосредственно:



Код

Команда Действие

37

STC



Установить флажок переноса в 1

3F

CMC



Заменить значение флажка его дополнением

В дополнение к арифметическим командам ADD, ADC, SUB

и SBB, которые были доступны и компьютеру из главы 17 (хотя

и не с той степенью гибкости), процессор 8080 способен вы-



334

Глава девятнадцатая

полнять и логические операции И, ИЛИ и «Исключающее

ИЛИ». Как арифметические, так и логические операции вы-

полняются в арифметико-логическом устройстве процессора.



Код

Команда

Код

Команда

A0

AND A,B



B0

OR A,B


A1

AND A,C


B1

OR A,C


A2

AND A,D


B2

OR A,D


A3

AND A,E


B3

OR A,E


A4

AND A,H


B4

OR A,H


A5

AND A,L


B5

OR A,L


A6

AND A,[HL]

B6

OR A,[HL]



A7

AND A,A


B7

OR A,A


A8

XOR A,B


B8

CMP A,B


A9

XOR A,C


B9

CMP A,C


AA

XOR A,D


BA

CMP A,D


AB

XOR A,E


BB

CMP A,E


AC

XOR A,H


BC

CMP A,H


AD

XOR A,L


BD

CMP A,L


AE

XOR A,[HL]

BE

CMP A,[HL]



AF

XOR A,A


BF

CMP A,A


Команды AND, OR и XOR выполняются побитово, т. е. дей-

ствуют независимо на каждую пару битов. Например, после

выполнения команд:

MVI A,0Fh

MVI B,55h

AND A,B


содержимое аккумулятора будет равняться 05h. Если бы пос-

ледняя команда была OR, в аккумулятор было бы записано

число 5Fh. Наконец, результатом команды XOR стало бы чис-

ло 5Ah.


Действие команды CMP (Compare, сравнить) аналогично

действию команды SUB с единственным исключением — ре-

зультат не сохраняется в аккумуляторе. Иначе говоря, коман-

да CMP вычитает одно число из другого и тут же забывает ре-



335

Два классических микропроцессора

зультат. В чем ее смысл? Во флажках! Они расскажут вам об

отношениях между числами, которые вы сравниваете. Рассмот-

рим в качестве примера команды:

MVI B,25h

CMP A,B


После их выполнения содержимое аккумулятора не изменит-

ся. Но если оно равно 25h, будет установлен флажок нуля, а

если оно меньше 25h — флажок переноса.

У восьми арифметических и логических команд имеются

также версии для работы непосредственно с байтами.

Код

Команда

Код

Команда

C6

ADI A,xx



E6

ANI A,xx


CE

ACI A,xx


EE

XRI A,xx


D6

SUI A,xx


F6

ORI A,xx


DE

SBI A,xx


FE

CPI A,xx


Так показанную выше пару команд можно заменить одной:

CPI A,25h

Еще две команды для работы с аккумулятором:

Код

Команда

27

DAA



2F

CMA


Команда CMA (Complement Accumulator, дополнить акку-

мулятор) вычисляет дополнение содержимого аккумулятора

до 1 — все нули превращаются в единицы, а все единицы — в

нули. Если до выполнения команды CMA в аккумуляторе за-

писано число 01100101, то после в нем будет число 10011010.

Дополнение аккумулятора до 1 вычисляет также команда:

XRI A,FFh

Команда DAA (Decimal Adjust Accumulator, десятичная кор-

рекция аккумулятора) — вероятно в наборе команд 8080 са-

мая сложная. Ее выполнением в микропроцессоре занимается

специально предназначенное для этого устройство.


336

Глава девятнадцатая

Команда DAA помогает программисту осуществлять ариф-

метические операции с десятичными числами, представлен-

ными в кодировке BCD (binary-coded decimal, десятичное в

двоичной кодировке). В данных, закодированных с помощью

BCD, каждая тетрада может принимать значения только от 0000

до 1001, символизирующие десятичные цифры от 0 до 9. В

формате BCD 8 битов байта используются для хранения двух

десятичных цифр.

Допустим, в аккумуляторе хранится BCD-значение 27h,

соответствующее десятичному числу 27 (в обычной ситуации

шестнадцатеричное число 27h равно десятичному 39), а в ре-

гистре В — BCD-значение 94h. После выполнения команд:

MVI A,27h

MVI B,94h

ADD A,B


аккумулятор будет содержать число BBh, которое, конечно, не

может быть числом в формате BCD, так как обе его тетрады

превышают 1001. Вот тут-то на помощь и приходит команда

DAA. После ее выполнения в аккумулятор записывается чис-

ло 21h и устанавливается флажок переноса, поскольку в деся-

тичном исчислении 27 + 94 = 121. При работе с BCD-арифме-

тикой команда DAA очень полезна.

При программировании довольно часто возникает необ-

ходимость прибавить к числу 1 или вычесть из него 1. Напри-

мер, в программе умножения из главы 17 нам нужно было

вычитать 1 из числа, для чего мы складывали его с FFh, т. е. с

дополнением до 2 числа –1. В наборе команд 8080 для умень-

шения или увеличения на 1 числа в регистре или ячейке памя-

ти предусмотрены специальные команды.



Код

Команда

Код

Команда

04

INR B



05

DCR B


0C

INR C


0D

DCR C


14

INR D


15

DCR D


1C

INR E


1D

DCR E


24

INR H


25

DCR H


2C

INR L


2D

DCR L


337

Два классических микропроцессора

34

INR [HL]



35

DCR [HL]


3C

INR A


3D

DCR A


Они действуют на все флажки, кроме флажка переноса.

В набор команд 8080 входят четыре команды циклического



сдвига (rotate), сдвигающие содержимое аккумулятора на 1 бит

влево или вправо.



Код

Команда Действие

07

RLC



Сдвинуть аккумулятор влево

0F

RRC



Сдвинуть аккумулятор вправо

17

RAL



Сдвинуть аккумулятор влево через разряд

переноса


1F

RAR


Сдвинуть аккумулятор вправо через разряд

переноса


Из всех флажков они действуют только на флажок переноса.

Допустим, аккумулятор содержит число A7h, или 10100111

в двоичном представлении. RLC сдвигает биты влево. Самый

старший бит («выталкиваемый» из числа «сверху») становит-

ся самым младшим и определяет состояние флажка переноса.

В данном случае в результате сдвига получится число 01001111,

а флажок переноса будет установлен в 1. RRC таким же обра-

зом сдвигает число вправо. Результат ее действия на число

10100111 будет равен 11010011, флажок переноса также будет

установлен в 1.

Команды RAL и RAR действуют немного иначе. RAL сдви-

гает содержимое аккумулятора влево, записывает во флажок

переноса содержимое старшего бита аккумулятора, а преды-

дущее значение флажка переноса записывает в младший бит

аккумулятора. Например, если аккумулятор содержит число

10100111 и флажок переноса равен 0, то после выполнения RAL

в аккумуляторе будет записано число 01001110, а флажок пе-

реноса равен 1. При тех же начальных условиях команда RAR

приведет к установке флажка переноса в 1 и записи в аккуму-

лятор числа 01010011.

Команды сдвига очень удобны при умножении или деле-

нии числа на 2, что соответствует сдвигу влево или вправо.

(продолжение)


338

Глава девятнадцатая

Память, к которой обращается процессор, называется па-

мятью с произвольным доступом не случайно. Для обращения

к любой ячейке памяти процессору достаточно указать ее ад-

рес. Память RAM подобна книге, которую можно открыть на

любой странице, в отличие от недельной подшивки газет на

микропленке. Чтобы добраться до субботнего выпуска, надо

промотать пленку за большую часть недели. Такие устройства

(микропленки, магнитофонные ленты и т. п.) называются ус-

тройствами с последовательным доступом (sequential access).

Однако временами удобнее оказывается запоминающее

устройство, доступ к которому нельзя назвать ни произволь-

ным, ни последовательным. Рассмотрим такую жизненную

ситуацию. Вы — самый младший служащий в фирме, которо-

му все вышестоящие работники дают поручения, складывая

на стол папки с документами, с которыми что-то нужно сде-

лать. Порой вы обнаруживаете, что не можете продолжить

работу с одной папкой, пока не обработаете другую, связан-

ную с ней папку. Вы кладете первую папку на стол, а вторую

раскрываете поверх нее. Но вот к вашему столу приближается

начальник и передает вам третью папку, работу над которой

нужно закончить срочно. Вы, естественно, располагаете ее по-

верх предыдущих двух. Но вот беда — для выполнения зада-

ния вам нужны документы из еще одной папки, и вот стопка

на столе состоит уже из четырех папок…

Если задуматься, то по этой стопке легко можно отследить

все выполняемые вами задания. Сверху лежит самая важная

папка. Закончив работу с ней, вы обращаетесь к следующей

папке и т. д. Покончив с самой нижней папкой (с нее вы нача-

ли рабочий день), вы вправе отправляться домой.

С технической точки зрения такой способ хранения инфор-

мации называется стеком (stack). «Стопка» информации растет

снизу вверх и убывает сверху вниз. Данные в стеке организова-

ны по принципу «последним вошел — первым вышел» (Last In

First Out, LIFO). То, что было помещено в стек в последнюю

очередь, первым извлекается из него. То, что было помещено в

стек в первую очередь, извлекается из него последним.

В компьютерах стек используется, конечно, не для хране-

ния бумаг, а для хранения чисел, что, впрочем, не менее удоб-

но. Помещение информации в стек называется «вталкивани-



ем» (push), а ее извлечение — «выталкиванием» (pop).

339

Два классических микропроцессора

Допустим, вы пишете на языке ассемблера программу, дан-

ные для которой хранятся в регистрах А, В и С. На каком-то

этапе вы замечаете, что для выполнения очередного расчета

вам нужно использовать эти регистры, а затем восстановить в

них исходные значения.

Конечно, ничто не мешает вам сохранить числа из регист-

ров в ячейках памяти, а затем вернуть их из памяти обратно в

регистры. Но при этом придется следить за тем, в каких ячей-

ках оказались эти числа, чтобы случайно не записать поверх

них другую информацию. Гораздо безопаснее на время поме-

стить («втолкнуть») числа в стек:

PUSH A

PUSH B


PUSH C

Суть действия этих команд я объясню чуть позже. Пока нам

достаточно знать, что они каким-то образом сохраняют содер-

жимое регистров в памяти LIFO. После их выполнения вы

вольны использовать регистры А, В и С по своему усмотре-

нию. Когда надобность в них отпадает, вы извлекаете числа из

стека в обратном порядке:

POP C


POP B

POP A


Помните: последним вошел — первым вышел. Изменив по-

рядок команд POP, вы скорее всего получите ошибку.

Стек особенно удобен тем, что его можно использовать в

различных фрагментах программы, не заботясь при этом о

потенциальных проблемах. Если вы, поместив в стек содер-

жимое регистров А, В и С, решили проделать ту же операцию

с регистрами D и E, используйте команды:

PUSH D


PUSH E

Для восстановления содержимого регистров необходимо вве-

сти в программу команды:

POP E


POP D

340

Глава девятнадцатая

до того как предыдущий фрагмент начнет извлекать из стека

содержимое регистров А, В и С.

Как работает стек? Для него выделяется область памяти, не

занятая другими данными. Для адресации этой области памя-

ти в микропроцессор 8080 включен специальный 16-битовый

регистр — указатель стека (Stack Pointer, SP).

Приведенные выше примеры записи и извлечения из сте-

ка содержимого регистров в случае 8080 не совсем корректны.

Команда PUSH в этом процессоре записывает в стек 16-бито-



вое значение, и такое же значение извлекается из стека коман-

дой POP. Поэтому вместо простых команд PUSH C и POP C в

этом процессоре применяются 8 команд:

Код

Команда

Код

Команда

C5

PUSH BC



C1

POP BC


D5

PUSH DE


D1

POP DE


E5

PUSH HL


E1

POP HL


F5

PUSH PSW


F1

POP PSW


Команда PUSH BC записывает в стек регистры B и C, а POP BC

соответственно извлекает их. В 8-битовом регистре PSW, как

вы помните, хранится слово состояния программы, т. е. флаж-

ки. Две команды в последней строке таблицы в действитель-

ности сохраняют в стеке содержимое не только регистра PSW,

но и аккумулятора. Чтобы сохранить в стеке все регистры и

флажки, используйте команды:

PUSH PSW


PUSH BC

PUSH DE


PUSH HL

а для восстановления этой информации:

POP HL

POP DE


POP BC

POP PSW


Чтобы разобраться в работе стека, допустим, что в какой-

то момент времени содержимое указателя стека равно 8000h.



341

Два классических микропроцессора

Выполнение команды PUSH BC в действительности состоит

из четырех шагов.

Указатель стека уменьшается на 1, становясь равным 7FFFh.



Содержимое регистра B сохраняется в ячейку с адресом из

указателя стека, т. е. 7FFFh.

Указатель стека уменьшается еще на 1, становясь равным



7FFEh.

Содержимое регистра C сохраняется в ячейку с адресом из



указателя стека, т. е. 7FFEh.

Команда POP BC прокручивает все эти действия в обрат-

ном порядке (при условии, что в указателе стека все еще запи-

сан адрес 7FFEh).

В регистр C загружается число из ячейки, адрес которой



(7FFEh) записан в указателе стека.

Указатель стека увеличивается на 1, становясь равным



7FFFh.

В регистр B загружается число из ячейки, адрес которой



(7FFFh) записан в указателе стека.

Указатель стека увеличивается на 1, становясь равным



8000h.

Каждая команда PUSH увеличивает размер стека на 2 бай-

та. В принципе не исключена ситуация, при которой стек (ве-

роятно, из-за ошибки в программе) так вырастет, что начнет

записываться поверх кодов команд и данных, нужных для вы-

полнения программы. Это называется  переполнением стека

(stack overflow). Подобным же образом ошибочное использо-

вание лишних команд POP приводит к  исчезновению стека

(stack underflow).

Если вы подключили к процессору 8080 память емкостью

64 кб, начальное значение указателя стека удобно сделать рав-

ным 0000h. Первая команда PUSH приведет к его уменьше-

нию на 1, т. е. запись стека начнется с адреса FFFFh, и он зай-

мет область памяти, максимально далекую от ваших программ,

которые, вероятно, будут располагаться, начиная с адреса

0000h.


Задать значение указателя стека позволяет команда LXI

(Load Extended Immediate, расширенная непосредственная заг-



342

Глава девятнадцатая

рузка), предназначенная для записи в 16-битовую пару регис-

тров двух байтов, следующих за кодом команды.

Код

Команда

01

LXI BC,xxxx



11

LXI DE,xxxx

21

LXI HL,xxxx



31

LXI SP,xxxx

Команда:

LXI BC,527Ah

эквивалентна командам:

MVI B,52h

MVI C,7Ah

но занимает в памяти на целый байт меньше. Последняя

команда в таблице служит для записи определенного числа в

регистр SP, т. е. в указатель стека. Как правило, она оказывает-

ся одной из первых команд, выполняемых процессором после

перезапуска:

0000h: LXI SP,0000h

Для увеличения или уменьшения на 1 содержимого пар

регистров и указателя стека служат специальные команды:

Код

Команда

Код

Команда

03

INX BC



0B

DCX BC


13

INX DE


1B

DCX DE


23

INX HL


2B

DCX HL


33

INX SP


3B

DCX SP


Раз уж я заговорил о 16-битовых командах, упомяну еще

несколько. Следующие команды складывают содержимое 16-

битовой пары регистров с парой HL.

Код

Команда

09

DAD HL,BC



19

DAD HL,DE



343

Два классических микропроцессора

29

DAD HL,HL



39

DAD HL,SP

Их использование также сокращает размер программы. На-

пример, чтобы заменить DAD HL,BC, вам понадобилось бы

шесть обычных команд:

MOV A,L


ADD A,C

MOV L,A


MOV A,H

ADC A,B


MOV H,A

Обычно команду DAD применяют для вычисления адресов в

памяти. Из всех флажков она влияет лишь на флажок переноса.

Нам осталось рассмотреть еще несколько команд. SHLD и

LHLD служат для сохранения в памяти содержимого пары ре-

гистров HL и для записи информации из памяти в эту пару

регистров.

Код

Команда

Действие

22

SHLD [aaaa],HL



Сохранить содержимое HL

2A

LHLD HL,[aaaa]



Загрузить данные в HL

Число из регистра L записывается по адресу [aaaa], а число из

регистра H — по адресу [aaaa + 1].

В программный счетчик (Program Counter, PC) и указатель

стека можно записать число из пары регистров HL:

Код

Команда

Действие

E9

PCHL PC,HL



Записать число из HL в PC

F9

SPHL SP,HL



Записать число из HL в SP

PCHL в действительно является разновидностью команды пере-

хода, так как следом за ней будет выполнена команда, адрес кото-

рой записан в паре регистров HL. Команда SPHL предоставляет

альтернативный способ задать значение указателя стека.

Две следующие команды позволяют поменять местами со-

держимое пары регистров HL либо с «верхним» элементом

стека, либо с парой регистров DE.

(продолжение)


344

Глава девятнадцатая

Код

Команда

Действие

E3

XTHL HL,[SP]



Поменять местами HL и

«верхний» элемент стека

EB

XCNG HL,DE



Поменять местами HL и DE

Теперь о командах ветвления. Как вы помните из главы 17,

в процессоре имеется специальный регистр — программный

счетчик, — куда записан адрес следующей команды, которую

должен выполнить процессор. Обычно команды выполняют-

ся последовательно, согласно их расположению в памяти. Но

некоторые — а именно команды перехода — позволяют про-

цессору отклониться от этого генерального курса. Их выпол-

нение приводит к записи в программный счетчик значения,

выпадающего из общей последовательности.

Хотя отказываться от старого доброго безусловного перехо-

да никто вас не призывает, куда удобнее оказываются команды



условного  перехода, действие которых зависит от состояния

определенных флажков, например, флажка переноса или

флажка нуля. Именно способность осуществлять условный

переход превратила автоматический сумматор из главы 17 в

настоящий многоцелевой компьютер.

У процессора 8080 пять флажков, четыре из которых ис-

пользуются в командах условного перехода. Всего в наборе 8080

предусмотрено 9 команд перехода: одна для безусловного пе-

рехода и еще 8 для перехода в зависимости от равенства 0 или

1 флажков нуля, переноса, четности и знака.

Прежде чем познакомить вас с ними, я хотел бы ввести еще

два типа переходов. Первый из них осуществляет команда

CALL (вызов). Она приводит в общем-то к обычному услов-

ному переходу с одним исключением: прежде чем записать в

программный счетчик новое значение, процессор сохраняет

адрес, который был в нем до этого. Где? Конечно, в стеке!

Это означает, что в процессоре сохраняется информация,

откуда был совершен переход. Сохраненный адрес позволяет

процессору вернуться к выполнению прерванной последова-

тельности команд. Для этого обратного перехода служит ко-

манда RET (Return, вернуться). Она извлекает 2 байта из стека

и помещает их в программный счетчик.

Наличие команд, подобных CALL и RET, в арсенале любо-

го процессора очень важно, так как они позволяют создавать


345

Два классических микропроцессора

подпрограммы, т. е. выделять часто используемые фрагменты

кода («часто» в данном случае означает «больше одного раза»).

Подпрограммы являются главным организующим элементом

программы на языке ассемблера.

Рассмотрим пример. Разрабатывая программу на языке ас-

семблера, вы столкнулись с необходимостью перемножить два

байта. Естественно, вы вставляете в код фрагмент, который

решает эту задачу, и продолжаете работать. Вскоре потребность

в умножении возникает опять. Конечно, можно использовать

те же команды, что и раньше. Но нужно ли второй раз встав-

лять их в программу? Думаю, нет. Это же напрасная трата па-

мяти! Разумно было бы использовать для умножения уже вве-

денные команды, но как к ним перейти? Обычная команда бе-

зусловного перехода здесь не подойдет, так как она не позво-

ляет после умножения вернуться обратно. Вот здесь-то в дей-

ствие и вступают команды CALL и RET.

Набор команд, осуществляющих умножение двух байтов,

— прекрасный пример подпрограммы. Рассмотрим ее подроб-

нее. В главе 17 перемножаемые байты и произведение храни-

лись в ячейках памяти. В подпрограмме для процессора 8080

мы разместим множители в регистрах В и С, а произведение

запишем в пару регистров HL.

Multiply: PUSH PSW

; Сохраняем регистры, которые

PUSH BC

; будут меняться



SUB H,H

; Записываем 0000h в HL (результат)

SUB L,L

MOV A,B


; Записываем множитель в А

CPI A,00h

; Если он 0, завершаем

JZ AllDone

MVI B,00h

; Записываем 0 в старший байт BC

MultLoop: DAD HL,BC

; Складываем HL и BC

DEC A

; Уменьшаем множитель на 1



JNZ MultLoop

; Возврат на начало цикла, если

; не 0


346

Глава девятнадцатая

AllDone: POP BC ; Восстанавливаем регистры

POP PSW

RET


; Возврат

Первая строчка подпрограммы начинается с метки Multiply,

соответствующей адресу в памяти, по которому расположена

подпрограмма. Начинается выполнение подпрограммы с двух

команд PUSH. Обычно регистры, используемые в подпрограм-

ме, желательно сохранять, а после окончания ее работы — вос-

станавливать.

Затем подпрограмма обнуляет содержимое регистров H и L.

То же действие можно выполнить и с помощью команд MVI,

но их понадобилось бы 4, а не 2, как команд SUB. По заверше-

нии работы подпрограммы пара регистров HL будет содержать

искомое произведение.

Следующий шаг: перемещение содержимого регистра В в

аккумулятор и проверка его равенства 0. Если множитель ра-

вен 0, произведение также равно 0, и работу подпрограммы

можно считать законченной. В регистры H и L ноль уже запи-

сан, так что можно с помощью команды JZ (переход, если 0)

переходить прямо к двум завершающим командам POP.

Если множитель 0 не равен, программа обнуляет регистр

В. Теперь один из множителей содержится в аккумуляторе,

второй — в паре регистров ВС. Команда DAD складывает мно-

житель (ВС) с результатом (HL). Значение множителя в акку-

муляторе уменьшается на 1. Если результат не равен 0, коман-

да JNZ (переход, если не 0) приводит к повторному сложению

ВС и HL. Выполнение этого короткого цикла продолжается,

пока содержимое аккумулятора не обратится в 0 (отмечу, что

более эффективную программу умножения для процессора

8080 можно написать с помощью команд сдвига).

Если в основной программе возникла необходимость ум-

ножить 25h на 12h, это делают команды:

MVI B,25h

MVI C,12h

CALL Multiply

Команда CALL записывает в стек содержимое программного

счетчика, т. е. адрес команды, стоящей  следом за командой

CALL. Затем происходит переход к команде, на которую ука-



347

Два классических микропроцессора

зывает метка Multiply, т. е. к началу подпрограммы. Когда про-

изведение в подпрограмме вычислено, выполняется команда

RET, в результате чего в программный счетчик возвращается

значение из стека. Далее выполняется команда, идущая за

CALL.


В набор команд процессора 8080 входят также условные

команды вызова подпрограммы и возвращения из нее, но ис-

пользуются они гораздо реже обычных команд условного пе-

рехода:


Условие

Код Команда Код

Команда

Код

Команда

Нет


C9

RET


C3

JMP aaaa


CD

CALL aaaa

Не ноль

C0

RNZ



C2

JNZ aaaa


C4

CNZ aaaa


Ноль

C8

RZ



CA

JZ aaaa


CC

CZ aaaa


Нет

D0

RNC



D2

JNC aaaa


D4

CNC aaaa


переноса

Есть


D8

RC

DA



JC aaaa

DC

CC aaaa



перенос

Результат

E0

RPO


E2

JPO aaaa


E4

CPO aaaa


нечетный

Результат

E8

RPE


EA

JPE aaaa


EC

CPE aaaa


четный

Результат

F0

RP

F2



JP aaaa

F4

CP aaaa



положителен

Результат

F8

RM

FA



JM aaaa

FC

CM aaaa



отрицателен

Вы, вероятно, и без меня знаете, что к процессору подклю-

чают не только память. Компьютер — ничто без устройств

ввода и вывода, позволяющих ему обмениваться информаци-

ей с окружающим миром. Самые популярные устройства ввода

и вывода — клавиатура и дисплей.

Как процессор обменивается информацией с периферий-

ными (peripheral) устройствами, т. е. со всеми подключенны-

ми к нему устройствами, кроме памяти? Обычно внешние

устройства конструируют так, что с точки зрения подключе-

ния к процессору они ведут себя подобно памяти. Микропро-

цессор считывает информацию из устройства и записывает ее,

задавая адрес, который соответствует этому устройству. В не-



348

Глава девятнадцатая

которых микропроцессорах адреса внешним устройствам вы-

деляются из обычного адресного пространства. Такая органи-

зация называется  вводом-выводом с распределением памяти

(memory-mapped input/output). В процессоре 8080 для уст-

ройств ввода-вывода 256 адресов зарезервированы в дополне-

ние к основной памяти с 65 536 адресами. Эти дополнитель-

ные адреса называются  портами ввода-вывода  (input/output

ports). Адреса портов подаются на адресные линии с A

0

 по A



7

.

От адресов памяти их с помощью системного контроллера 8228



отличают специальные управляющие сигналы.

Запись содержимого аккумулятора в порт осуществляет

команда OUT. Адрес порта указывается вслед за ее кодом. Для

считывания байта в аккумулятор предназначена команда IN.



Код

Команда

D3

OUT pp



DB

IN pp


В некоторых случаях периферийным устройствам надо

«привлечь внимание» процессора. Например, когда вы нажи-

маете клавишу на клавиатуре, процессору, как правило, жела-

тельно знать об этом сразу. Осуществляет это механизм пре-



рываний (interrupts) — сигналов, поступающих в процессор

8080 через вход INT.

После перезапуска процессор 8080 на прерывания не реа-

гирует. Чтобы разрешить прерывания, в программу нужно

вставить команду EI (Enable Interrupts, разрешить прерывания),

а чтобы отказаться от реагирования на них — DI (Disable

Interrupts, запретить прерывания).

Код

Команда

F3

DI



FB

EI

Когда прерывания разрешены, подается сигнал на выход



процессора INTE. Когда устройству нужно прервать работу

процессора, оно подает сигнал на вход INT. Процессор извле-

кает из памяти очередную команду программы, но выполняет

не ее, а одну из следующих:



349

Два классических микропроцессора

Код

Команда

Код

Команда

C7

RST 0



E7

RST 4


CF

RST 1


EF

RST 5


D7

RST 2


F7

RST 6


DF

RST 3


FF

RST 7


Действуют они подобно команде CALL в том смысле, что

при их выполнении в стек записывается содержимое про-

граммного счетчика. Но переход при этом осуществляется по

строго определенным адресам: команда RST 0 передает управ-

ление команде по адресу 0000h, RST 1 — команде по адресу

0008h и т. д. до RST 7, которая передает управление команде по

адресу 0038h. По этим адресам должны располагаться фраг-

менты кода, реагирующие на прерывания. Допустим, что пре-

рывание от клавиатуры привело к срабатыванию RST 4. Зна-

чит, по адресу 0020h должны располагаться команды для счи-

тывания с клавиатуры введенного байта (подробнее об этом в

главе 21).

Я описал 243 команды. Неиспользованными остались

коды 08h, 10h, 18h, 20h, 28h, 30h, 38h, CBh, D9h, DDh, EDh и

FDh. В заключение упомяну еще один код и соответствую-

щую команду.



Код

Команда

00

NOP



NOP (No Operation, нет операции) не выполняет никаких дей-

ствий. Зачем она нужна? Например, для заполнения пустых

ячеек.

Обсуждать с теми же подробностями процессор 6800 фир-



мы Motorola я не собираюсь, поскольку он как по конструк-

ции, так и по действию довольно похож на процессор 8080.

Вот какие у него есть выводы.


350

Глава девятнадцатая

V

SS



1

2

3



4

5

6



7

8

9



10

11

12



13

14

15



16

17

18



19

20

40



39

38

37



36

35

34



33

32

31



30

29

28



27

26

25



24

23

22



21

A

12



A

13

A



14

A

15



D

7

D



6

D

5



D

4

D



3

D

2



D

1

D



0

R/W


DBE

0

2



TSC

RESET


A

11

A



10

A

9



A

8

A



7

A

6



A

5

A



4

A

3



A

2

A



1

A

0



V

CC

BA



NMI

VMA


IRQ

0

1



HALT

V

SS



MC6800

Контакт V

SS

 соединяется с землей, контакт V



CC

 — с питанием

5 В. Подобно микросхеме 8080, у процессора 6800 имеется 16

адресных входов и 8 сигналов для данных, применяемых как

для ввода, так и для вывода информации. На вход IRQ подает-

ся запрос на прерывание (interrupt request). Порты ввода-выво-

да в 6800 не используются. Адреса устройств берутся из обыч-

ного адресного пространства.

Есть в процессоре 6800 16-битовый программный счетчик,

16-битовый указатель стека, 8-битовый регистр состояния (для

флажков) и два 8-битовых аккумулятора А и В. В считается

именно аккумулятором, а не регистром, поскольку с ним мож-

но выполнять все те же операции, что и с А. Других 8-битовых

регистров в процессоре нет.

16-битовые значения в 6800 хранятся в индексном регистре

(index register), подобном паре регистров HL в 8080. Адрес для

многих команд вычисляется суммированием содержимого ин-

дексного регистра и байта, следующего за кодом команды.



351

Два классических микропроцессора

Хотя набор команд процессора 6800 в целом идентичен

набору процессора 8080, очевидно, что численные и мнемо-

нические коды этих команд совершенно различны. Вот, напри-

мер, как выглядят в наборе 6800 команды перехода.

Код

Команда

Действие

20

BRA



Переход

22

BHI



Переход, если больше

23

BLS



Переход, если меньше или равно

24

BCC



Переход, если нет переноса

25

BCS



Переход, если есть перенос

26

BNE



Переход, если не равно

27

BEQ



Переход, если равно

28

BVC



Переход, если нет переполнение

29

BVS



Переход, если есть переполнение

2A

BPL



Переход, если плюс

2B

BMI



Переход, если минус

2C

BGE



Переход, если больше или равно 0

2D

BLT



Переход, если меньше 0

2E

BGT



Переход, если больше 0

2F

BLE



Переход, если меньше или равно 0

Флажка четности в 6800 нет, зато в отличие от 8080 есть фла-

жок переполнения. Действие некоторых команд перехода за-

висит от сочетания флажков.

Различие наборов команд 8080 и 6800 удивления, разуме-

ется, не вызывает. Две этих микросхемы разрабатывались

практически одновременно двумя группами инженеров двух

различных компаний. Поэтому они и несовместимы: машин-

ные коды одного процессора не работают на другом процес-

соре. Даже программу на языке ассемблера, написанную для

одного процессора, нельзя перевести в машинные коды дру-

гого процессора. О программах, которые работают на разных

процессорах, мы поговорим в главе 24.



352

Глава девятнадцатая

Между процессорами 8080 и 6800 есть и другое интересное

отличие. В обоих наборах есть команда LDA, загружающая в

аккумулятор содержимое ячейки памяти. В 8080, например,

следующая последовательность байтов:

3Ah


7Bh

34h


Команда LDA процессора 8080

приведет к записи в аккумулятор байта из ячейки с адресом

347Bh. Теперь сравните это с командой LDA из набора процес-

сора 6800 в так называемом расширенном режиме адресации:

B6h

7Bh


34h

Команда LDA процессора 6800

Эта последовательность байтов приведет к записи в аккуму-

лятор байта из ячейки с адресом 7B34h.

В различии кодов команд (3Ah в 8080 и B6h в 6800) нет, как

мы уже говорили, ничего удивительного. Но процессоры так-

же по-разному обрабатывают байты, которые следуют за ко-

дом команды. В программе для процессора 8080 считается, что

сначала за кодом идет младший байт адреса, а потом — стар-

ший. В программе же для процессора 6800 сначала идет стар-

ший байт!

Это фундаментальное различие в способе хранения мно-

гобайтовых величин между процессорами фирм Intel и

Motorola  так и не устранено. И в наши дни в процессорах

фирмы Intel многобайтовые величины хранятся, начиная с

младшего байта, а в процессорах фирмы Motorola — начиная

со старшего.

Помните из-за чего Лилипутия воевала с государством Бле-

фуску? Из-за разногласий по поводу того, с какого конца над-

лежит разбивать вареные яйца: с острого или тупого. Споры

между сторонниками двух способов записи многобайтовых


353

Два классических микропроцессора

величин сродни спорам между остроконечниками и тупоко-

нечниками (так Джонатан Свифт назвал приверженцев враж-

дующих партий) и настолько же лишены смысла (хотя дол-

жен признаться, что мне самому способ, использованный в

компьютере из главы 17, не очень нравится!). Сами по себе оба

метода «правильны», но различие между ними создает боль-

шие трудности при необходимости переносить информацию

с компьютеров остроконечников (Intel) на компьютеры тупо-

конечников (Motorola).

Какая судьба ожидала процессоры 8080 и 6800? Первый стал

основой устройства, которое иногда называют первым персо-

нальным компьютером, хотя правильнее было бы называть его

первым домашним компьютером. Это устройство — компью-

тер «Альтаир 8800», в январе 1975 г. украсивший обложку жур-

нала «Popular Electronics».

Взгляните на него: лампочки, переключатели — все это нам

знакомо, правда? Именно так выглядел пульт управления па-

мятью, который я описал вам в главе 16.

За процессором 8080 последовали чипы 8085 и Z-80 фир-

мы Zilog — конкурента корпорации Intel, основанного быв-


354

Глава девятнадцатая

шим работником последней Федерико Фаггином (Federico

Faggin), который принимал активное участие в работе над мик-

росхемой 4004. Процессор Z-80 был полностью совместим с

8080, но отличался от него наличием множества очень полез-

ных дополнительных команд.

В 1977 г. появился компьютер «Apple II» компании Apple

Computer, основанной Стивеном Джобсом (Steven Jobs) и Сте-

фаном Возняком (Stephen Wozniak). В нем был применен усо-

вершенствованный вариант 6800 — дешевый микрочип 6502

фирмы MOS Technology.

В июне 1978 г. фирма Intel выпустила 16-битовый процес-

сор 8086 с адресным пространством 1 Мб. Его машинные коды

были несовместимы с кодами 8080, зато включали специаль-

ные команды для умножения и деления. Годом позже появил-

ся процессор 8088, внутренне идентичный 8086, но адресовав-

ший память побайтово. Это позволяло использовать в сочета-

нии с ним широко распространенные вспомогательные мик-

росхемы, разработанные для процессора 8080. На процессоре

8088 работал персональный компьютер 5150 фирмы IBM (бо-

лее известный как IBM PC), появившийся осенью 1981 г.

IBM оказала на рынок персональных компьютеров громад-

ное влияние. Многие компании занялись выпуском компью-

теров, совместимых с IBM PC (смысл понятия «совместимость»

я разъясню в следующих главах). В 1982 г. семейство процес-

соров x86 пополнилось чипами 186 и 286, в 1985 г. появился

32-разрядный процессор 386, в 1986 г. — 486. С 1993 г. в IBM-

совместимых компьютерах используются процессоры Pentium

фирмы Intel. Хотя наборы команд этих процессоров постоян-

но расширяются, в них неизменно поддерживаются и коман-

ды всех предыдущих версий, начиная с 8086.

Прямым наследником процессора 6800 стал 16-разрядный

чип 68000 фирмы Motorola, ставший в 1984 г. основой компь-

ютера «Apple Macintosh». Этот процессор и последовавшие за

ним процессоры той же серии (иногда ее называют 68К) и по

сей день имеют многочисленных поклонников.

С 1996 г. в компьютерах «Macintosh» используется микро-

процессор PowerPC, разработанный совместно компаниями

Motorola, IBM и Apple. Он построен с использованием архи-

тектуры RISC (Reduced Instruction Set Computing, вычисления



355

Два классических микропроцессора

с сокращенным набором команд), в которой предпринята по-

пытка повысить быстродействие процессора за счет его упро-

щения в некоторых отношениях. В RISC-компьютере все ко-

манды, как правило, имеют одну и ту же длину (в PowerPC она

равна 32 битам), доступ к памяти органичен командами заг-

рузки и сохранения, и вообще команды выполняют максималь-

но простые действия. Обычно RISC-компьютеры снабжены

большим числом регистров, чтобы избежать частых обраще-

ний к памяти.

Набор команд PowerPC кардинально отличается от набора

серии 68К, поэтому запустить на PowerPC программу для про-

цессора 68К нельзя. Однако в процессорах PowerPC, устанав-

ливаемых на компьютерах «Apple Macintosh», предусмотрена

возможность эмуляции процессора 68К. Программа-эмулятор

по одному просматривает все машинные коды программы для

68К и выполняет соответствующее действие. Это, конечно, не

так быстро, как программа, изначально написанная для

PowerPC, но работает.

Согласно закону Мура количество транзисторов в микро-

процессорах удваивается каждые полтора года. Для чего ис-

пользуются все эти дополнительные транзисторы?

Некоторые из них позволили повысить разрядность процес-

сора, другие — расширить набор его команд. В большинстве

современных микропроцессоров имеются специальные коман-

ды для арифметических операций с вещественными числами

(подробнее в главе 23). Специальные команды разработаны для

выполнения многократных вычислений, потребность в кото-

рых возникает при отображении на экране компьютера графи-

ческих изображений (в том числе движущихся).

В современных процессорах используется несколько мето-

дов повышения быстродействия, в частности, конвейеризация

(pipelining). Выполняя одну инструкцию, процессор заранее

считывает следующую, пытаясь предсказать возможное ветв-

ление программы. Еще одно нововведение —  кэш  (cache),

сверхбыстрая память внутри процессора, в которой хранятся

недавно выполнявшиеся команды. Когда в программе встре-

чается короткий цикл, кэш позволяет ускорить его выполне-

ние за счет того, что команды не нужно многократно считы-

вать из памяти. Для всех этих усовершенствований необходи-

мы новые логические схемы, а значит, новые транзисторы.


356

Глава девятнадцатая

Я уже говорил, что процессор — лишь часть завершенной

компьютерной системы (хотя и самая важная). Такую систему

мы спроектируем в главе 21, а пока обратимся к тому, как хра-

нить в памяти нечто, отличное от кодов команд и чисел. Итак,

возвращаемся в первый класс и учимся читать и писать.





Достарыңызбен бөлісу:
1   ...   13   14   15   16   17   18   19   20   ...   26




©www.engime.org 2024
әкімшілігінің қараңыз

    Басты бет