Главная страница
Навигация по странице:

  • Условие Код Команда Код Команда Код Команда

  • кр гаряев. Чарльз Петцольд - Код_ тайный язык информатики-Манн, Иванов и Фе. Книга принадлежит Контакты владельца Культовая книга талантливого преподавателя стала для многих первым уверенным шагом в программировании


    Скачать 6.11 Mb.
    НазваниеКнига принадлежит Контакты владельца Культовая книга талантливого преподавателя стала для многих первым уверенным шагом в программировании
    Анкоркр гаряев
    Дата19.10.2022
    Размер6.11 Mb.
    Формат файлаpdf
    Имя файлаЧарльз Петцольд - Код_ тайный язык информатики-Манн, Иванов и Фе.pdf
    ТипКнига
    #743064
    страница20 из 28
    1   ...   16   17   18   19   20   21   22   23   ...   28
    Код
    Команда
    Код
    Команда
    C5
    PUSH BC
    C1
    POP BC
    D5
    PUSH DE
    D1
    POP DE
    E5
    PUSH HL
    E1
    POP HL
    F5
    PUSH PSW
    F1
    POP PSW

    Глава 19. Два классических микропроцессора
    311
    Команда PUSH BC сохраняет в стеке значения регистров B и C, а команда POP
    BC извлекает их. Аббревиатура PSW в последней строке означает слова состояния
    программы, которые, как вы помните, представляют собой 8-битный регистр, содер- жащий флаги. Две команды в нижней строке фактически помещают и извлекают из стека содержимое как аккумулятора, так и регистра PSW. Если вы хотите сохранить содержимое всех регистров и значения всех флагов, используйте следующие команды.
    PUSH PSW
    PUSH BC
    PUSH DE
    PUSH HL
    Когда вам потребуется восстановить содержимое этих регистров, обра- щайтесь к командам POP в обратном порядке.
    POP HL
    POP DE
    POP BC
    POP PSW
    Как работает стек? Предположим, что указатель стека равен 8000h. При выполнении команды PUSH BC происходит следующее:
    ȣ значение указателя стека уменьшается на 1 и становится равным 7FFFh;
    ȣ содержимое регистра B сохраняется по адресу, соответствующему значе- нию указателя стека, то есть в ячейке 7FFFh;
    ȣ значение указателя стека уменьшается на 1 и становится равным 7FFEh;
    ȣ содержимое регистра C сохраняется по адресу, соответствующему значе- нию указателя стека, то есть в ячейке 7FFEh.
    Команда POP BC, выполняемая при значении указателя стека, все еще равном 7FFEh, производит обратные операции:
    ȣ содержимое регистра C загружается из ячейки, адрес которой соответ- ствует значению указателя стека, то есть из ячейки 7FFEh;
    ȣ значение указателя стека увеличивается на 1 и становится равным 7FFFh;
    ȣ содержимое регистра B загружается из ячейки, адрес которой соответ- ствует значению указателя стека, то есть из ячейки 7FFFh;
    ȣ значение указателя стека увеличивается на 1 и становится равным 8000h.

    312
    Код
    Каждая команда PUSH увеличивает размер стека на два байта. Существу- ет вероятность того, что из-за ошибки в программе размер стека станет на- столько большим, что его содержимое начнет сохраняться в ячейках, занятых необходимым программе кодом или данными. Эта проблема называется пе-
    реполнением стека. Точно так же слишком большое количество команд POP может привести к преждевременному исчерпанию стека.
    Если к процессору 8080 подключена память объемом 64 килобайт, имеет смысл установить начальное значение указателя стека равным 0000h. Первая команда PUSH уменьшает это значение на 1 — до FFFFh. После этого стек зай- мет область памяти с самыми высокими адресами, которая максимально уда- лена от ваших программ, хранящихся, вероятно, начиная с 0000h.
    Установить значение указателя стека можно с помощью команды LXI (Load
    Extended Immediate — расширенная непосредственная загрузка). Перечислен- ные далее команды также загружают в 16-битные пары регистров два байта, которые следуют за кодом команды.
    Код
    Команда
    01
    LXI BC, xxxx
    11
    LXI DE, xxxx
    21
    LXI HL, xxxx
    31
    LXI SP, xxxx
    Команда LXI BC,527Ah эквивалентна следующим командам.
    MVI B,52
    MVI C,7Ah
    Однако команда LXI позволяет сэкономить один байт. Кроме того, по- следняя команда LXI в предыдущей таблице используется для установки кон- кретного значения для указателя стека. Часто эта команда одной из первых выполняется микропроцессором после его перезапуска.
    0000h: LXI SP,0000h
    Увеличить и уменьшить на 1 значение пары регистров и указателя стека можно с помощью следующих команд.

    Глава 19. Два классических микропроцессора
    313
    Код
    Команда
    Код
    Команда
    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
    29
    DAD HL, HL
    39
    DAD HL, SP
    Эти команды позволяют сэкономить несколько байтов. Например, первая из них, как правило, требует шесть байт.
    MOV A, L
    ADD A, C
    MOV L, A
    MOV A, H
    ADC A, B
    MOV H, A
    Команда DAD обычно используется для вычисления адресов ячеек памя- ти и влияет только на флаг переноса.
    Следующие два кода команд сопровождаются 2-байтовым адресом ячей- ки памяти и позволяют сохранить содержимое пары регистров HL в соответ- ствующей ячейке, а также загрузить из нее содержимое в пару регистров HL.
    Код
    Команда
    Значение
    2h
    SHLD [aaaa], HL
    Записать число из HL в PC
    2Ah
    LHLD HL,[aaaa]
    Загрузить данные в HL
    Содержимое регистра L сохраняется по адресу aaaa, а содержимое регист - ра H — по адресу aaaa + 1.

    314
    Код
    Эти две команды загружают в счетчик команд (PC) или в указатель стека
    (SP) значение из пары регистров HL.
    Код
    Команда
    Значение
    E9h
    PCHL PC, HL
    Загрузить значение HL в PC
    F9h
    SPHL SP, HL
    Загрузить значение HL в SP
    Команда PCHL — своеобразная команда перехода. После нее процессор
    8080 выполняет команду, код которой занимает ячейку по адресу, записанно- му в паре регистров HL. Команда SPHL — еще один способ установки значе- ния указателя стека.
    Следующие две команды позволяют поменять местами содержимое реги- стров HL с двумя байтами, являющимися «верхними» элементами стека, или с содержимым пары регистров DE.
    Код
    Команда
    Значение
    E3h
    XTHL HL,[SP]
    Поменять местами «верхний» элемент стека и HL
    EBh
    XCHG HL, DE
    Поменять местами DE и HL
    Из всех команд перехода для процессора 8080 пока я описал только PCHL.
    Как вы помните из главы 17, процессор предусматривает регистр под названи- ем «счетчик команд», содержащий адрес ячейки памяти, из которой процессор извлекает следующую команду, подлежащую выполнению. Как правило, счет- чик команд заставляет процессор выполнять команды, сохраненные в памяти, последовательно. Однако так называемые команды перехода, или ветвления, позволяют процессору отклониться от этого главного курса. Эти команды за- гружают в счетчик команд другое значение, поэтому следующая команда из- влекается процессором из какой-то другой области памяти.
    Несмотря на удобство обычной команды перехода, команды условного пе-
    рехода более удобные, поскольку заставляют процессор переходить к другому адресу, основываясь на значении определенного флага, например флага перено- са или флага нуля. Именно реализация условного перехода превратила автома- тизированный сумматор из главы 17 в универсальный цифровой компьютер.
    В процессоре 8080 имеется пять флагов, четыре из которых используют- ся для реализации условных переходов. Набор команд 8080 содержит девять команд безусловных и условных переходов, зависящих от того, чему равны флаги нуля, переноса, четности и знака: 1 или 0.

    Глава 19. Два классических микропроцессора
    315
    Прежде чем продемонстрировать эти команды, хочу познакомить вас с дву- мя другими типами команд, имеющих отношение к переходу. Первая — CALL
    (вызов), она аналогична команде перехода, за исключением того, что перед загрузкой нового адреса в счетчик команд процессор сохраняет предыдущий адрес. Где он сохраняет этот адрес? Разумеется, в стеке!
    Эта стратегия подразумевает, что команда вызова сохраняет информацию о том месте, откуда был совершен переход. Сохраненный адрес позволяет про- цессору вернуться в исходное местоположение. Команда для совершения об- ратного перехода называется RET (Return — вернуться). Она удаляет из стека
    2-байтное значение и загружает его в счетчик команд.
    Команды CALL и RET — чрезвычайно важные функции любого процес- сора, позволяющие программисту реализовывать подпрограммы, которые яв- ляются часто используемыми фрагментами кода. (Под словом «часто» обычно я имею в виду «более одного раза».) Подпрограммы — основные организую- щие элементы программ на языке ассемблера.
    Обратимся к примеру. В процессе написания программы на языке ассемблера у вас возникает необходимость в перемножении двух байтов. Вы пишете код для выполнения этой операции, а затем продолжаете работу с программой. На каком-то этапе вам снова требуется перемножить два байта. Поскольку вы уже знаете, как это сделать, можно просто использовать те же команды снова и снова. Собирае- тесь ли вы во второй раз ввести эти команды в память? Надеюсь, что нет, посколь- ку это пустая трата времени и памяти. Вместо этого вам следует просто перейти к предыдущему фрагменту кода. Правда, в данном случае обычная команда пере- хода не сработает, поскольку она не позволяет вернуться к тому месту, с которого был совершен переход. Именно в этом случае пригодятся команды CALL и RET.
    Набор команд, позволяющих перемножить два байта, идеально подходит на роль подпрограммы. Давайте рассмотрим одну из них. В главе 17 подлежа- щие перемножению байты и произведение хранились в определенных ячейках памяти. Приведенная далее подпрограмма 8080 умножает байт в регистре B на байт в регистре C и помещает 16-битное произведение в регистр HL.
    Multiply: PUSH PSW
    ; Сохранение изменяемых регистров
    PUSH BC
    SUB H, H
    ; Установить HL (результат)
    SUB L, L ; в 0000h
    MOV A, B
    ; Сохранение множителя в А
    CPI A,00h
    ; Если он равен 0,

    316
    Код
    JZ AllDone
    ; завершить программу
    MVI B,00h ; Сохранение значения 0 в старшем байте BC
    MultLoop: DAD HL, BC
    ; Сложение значений HL и BC
    DEC A ; Уменьшение множителя на 1
    JNZ MultLoop ; Возврат к началу цикла,если не 0
    AllDone: POP BC ; Восстановление значений
    POP PSW ; регистров
    RET
    ; Возврат
    Обратите внимание: первая строка подпрограммы начинается с метки
    Multiply. Эта метка соответствует адресу ячейки памяти, в которой располо- жена подпрограмма. Подпрограмма начинается с двух команд PUSH. Как пра- вило, она пытается сохранить (а в дальнейшем восстановить) значения любых регистров, которые могут ей потребоваться.
    Затем подпрограмма записывает значение 0 в регистры H и L. Для это- го вместо команды SUB можно было бы использовать команду MVI (Move
    Immediate — переместить непосредственно), однако в этом случае потребова- лись бы четыре команды, а не две. После выполнения подпрограммы в паре регистров HL будет содержаться произведение.
    После этого подпрограмма перемещает содержимое регистра B (мно- житель) в A и проверяет, не равно ли оно 0. Если оно равно 0, подпрограм- ма завершается, так как произведение — 0. Поскольку значения в регистрах
    H и L уже равны 0, подпрограмма может просто использовать команду JZ
    (Jump If Zero — перейти, если ноль), чтобы перейти к двум командам POP в конце программы.
    В противном случае подпрограмма записывает в регистр B значение 0.
    Теперь в паре регистров BC содержится 16-битное множимое, а в аккуму- ляторе (А) — множитель. Команда DAD прибавляет значение BC (множи- мое) к значению HL (произведение). Значение множителя в A уменьшается на 1. Пока он не станет равен 0, выполнение команды JNZ (Jump If Not Zero — перейти, если не ноль) будет приводить к повторному сложению значения
    BC со значением HL. Этот небольшой цикл будет выполняться до тех пор, пока количество операций сложения BC и HL не станет равным множителю.
    (Более эффективную подпрограмму для умножения можно написать, исполь- зуя команды сдвига из набора команд процессора 8080.)
    Эту подпрограмму для перемножения чисел, например 25h и 12h, можно использовать в программе, добавив следующий фрагмент кода.

    Глава 19. Два классических микропроцессора
    317
    MVI B,25h
    MVI C,12h
    CALL Multiply
    Команда CALL сохраняет в стеке значение счетчика команд, которое пред- ставляет адрес команды, следующей после CALL. Затем CALL вызывает пере- ход к команде, на которую указывает метка 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

    318
    Код
    Как вы знаете, к микропроцессору подключается не только память. Ком- пьютерная система обычно требует устройства ввода и вывода (I/O), которые облегчают пользователям взаимодействие с машиной. К этим устройствам, как правило, относятся клавиатура и дисплей.
    Как микропроцессор взаимодействует с этими периферийными устрой- ствами? (Все подключенные к микропроцессору компоненты, кроме памяти, называются периферийными.) Конструкция периферийных устройств, подоб- но памяти, предусматривает интерфейс. Микропроцессор может записывать и считывать данные с периферийного устройства, указывая определенные адреса, на которые оно реагирует. В некоторых микропроцессорах перифе- рийные устройства фактически задействуют адреса, обычно используемые для обращения к памяти. Такая конфигурация называется вводом-выводом
    с распределением памяти. Тем не менее в процессоре 8080, кроме обычных
    65 536 адресов для устройств ввода и вывода, специально зарезервированы
    256 дополнительных, которые называются портами ввода/вывода. Адрес- ные сигналы устройств ввода/вывода подаются на входы с A
    0
    по A
    7
    , а от об- ращений к памяти их отличают сигналы, фиксируемые чипом системного контроллера 8228.
    Команда OUT записывает содержимое аккумулятора в порт, адресуемый следующим за командой байтом. Команда IN позволяет считать байт в акку- мулятор.
    Код
    Команда
    D3
    OUT pp
    DB
    IN pp
    Периферийным устройствам иногда требуется привлечь внимание микро- процессора. Например, когда вы нажимаете клавишу на клавиатуре, желатель- но, чтобы микропроцессор узнавал об этом сразу. Это реализуется благодаря механизму прерываний — сигналам, поступающим от периферийного устрой- ства на вход INT процессора 8080.
    Однако после перезапуска микропроцессор 8080 не реагирует на преры- вания. Для разрешения прерываний программа должна выполнить команду EI
    (Enable Interrupts — разрешить прерывания), а для их запрещения — команду
    DI (Disable Interrupts — запретить прерывания).
    Код
    Команда
    F3
    DI
    FB
    EI

    Глава 19. Два классических микропроцессора
    319
    Выходной сигнал процессора 8080 INTE означает, что прерывания были разрешены. Когда у периферийного устройства возникает необходимость пре- рвать работу микропроцессора, оно подает на вход INT сигнал, равный 1. В от- вет на него процессор 8080 извлекает из памяти команду, однако управляющие сигналы сообщают о прерывании. В ответ на это периферийное устройство передает процессору 8080 одну из следующих команд.
    Код
    Команда
    Код
    Команда
    C7
    RST 0
    E7
    RST 4
    CF
    RST 1
    EF
    RST 5
    D7
    RST 2
    F7
    RST 6
    DF
    RST 3
    FF
    RST 7
    Эти команды RST (Restart — перезагрузка) аналогичны командам CALL в пла- не того, что текущее значение счетчика команд сохраняется в стеке. Однако после этого RST осуществляет переход к определенным адресам памяти: RST 0 переходит к ячейке 0000h, RST 1 — к ячейке 0008h и так далее вплоть до RST 7, которая совершает переход к ячейке 0038h. В этих ячейках должны содержать- ся фрагменты кода, предусмотренного для обработки прерывания. Например, прерывание от клавиатуры привело к выполнению команды RST 4. Это значит, что начиная с ячейки 0020h в памяти должен храниться некоторый код для считывания байта, введенного с клавиатуры. (В главе 21 я объясню все это.)
    К настоящему моменту мной описаны 243 кода команд. Существует 12 бай- тов, которые не соответствуют никаким командам: 08h, 10h, 18h, 20h, 28h, 30h,
    38h, CBh, D9h, DDh, EDh и FDh. В сумме это дает 255. Но есть еще один код, о котором я должен упомянуть.
    Код
    Команда
    00
    NOP
    Команда NOP (No Operation — нет операции) заставляет процессор без- действовать. Для чего она нужна? Для заполнения адресного пространства.
    Как правило, процессор 8080 может выполнять множество команд NOP без каких-либо неприятных последствий.
    Не буду подробно описывать устройство микросхемы 6800 компании
    Motorola, поскольку ее конструкция и функционал во многом аналогичны со- ответствующим аспектам процессора 8080. На следующей схеме изображены ее 40 контактов.

    320
    Код
    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
    NM I
    VM A
    IRQ
    0 1
    HALT
    V
    SS
    MC6800
    Контакт V
    SS
    подключается к земле, V
    CC
    — к источнику питания с напря- жением пять вольт. Как и процессор 8080, микросхема 6800 предусматрива- ет 16 выходных адресных сигналов и восемь сигналов для данных, работаю- щих как на ввод, так и на вывод. Есть сигналы RESET и R/W (чтение/запись).
    На вход IRQ подается сигнал запроса на прерывание (interrupt request). Счита- ется, что система синхронизации в микросхеме 6800 устроена гораздо проще, чем в процессоре 8080. Чего в микросхеме 6800 нет, так это понятия портов ввода/вывода. Адреса всех устройств ввода и вывода принадлежат общему ад- ресному пространству 6800.
    Микросхема 6800 предусматривает 16-битный счетчик команд, 16-битный указатель стека, 8-битный регистр состояния (для флагов) и два 8-битных ак- кумулятора, называемых A и B.
    В качестве аккумулятора, а не простого регистра рассматривается В, по- скольку его можно использовать так же, как и A. Однако дополнительных
    8-битных регистров в такой микросхеме нет.
    Вместо этого 6800 предполагает 16-битный индексный регистр, который может использоваться для хранения 16-битного адреса, подобно паре регистров
    HL в 8080. Для многих команд адрес может вычисляться путем суммирования значения их индексного регистра и байта, который следует за кодом команды.
    Несмотря на то что микросхема 6800 выполняет примерно те же опера- ции, что и процессор 8080 (загрузка, сохранение, сложение, вычитание, сдвиг,

    Глава 19. Два классических микропроцессора
    321
    переход, вызов), коды команд и соответствующие им мнемокоды у этих чипов совершенно разные. В следующей таблице, например, перечислены команды
    перехода из набора микросхемы 6800.
    1   ...   16   17   18   19   20   21   22   23   ...   28


    написать администратору сайта