Ассемблер КР580
Ассемблер КР580
Страница: 1
Сообщений 1 страница 3 из 3
Поделиться22024-04-01 14:30:10
Код:
Список сокращений ----------------- ЗП - запись МП - микропроцессор ОЗУ- оперативное запоминающее устройство ПЗУ- постоянное запоминающее устройство ЧТ - чтение ША - нина адреса ШД - шина данных ЯП - ячейка памяти PC - счетчик команд (program counter) PSW- слово состояния процессора (processor station word) RC - регистр команды (register of command) SP - указатель стека (stack pointer) A :DB 1 B :DB 8 C¤ :DB ’СТРОКА СИМВОЛОВ’ D :DB 14H,28H,3CH,50H,64H,78H,8CH DB 0A0H,0B4H,0C8H E :DS 10 ------------------- | | | ----- ----- | ------------- | | A | | F | | /| |\ | | | ----- ----- | / | | \ | | | | / ----------- \ | | | ----- ----- | / \ | | | | B | | C | |< Шина данных (8) >| | | ----- ----- | \ / | О З У | | | \ ----------- / | | | ----- ----- | \ | | / | | | | D | | E | | \| |/ | | | ----- ----- | | | | | | и | | ----- ----- | | | | | H | | L | | |\ | | | ----- ----- | | \ | | | |----------------- \ | | | ------------- | \ | П З У | | | SP | | Шина адреса (16) >| | | ------------- | / | | | |----------------- / | | | ------------- | | / | | | | PC | | |/ | | | ------------- | ------------- | | ------------------- В отличие от MOV существует команда обмена XCHG. Она осуществляет обмен данными между регистровыми парами HL и DE. В принципе это можно осуществить следующим образом: Существуют также команды, которые применяют адресацию к памяти через ре- гистровую пару BC или DE. Это команды LDAX и STAX: EXAM3 :LDAX B ;загрузка A из ЯП по адресу, указанному в BC STAX D ;запись A в ЯП по адресу, указанному в DE Для сохранения промежуточного результата используется регистр L. Команды пересылок LDAX, STAX, MOV D,M и MOV M,S называются командами с косвенной адресацией. МП обращается к ЯП, адрес которой в явном виде в команде не указывается. В команде понятно только в какой из регистровых пар должен быть адрес - BC, DE или HL. Наиболее гибкой является команда MOV, в ней пере- сылки осуществляются из любого регистра, минуя аккумулятор A. Однако, это не всегда удобно, т.к. необходимо задействовать для указания адреса ЯП какую-нибудь регистровую пару. Существуют другие команды пересылок, у которых адрес ЯП указывается непосредственно в атрибуте команды: EXAM5 :LDA 0BE36H ;загрузка A из ячейки 0BE36H STA 0BE38H ;запись A в ячейку 0BE38H Конкретный адрес в команде указывать не обязательно, достаточно указать имя переменной. Пример: EXAM6 :LDA COLOR STA BORD При использовании команд LDA и STA МП осуществляет обмен с внешней па- мятью через аккумулятор 8-разрядными данными. Обмен возможен также и 16-раз- рядными данными, это производится через регистровую пару HL при помощи команд LHLD и SHLD: EXAM10:LHLD COLOR ;загрузка HL из памяти SHLD BORD ;запись HL в память Команды пересылок LDA, STA, LHLD, SHLD называются командами с прямой ад- ресацией, т.к. адрес ЯП обязательно указывается в атрибуте команды. Загрузка регистра - MVI D,D8. Здесь в качестве приемника D может выступать аккумулятор A, любой из регистров B,C,D,E,H,L или ячейка памяти М (ее адрес указывается в HL); D8 - непосредственно числовое значение в десятичной (0...255) или шест- надцатиричной форме (0H...0FFH) - байт данных. Все команды пересылок сведем в единую таблицу. Таблица 1 ------------------------------------------------------------------------------ | | Команда | Алгоритм | Пояснения | | -----------|-------------------------|---------------------------------------- | | MOV D,S | D <-- S | Пересылка данных из источника S в при- | | емник D. D и S: A,B,C,D,E,H,L,M. MVI D,D8 | D <-- D8 | Загрузка байта данных D8 в приемник D. | | LDA ADR | A <-- M(ADR) | Загрузка аккумулятора из ЯП с адресом | | ADR. STA ADR | А --> M(ADR) | Запись байта из аккумулятора в память. | | LDAX R | A <-- M(R) | Загрузка аккумулятора из ЯП, адрес ко- | | торой указан в per. паре BC или DE. STAX R | A --> M(R) | Запись байта из аккумулятора в память. | | R: B, D. XCHG | HL <--> DE | Обмен данными между рег.парами HL и DE. | | LXI P,D16 | P <-- D16 | Загрузка двухбайтного числа D16 в рег. | | пару BC, DE, HL или SP. P: B, D, H, SP. LHLD ADR | L<--M(ADR),H<--M(ADR+1) | Загрузка рег. пары HL из ЯП по адресам | | ADR и ADR+1. SHLD ADR | L-->M(ADR),H-->M(ADR+1) | Запись пары байт из HL в память. | | ------------------------------------------------------------------------------ Арифметические команды ---------------------- Таблица 2 ------------------------------------------------------------------------------ | | Признаки | Команда | Алгоритм |------------| Пояснения | | S Z Ac P C | --------|----------|------------|--------------------------------------------- | | | ADD S | A=A+S | + + + + + | Сложение аккумулятора с источником S. | | | S: A,B,C,D,E,H,L,M. ADC S | A=A+S+c | + + + + + | Сложение с учетом признака переноса "c". | | | SUB S | A=A-S | + + + + + | Вычитание. | | | SBB S | A=A-S-c | + + + + + | Вычитание с учетом заема "c". | | | ADI D8 | A=A+D8 | + + + + + | Сложение аккумулятора с байтом данных D8. | | | ACI D8 | A=A+D8+c | + + + + + | Сложение с учетом переноса. | | | SUI D8 | A=A-D8 | + + + + + | Вычитание. | | | SBI D8 | A=A-D8-c | + + + + + | Вычитание с учетом заема. | | | DAD P | HL=HL+P | - - - - + | Сложение HL с рег. парой BC, DE, HL или SP. | | | P: B, D, H, SP. INR D | D=D+1 | + + + + - | Увеличение приемника D на 1. | | | D:A,B,C,D,E,H,L,M. DCR D | D=D-1 | + + + + - | Уменьшение приемника D на 1. | | | INX P | P=P+1 | - - - - - | Увеличение на 1 содержимого per. пары BC, | | | DE, HL или SP. P: B, D, H, SP. DCX P | P=P-1 | - - - - - | Уменьшение на 1 содержимого рег.пары или SP. | | | DAA |Десятичная| + + + + + | Преобразование содержимого аккумулятора в |коррекция | | двоично-десятичный код. ------------------------------------------------------------------------------ + признак изменяется - не изменяется S - знак результата Z - признак нулевого результата Ac- дополнительный перенос P - признак четности C - признак переноса/заема МП обрабатывает в основном 8-разрядные числа (байты) - команды ADD, SUB, ADI, SUI, INR, DCR. Все действия по сложению и вычитанию производятся в акку- муляторе. Команды INX и DCX аналогичны по действию командам INR и DCR, только в качестве операнда уже выступает регистровая пара, а не отдельный регистр. Это позволяет работать с числами в диапазоне 0 ...65535, а не 0 ...255, как в однобайтной арифметике. Для арифметики с числами большей разрядности (24, 32 и т.д.) применяют команды ADC, SBB, ACI, SBI. Обработка числа производится побайтно, а промежу- точный результат фиксируется в признаке переноса C (не путать с регистром C!). Признак C устанавливается в "1" при сложении, если результат превысил 0FFH (т.е. 255); при вычитании, если результат оказался меньше 0. То есть в любом случае, если при арифметическом действии был переход через границу 0FFH/0. За- тем содержимое признака переноса учитывается при обработке следующего байта числа. Помимо признака переноса C при выполнении арифметических операций уста- навливаются еще четыре признака МП (см. таблицу 2). S - знак результата: 1-результат отрицательный, 0-результат положительный. Фактически это содержимое старшего разряда результата. Z - признак нулевого результата: 1-нулевой результат, 0-ненулевой результат. Ac- дополнительный перенос: 1-произошел перенос между тетрадами байта, 0-нет переноса. P - признак четности: 1-в результате четное количество единиц, 0-нечетное количество единиц. C - признак переноса/заема: 1-перенос/заем, 0-нет переноса. Все пять признаков составляют регистр признаков F (см. стр. 8). Содержимое ре- гистра используется в программировании для принятия решений. Об этом речь пой- дет ниже. Логические команды ------------------ В программировании на ассемблере помимо арифметических широко используют- ся логические команды. Таблица 3 ------------------------------------------------------------------------------ | | Признаки | Команда | Алгоритм |------------| Пояснения | | S Z Ac P C | --------|------------|------------|------------------------------------------- | | | ANA S | A = A & S | + + 0 + 0 | Логическое И аккумулятора с источником S. | | | S: A,B,C,D,E,H,L,M. ORA S | A = A ! S | + + 0 + 0 | Логическое ИЛИ. | | | XRA S | A = A ¤ S | + + 0 + 0 | Исключающее ИЛИ. | | | CMP S | A - S | + + + + + | Сравнение аккумулятора с источником S. | | | ANI D8 | A = A & D8 | + + 0 + 0 | Логическое И аккумулятора с байтом | | | данных D8. ORI D8 | A = A ! D8 | + + 0 + 0 | Логическое ИЛИ. | | | XRI D8 ! A = A ¤ D8 | + + 0 + 0 | Исключающее ИЛИ. | | | CPI D8 | A - D8 | + + + + + | Сравнение аккумулятора с байтом данных D8. | | | RLC | C <--A<-- | - - - - + | Циклический сдвиг влево содержимого | | | аккумулятора. RRC | C -->A--> | - - - - + | Циклический сдвиг вправо. | | | RAL | C <--A<-- | - - - - + | Циклический сдвиг влево с использованием | | | признака переноса C. RAR | C -->A--> | - - - - + | Циклический сдвиг вправо с использованием | _ | | признака переноса C. CMA | A = A | - - - - - | Инверсия содержимого аккумулятора. | | | STC | 1 --> c | - - - - 1 | Установка признака C в "1". | _ | | CMC | c = c | - - - - + | Инверсия признака C. | | | ------------------------------------------------------------------------------ "&"-логическое И + признак изменяется "!"-логическое ИЛИ - не изменяется "¤"-исключающее ИЛИ 0 сбрасывается 1 устанавливается Все логические команды выполняются в аккумуляторе, результат также остается в аккумуляторе. При выполнении операций И, ИЛИ, исключающее ИЛИ (ANA, ORA, XRA, ANI, ORI, XRI) признаки S, Z, P изменяются в зависимости от результата, а Ac и C сбрасываются в 0, т.к. при этом никаких переносов не производится. Команда RLC (RRC) осуществляет сдвиг байта в акккумуляторе на один би- влево (вправо). При этом "вытесненный" старший (младший) бит записывается в "опустевший" младший (старший) разряд и одновременно в признак переноса C. Та- ким образом, сдвиг производится по кольцу из 8 бит. Команды RAL и RAR выполняются примерно также, но в кольцо сдвига включа- ется признак C, т.е. сдвиг производится как бы в 9-разрядном регистре. Команды сдвига RLC, RRC, RAL, RAR не влияют на признаки S, Z, Ac и P. 17 CMA - инверсия содержимого аккумулятора. С помощью этой команды, напри- мер, можно получить дополнительный код числа: Приведенный фрагмент в Бейсике выглядел бы так: 160 X3=-X3 Дополнительные возможности предоставляют команды STC и CMC, с их помощью можно непосредственно управлять состоянием признака переноса C. Для сравнения чисел используют команды CMP и CPI. Особенность состоит в том, что здесь производится вычитание сравниваемой величины (S - регистра / ЯП или D8 - байта) из аккумулятора, но результат не фиксируется. В результате вы- полнения команды будут установлены признаки МП, по состоянию которых затем можно будет принять определенное решение. Команды перехода ---------------- Как и в Бейсике в ассемблере есть команда безусловного перехода. В Бейси- ке она называется GOTO, в ассемблере - JMP. В качестве параметра у команды GOTO должен быть укзан номер строки, а у JMP - адрес перехода или имя метки. Но ключевой командой в любом языке программирования является команда ус- ловного перехода. Именно с ее помощью программа может принимать решения, а компьютер наделяется определенным интеллектом. В Бейсике это оператор IF-THEN. В ассемблере условный переход осуществляется исходя из состояния признаков. Таблица 4 ------------------------------------------------------------------------------ | | Команда | Условие | Пояснения | | ---------|-------------------|------------------------------------------------ | | JMP ADR |безусловный переход| Переход по адресу (на метку) ADR. | | * JNZ ADR | переход, если Z=0 | Переход, если результат ненулевой. * JZ ADR | " " Z=1 | " " результат нулевой. * JNC ADR | " " C=0 | " " не было переноса/заема. * JC ADR | " " C=1 | " " произошел перенос/заем. * JPO ADR | " " P=0 | " " в результате нечетное кол-во "1". * JPE ADR | " " P=1 | " " в результате четное кол-во "1". * JP ADR | " " S=0 | " " результат положительный. * JM ADR | " " S=1 | " " результат отрицательный. | | PCHL | переход на HL | Переход по адресу, заданному в HL. | | ------------------------------------------------------------------------------ Здесь используется команда условного перехода JNC. Если A+B будет больше или Все достаточно просто, если речь идет об однобайтных величинах. Как быть, если приходится сравнивать числа большей разрядности? В этом случае надо раз- бить процесс сравнения побайтно и реализовать его поэтапно. Сравнение начина- ется со старших байт, если их сравнение дает результат в чью-нибудь пользу, то этого достаточно для принятия решения. Если же старшие байты оказались равны, то производится проверка следующих байт, и так до самых младших байт. Для организации счета задействуется один из регистров МП, причем счет ведется в порядке уменьшения от заданного значения до нуля. Как видите, при сравнении величин используются команды JC, JNC, JZ, JNZ. Команды JP и JM применяются в арифметике со знаком. JPO и JPE используются при В ассемблере существуют аналогичные команды, они называются CALL и RET. Пара- метром для GOSUB является номер строки начала вызываемой подпрограммы. Для CALL параметром служит адрес или имя метки (имя подпрограммы). Чтобы программа В К Л А Д Ы Ш Таблица 7 ------------------------------------------------------------------------------ | | |Признаки|Число|Число| N | Команда | Алгоритм |--------| | так-| Пояснения | | | SZAcPC |байт | тов | ---|----------|------------------|--------|-----|-----|----------------------- Команды пересылок | | | | | | 1 | MOV D,S | D <-- S | --- -- | 1 | 5/7 | Пересылка байта из ис- | | | | | | точникa S в приемник D | | | | | | D и S: A,B,C,D,E,H,L,M | | | | | | При пересылках между | | | | | | регистрами число так- | | | | | | тов 5; при пересылках | | | | | | из / в память (M) - 7. | | | | | | 2 | MVI D,D8 | D <-- D8 | --- -- | 2 | 7/10| Загрузка байта данных ! | | | | | D8 в приемник D.(D см. | | | | | | в 1.) При загрузке в | | | | | | регистр число тактов | | | | | | 7, в ЯП (M) - 10. | | | | | | 3 | LDA ADR | A <-- M(ADR) | --- -- | 3 | 13 | Загрузка (запись) ак- 4 | STA ADR | A --> M(ADR) | --- -- | 3 | 13 | кумулятора из (в) ЯП | | | | | | с адресом ADR. | | | | | | 5 | LDAX R | A <-- M(R) | --- -- | 1 | 7 | Загрузка (запись) ак- 6 | STAX R | A --> M(R) | --- -- | 1 | 7 | кумулятора из (в) ЯП, | | | | | | адрес которой указан в | | | | | | BC или DE. R: B, D. | | | | | | 7 | LXI P,D16| P <-- D16 | --- -- | 3 | 10 | Загрузка двухбайтного | | | | | | числа D16 в рег. пару | | | | | | BC, DE, HL или SP. | | | | | | P: B, D, H, SP. | | | | | | 8 | LHLD ADR | H <-- M(ADR+l) | --- -- | 3 | 16 | Загрузка (запись) рег. | | L <-- M(ADR) | | | | пары HL из(в) ЯП с ад- 9 | SHLD ADR | H --> M <ADR+1) | --- -- | 3 | 16 | ресами ADR и ADR+1. | | L --> M(ADR) | | | | 10 | XCHG | HL <--> DE | --- -- | 1 | 4 | Обмен данными между | | | | | | рег. парами HL и DE. | | | | | | 11 | SPHL | SP <-- HL | --- -- | 1 | 5 | Пересылка HL в SP. | | | | | | 12 | PCHL | PC <-- HL | --- -- | 1 | 5 | Пересылка HL в PC. | | | | | | 13 | PUSH X |X --> M(SP-1,SP-2)| --- -- | 1 | 11 | Сохранить в стеке co- | | SP = SP - 2 | | | | держимое BC, DE, HL | | | | | | или PSW. X: B,D,H,PSW. | | | | | | 14 ! POP X | X <-- M(SP,SP+1) | --- -- | 1 | 10 | Восстановить из стека | | SP = SP + 2 | | | | BC,DE,HL или PSW.(X см | | | | | | в 13.) Внимание! При | | | | | | восстановлении PSW из- | | | | | | меняются все признаки. | | | | | | 15 | XTHL |HL <--> M(SP,SP+1)| --- -- | 1 | 18 | Обмен данными между HL | | | | | | и вершиной стека. ------------------------------------------------------------------------------ В К Л А Д Ы Ш ------------------------------------------------------------------------------ | | |Признаки|Число|Число| N | Команда | Алгоритм |--------| | так-| Пояснения | | | SZAcPC |байт | тов | ---|----------|------------------|--------|-----|-----|----------------------- Арифметические и логические команды 16 | ADD S | A = A + S | +++ ++ | 1 | 4/7 | Сложение аккумулятора | | | | | | с источником S. (S см. | | | | | | в 1.) При сложении с | | | | | | регистром число тактов | | | | | | 4, с ЯП (M) - 7. 17 | ADC S | A = A + S + c | +++ ++ | 1 | 4/7 | Сложение с учетом | | | | | | признака переноса C. 18 | SUB S | A = A - S | +++ ++ | 1 | 4/7 | Вычитание. | | | | | | 19 | SBB S | A = A - S - c | +++ ++ | 1 | 4/7 | Вычитание с учетом | | | | | | заема. 20 | ANA S | A = A & S | ++0 +0 | 1 | 4/7 | Логическое И. | | | | | | 21 | XRA S | A = A ¤ S | ++0 +0 | 1 | 4/7 | Исключающее ИЛИ. | | | | | | 22 | ORA S | A = A ! S | ++0 +0 | 1 | 4/7 | Логическое ИЛИ. | | | | | | 23 | CMP S | A - S | +++ ++ | 1 | 4/7 | Сравнение. | | | | | | 24 | ADI D8 | A = A + D8 | +++ ++ | 2 | 7 | Выполняются операции с 25 | ACI D8 | A = A + D8 + c | +++ ++ | 2 | 7 | байтом данных D8 как в 26 | SUI D8 | A = A - D8 | +++ ++ | 2 | 7 | командах 16 ...23. 27 | SBI D8 | A = A - D8 - c | +++ ++ | 2 | 7 | 28 | ANI D8 | A = A & D8 | ++0 +0 | 2 | 7 | 29 | XRI D8 | A = A ¤ D8 | ++0 +0 | 2 | 7 | 30 | ORI D8 | A = A ! D9 | ++0 +0 | 2 | 7 | 31 | CPI D8 | A - D8 | +++ ++ | 2 | 7 | | | | | | | 32 | DAD P | HL = HL + P | --- -+ | 1 | 10 | Сложение HL с рег. па- | | | | | | рой BC, DE, HL или SP. | | | | | | (P см. в 7.) | | | | | | 33 | INR D | D = D + 1 | +++ +- | 1 | 5/10| Увеличение (уменьше- 34 | DCR D | D = D - 1 | +++ +- | 1 | 5/10| ние) на 1 приемника D. | | | | | | (D см.в 1) При опера- | | | | | | ции с регистром число | | | | | | тактов 5, с ЯП (M)-10. | | | | | | 35 | INX P | P = P + 1 | --- -- | 1 | 5 | Увеличение (уменьше- 36 | DCX P | P = P - 1 | --- -- | 1 | 5 | ние) на 1 рег.пары BC, | | | | | | DE,HL,SP. (P см. в 7.) | | | | | | 37 | DAA | 2-10 коррекция | +++ ++ | 1 | 4 | Десятичная коррекция. | | | | | | 38 | RLC | C <-- A <-- | --- -+ | 1 | 4 | Циклический сдвиг со- | | | | | | держимого аккумулятора 39 | RRC | C --> A --> | --- -+ | 1 | 4 | влево (вправо). | | | | | | 40 | RAL | C <-- A <-- | --- -+ | 1 | 4 | Циклический сдвиг вле- | | | | | | во (вправо) с исполь- 41 | RAR | C --> A --> | --- -+ | 1 | 4 | зованием признака C. | | _ | | | | 42 | CMA | A = A | --- -- | 1 | 4 | Инверсия аккумулятора. ------------------------------------------------------------------------------ В К Л А Д Ы Ш ------------------------------------------------------------------------------ | | |Признаки|Число|Число| N | Команда | Алгоритм |--------| | так-| Пояснения | | | SZAcPC |байт | тов | ---|----------|------------------|--------|-----|-----|----------------------- 43 | STC | 1 --> c | --- -1 | 1 | 4 | Установка признака C. | | _ | | | | 44 | CMC | c = c | --- -+ | 1 | 4 | Инверсия признака C. Команды управления | | | | | | 45 | JMP ADR | ADR --> PC | --- -- | 3 | 10 | Безусловный переход. | | | | | | 46 | JNZ ADR ! Переход при Z=0 | --- -- | 3 | 10 | Условный переход отра- 47 | JZ ADR | " " Z=1 | --- -- | 3 | 10 | батывается, если опре- 48 | JNC ADR | " " C=0 | --- -- | 3 | 10 | деленный признак нахо- 49 | JC ADR | " " C=1 | --- -- | 3 | 10 | дится в требуемом сос- 50 | JPO ADR | " " P=0 | --- -- | 3 | 10 | тоянии, в противном 51 | JPE ADR | " " P=1 | --- -- | 3 | 10 | случае выполняется 52 | JP ADR | " " S=0 | --- -- | 3 | 10 | следующая команда. 53 | JM ADR | " " S=1 | --- -- | 3 | 10 | | | | | | | 54 | CALL ADR |PC-->M(SP-l,SP-2) | --- -- | 3 | 17 | Безусловный вызов под- | |SP=SP-2, ADR-->PC | | | | программы. 55 | CNZ ADR |Вызов п/пр при Z=0| --- -- | 3 |17/11| Условный вызов подпро- 56 | CZ ADR | " " " Z=1| --- -- | 3 |17/11| граммы отрабатывается, 57 | CNC ADR | " " " C=0| --- -- | 3 |17/11| если определенный при- 58 | CC ADR | " " " C=1| --- -- | 3 |17/11| знак находится в тре- 59 | CPO ADR | " " " P=0| --- -- | 3 |17/11| буемом состоянии, при 60 | CPE ADR | " " " P=1| --- -- | 3 |17/11! этом число тактов 17. 61 | CP ADR | " " " S=0| --- -- | 3 |17/11| В противном случае вы- 62 | CM ADR | " " " S=1| --- -- | 3 |17/11| полняется след, коман- | | | | | | да, а число тактов 11. | | | | | | 63 | RET |PC <-- M(SP,SP+1) | --- -- | 1 | 10 | Безусловный возврат из | | SP = SP + 2 | | | | подпрограммы. 64 | RNZ | Возврат при Z=0 | --- -- | 1 |11/5 | Условный возврат отра- 65 | RZ | " " Z=1 | --- -- | 1 |11/5 | батывается, если опре- 66 | RNC | " " C=0 | --- -- | 1 |11/5 | деленный признак нахо- 67 | RC | " " C=1 | --- -- | 1 |11/5 | дится в требуемом сос- 68 | RPO | " " P=0 | --- -- | 1 |11/5 | тоянии, при этом число 69 | RPE | " " P=1 | --- -- | 1 |11/5 | тактов 11. В противном 70 | RP | " " S=0 | --- -- | 1 |11/5 | случае выполняется 71 | RM | " " S=1 | --- -- | 1 |11/5 | следующая команда, а | | | | | | число тактов равно 5. | | | | | | 72 | RST V |PC-->M(SP-1,SP-2) | --- -- | 1 | 11 | Прерывание по вектору | |SP=SP-2, V*8-->PC | | 1 | | V*8. V = 0 ...7 Ввод-вывод и специальные команды | | | | | | 73 | IN N | A <-- P(N) | --- -- | 2 | 10 | Ввод (вывод) байта 74 | PUT N | A --> P(N) | --- -- | 2 | 10 | порта N в аккумулятор. | | | | | | 75 | EI | 1 --> INTE | --- -- | 1 | 4 | Разрешение прерываний. 76 | DI | 0 --> INTE | --- -- | 1 | 4 | Запрет прерываний. | | | | | | 77 | NOP | PC = PC + 1 | --- -- | 1 | 4 | Нет операции. | | | | | | 78 | HLT ! Останов | --- -- | 1 | 4 | МП переходит в режим | | | | | | останов. ------------------------------------------------------------------------------ В К Л А Д Ы Ш Таблица 8 ------------------------------------------------------------------------------ N | Дир.| Формат записи | Пояснения ---|-----|-----------------|-------------------------------------------------- 1 | ORG |METKA:ORG ADR | Размещение загрузочного модуля с адреса ADR. | | | METKA - имя метки - необязательно; | | | ADR - десятичное или шестнадцатиричное число. 2 | EQU |METKA:EQU CONST | Задание константы. | | | METKA - имя константы; | | | CONST - значение константы. 3 | DS |METKA:DS DIM | Резервирование памяти под переменные или массивы. | | | METKA - имя переменной / массива; | | | DIM - количество резервируемых байт памяти. 4 | DB |METKA:DB B1,B2...| Размещение данных в памяти побайтно. | | | METKA - имя переменной / массива - необязательно; | | | B1,B2...- список байт. 5 | DW |METKA:DW W1,W2...| Размещение данных в памяти двухбайтными словами. | | | W1,W2...- список двухбайтных слов. 6 | END | END | Конец текста программы. ------------------------------------------------------------------------------ Таблица 9 | 0 1 2 3 4 5 6 7 8 9 A B C D E F --+------------------------------------------------------------------------------------------------- 0 | NOP LXI B STAX B INX B INR B DCR B MVI B RLC - DAD B LDAX B DCX B INR C DCR C MVI C RRC | ** * * 1 | - LXI D STAX D INX D INR D DCR D MVI D RAL - DAD D LDAX D DCX D INR E DCR E MVI E RAR | ** * * 2 | - LXI H SHLD INX H INR H DCR H MVI H DAA - DAD H LHLD DCX H INR L DCR L MVI L CMA | ** ** * ** * 3 | - LXI SP STA INX SP INR M DCR M MVI M STC - DAD SP LDA DCX SP INR A DCR A MVI A CMC | ** ** * ** * 4 | MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV | B,B B,C B,D B,E B,H B,L B,M B,A C,B C,C C,D C,E C,H C,L C,M C,A 5 | MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV | D,B D,C D,D D,E D,H D,L D,M D,A E,B E,C E,D E,E E,H E,L E,M E,A 6 | MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV | H,B H,C H,D H,E H,H H,L H,M H,A L,B L,C L,D L,E L,H L,L L,M L,A 7 | MOV MOV MOV MOV MOV MOV HLT MOV MOV MOV MOV MOV MOV MOV MOV MOV | M,B M,C M,D M,E M,H H,L M,A A,B A,C A,D A,E A,H A,L A,M A,A 8 |ADD B ADD C ADD D ADD E ADD H ADD L ADD M ADD A ADC B ADC C ADC D ADC E ADC H ADC L ADC M ADC A | 9 |SUB B SUB C SUB D SUB E SUB H SUB L SUB M SUB A SBB B SBB C SBB D SBB E SBB H SBB L SBB M SBB A | A |ANA B ANA C ANA D ANA E ANA H ANA L ANA M ANA A XRA B XRA C XRA D XRA E XRA H XRA L XRA M XRA A | B |ORA B ORA C ORA D ORA E ORA H ORA L ORA M ORA A CMP B CMP C CMP D CMP E CMP H CMP L CMP M CMP A | C | RNZ POP B JNZ JMP CNZ PUSH B ADI RST 0 RZ RET JZ - CZ CALL ACI RST 1 | ** ** ** * ** ** ** * D | RNC POP D JNC OUT CNC PUSH D SUI RST 2 RC - JC IN CC - SBI RST 3 | ** * ** * ** * ** * E | RPO POP H JPO XTHL CPO PUSH H ANI RST 4 RPE PCHL JPE XCHG CPE - XRI RST 5 | ** ** * ** ** * F | RP POP JP DI CP PUSH ORI RST 6 RM SPHL JM EI CM - CPI RST 7 | PSW ** ** PSW * ** ** * ---------------------------------------------------------------------------------------------------- Таблица 5 ------------------------------------------------------------------------------ | | Команда | Условие | Пояснения | | ----------|-------------------|----------------------------------------------- | | CALL ADR | безусловный вызов | Вызов подпрограммы по адресу (с именем) ADR. | | CNZ ADR | вызов, если Z=0 | Вызов, если результат ненулевой. CZ ADR | " " Z=1 | " " результат нулевой. CNC ADR | " " C=0 | " " не было переноса/заема. CC ADR | " " C=1 | " " произошел перенос/заем. CPO ADR | " " P=0 | " " в результате нечетное кол-во "1". CPE ADR | " " P=1 | " " в результате четное кол-во "1". CP ADR | " " S=0 | " " результат положительный. CM ADR | " " S=1 | " " результат отрицательный. | | RET |безусловный возврат| Возврат из подпрогараммы в вызывавшую | | процедуру. RNZ | возврат, если Z=0 | Возврат, если результат ненулевой. RZ | " " Z=1 | " " результат нулевой. RNC | " " C=0 | " " не было переноса/заема. RC | " " C=1 | " " произошел перенос/заем. RPO | " " P=0 | " " в результате нечетное кол-во"1". RPE | " " P=1 | " " в результате четное кол-во "1". RP | " " S=0 | " " результат положительный. RM | " " S=1 | " " результат отрицательный. | | ------------------------------------------------------------------------------ Здесь результатом подпрограммы является признак нулевого результата Z. Если какой-то из элементов массива не совпадает с соответствующим элементом другого массива, то подпрограмма завершается командой RNZ, при этом признак Z будет сброшен в 0. Если все 16 элементов совпадают, то подпрограмма завершится на последней команде - RET, когда счетчик B досчитает до 0. В этом случае признак Z будет установлен в 1. Стек ---- Стек - это область памяти, к ячейкам которой организован последовательный доступ. Адресация к ЯП стека производится через указатель стека SP. Стек необ- ходим для функционирования команд вызова подпрограмм и возврата. Область памя- ти, резервируемая под стек, задается командой LXI SP. Ниже приведена схема, иллюстрирующая работу МП при выполнении команд CALL и RET. С адреса 7000H начинается программа. Первая ее команда LXI SP,STACK вы- полняет установку указателя стека SP=0B000H. Далее по адресу 74E2H находится команда вызова подпрограммы с именем SUBR (ее адрес 7C45H). Команда CALL вы- полняется следующим образом. Код команды (CD 45 7C) помещается процессором в RC1, RC2 и RC3. В счетчи- ке команд после этого будет адрес следующей команды PC=74E5H. Далее уменьшает- ся на 1 указатель стека SP=SP-1, его содержимое выставляется на ША, а на ШД выдается старший байт счетчика команд - PCh. По сигналу ЗП он записывается в память (74 --> M(AFFF)). Затем еще раз производится уменьшение SP на 1, и ана- логичным образом в памяти запоминается младший байт счетчика команд PCl (E5 --> M(AFFE)). И, наконец, в PC заносится содержимое RC2 и RC3 (7C45 --> PC). МП переходит к выполнению подпрограммы. Любая подпрограмма всегда завершается командой возврата. На схеме по ад- ресу 7C58H находится команда RET. По этой команде после выполнения подпрограм- мы SUBR производится возврат в основную программу. Процесс осуществляется следующим образом. При получении в RC1 кода 0C9H - 26 команда RET - на ША выставляется содержимое SP (по схеме в момент возврата SP=0AFFEH) и по сигналу ЧТ из памяти считывается байт данных, который заносит- ся в младший байт счетчика команд (E5 --> PCl). Затем указатель стека увеличи- вается на 1 - SP=SP+1 - и аналогичным образом из памяти извлекается старший байт адреса возврата (74 --> PCh). Указатель стека вновь увеличивается на 1 - SP=SP+1, после чего SP=0B000H. На этом выполнение команды RET заканчивается. Теперь в счетчике команд находится адрес команды, следующей за CALL SUBR (PC= 74E5H). Таким образом после RET будет выполнена команда MVI A,40H, т.е. МП продолжит выполнение основной программы. ORG 7000H | | | |------|------| START :LXI SP,STACK | 7000 | 31 | B000 --> SP |------|------| . | 7001 | 00 | . |------|------| . | 7002 | B0 | |------|------| | . | . | . | |------|------| CALL SUBR | 74E2 | CD | PCh --> M(SP-1) |------|------| PCl --> M(SP-2) | 74E3 | 45 | SP = SP - 2 |------|------| | 74E4 | 7C | 7C45 --> PC |------|------| MVI A,40H | 74E5 | 3E | |------|------| | 74E6 | 40 | |------|------| | . | . | . | |------|------| SUBR :MOV B,A | 7C45 | 47 | |------|------| ... | ... | |------|------| RET | 7C58 | C9 | M(SP-2) --> PCl |------|------| M(SP-1) --> PCh STACK :EQU 0B000H | . | SP = SP + 2 . | . | |------|------| SP-2 | AFFE | E5 | |------|------| адрес возврата SP-1 | AFFF | 74 | |------|------| SP | B000 | | |------|------| | . | Команды, использующие стек -------------------------- Стек удобен для временного хранения данных. При использовании стека нет необходимости резервировать память под отдельные переменные. Данные "сдаются на временное хранение" в одни и те же ячейки памяти. Таблица 6 ------------------------------------------------------------------------------ | | Команда | Алгоритм | Пояснения | | --------|--------------------|------------------------------------------------ | | PUSH X | X --> M(SP-1,SP-2) | Запись в стек содержимого рег. пары BC, DE, HL | SP = SP - 2 | или PSW. X: B, D, H, PSW. POP X | X <-- M(SP,SP+1) | Восстановление из стека содержимого рег. пары | SP = SP + 2 | BC, DE, HL или PSW. XTHL | HL <--> M(SP,SP+1) | Обмен данными между HL и стеком. | | SPHL | HL --> SP | Установка указателя стека SP=HL. | | ------------------------------------------------------------------------------ PSW - слово состояния процессора A+F. Команды PUSH и POP используются для временного сохранения состояния ре- гистров. Регистры сохраняются парами: BC, DE, HL. Сохранение / восстановление содержимого аккумулятора производится совместно с регистром признаков при по- мощи команд PUSH PSW / POP PSW. PSW (processor station word) - слово состоя- ния процессора - состоит из аккумулятора A и регистра признаков F. Обычно команды PUSH и POP используются в подпрограммах для сохранения ре- гистров, которые не должны изменяться подпрограммой, т.к. задействованы в ос- новной Программе. Особенность состоит в следующем: в каком порядке регистры сохраняются в стеке, в таком же порядке и восстанавливаются, только в обратной последовательности. Пример: EXAM40:СALL PROG1 |--------| ... SP* -->| BC | PROG1 :PUSH PSW |--------| PUSH H | DE | PUSH D |--------| PUSH B | HL | ... |--------| POP B | PSW | POP D |--------| POP H SP**-->| ADR | POP PSW |--------| RET SP -->| | 28 При вызове подпрограммы в стек заносится адрес возврата, затем происходит вы- полнение самой подпрограммы PROGl. Здесь последовательно записываются в стек слово состояния процессора PSW, регистровые пары HL, DE, BC. Во время каждой операции указатель стека уменьшается на 2. Таким образом в стеке сейчас хранится 10 байт. На рисунке положение ука- зателя стека соответствует SP*. После выполнения всех необходимых действий подпрограмма завершается. Пе- ред тем, как произойдет возврат в осносную программу, производится восстанов- ление регистров МП. При выполнении каждой команды POP указатель стека увеличи- вается на 2. Этим и обусловлена обратная последовательность восстановления ре- гистров: BC, DE, HL, PSW. Затем выполняется команда RET. К этому моменту ука- затель стека будет находиться в положении, которое на рисунке обозначено SP**. Это значит, что по команде RET в счетчик команд PC будет занесен адрес возвра- та в основную программу, и процессор продолжит выполнение программы. При этом для основной программы все регистры МП останутся неизменными, даже если в PROG1 выполнялись какие-нибудь действия с их использованием. Для примера вернемся к рассмотрению EXAM35 (стр. 24). В этом фрагменте программы каждый раз приходится задавать HL и DE. Рациональнее было бы сохра- нять содержимое этих регистровых пар в подпрограммах COMP и ZERO. В новой мо- дификации это будет выглядеть следующим образом: Команды ввода-вывода -------------------- Для взаимодействия с внешними устройствами в любом компьютере имеются порты ввода-вывода. С их помощью производится ввод информации, например, с клавиатуры или магнитофона и вывод, например, на принтер или дисковод. Для вы- полнения операций ввода-вывода в ассемблере существуют команды: IN N - ввод информации с порта N в аккумулятор; OUT N - вывод содержимого аккумулятора на порт N. N - однобайтный адрес (номер) порта ввода-вывода. - 0C0H - канал A; - 0C1H - канал B; - 0C2H - канал C. 0C3H - это номер управляющего регистра адаптера. Прерывания ---------- Иногда возникает необходимость вводить данные не в определенный момент времени, что обусловлено программой, а в любой независимый момент времени. Это производится при помощи прерывания. Приведем простой пример. При составлении динамической игровой программы необходимо предусмотреть ввод данных, например, с клавиатуры, чтобы игрок мог управлять каким-то объектом. Можно на протяжении всей программы производить обращение к подпрограмме обслуживания клавиатуры, а можно и организовать ввод с клавиатуры при помощи прерываний. Тогда при нажа- тии любой клавиши основная программа прерывается, обслуживается ввод с клавиа- туры, а затем возобновляется выполнение прерваной программы. Для этого в МП существует вход запроса на прерывание (INT) и предусмотре- на однобайтная команда прерывания RST V. Прерывание производится при помощи контороллера прерываний. На контроллер поступает сигнал от внешнего устройства (например, с клавиатуры), требующий осуществить ввод данных. Контроллер посы- лает на МП запрос на прерывание, а на ШД выставляет код команды RST V. Здесь V номер прерывания (0...7) соответствующий тому устройству, которое потребовало ввода (или вывода) данных. Под воздействием сигнала INT МП прекращает выполнение программы и считы- вает с ШД код команды, который заносится в RC1. По команде RST МП заносит в стек текущее значение счетчика команд (т.е. адрес следующей команды прерванной программы) и переходит на адрес V*8. Т.е. по RST 0 происходит вызов подпрог- раммы с адресом 0000H, по RST 1 - с адресом 0008H, по RST 2 - 0010H и т.д. 30 Адреса 0000H, 0008H, 0010H ...0038H называются векторами прерываний. Это начальные адреса подпрограмм обслуживания различных устройств ввода-вывода. Такая организация взаимодействия с внешними устройствами наиболее прием- лема и на практике широко используется. Все IBM-компьютеры осуществляют ввод- вывод данных по системе прерываний. Но это требует дополнительного оборудова- ния - контроллера прерываний. В компьютерах типа "Микроша", "Радио РК-86", "Львов", "Вектор" система прерываний не организована, но при этом команда RST свой смысл не утрачивает. Если в текст программы включить команду RST, то это будет равносильно ис- пользованию команды CALL. Разница в том, что команда RST однобайтная, a CALL трехбайтная. В этом основное преимущество. Например, Вы составили программу, в которой очень часто производится ссылка на какую-то подпрограмму. Тогда эту подпрограмму можно разместить начиная с одного из адресов 0000H, 0008H, 0010H ...0038H, а обращение к ней производить не при помощи CALL, а командой RST. Это может дать значительную экономию занимаемого программой объема памяти. Пример: ORG 30H EXAM42:LXI H,NAD HLDE :MOV A,H LXI D,KAD CMP D M1 :MVI M,0 RNZ INX H MOV A,L CALL HLDE CMP E JC M1 RET ... ... DATAD :PUSH H EXAM43:LXI H,NAD PUSH B LXI D,KAD M2 :LDAX B M1 :MVI M,0 ADD M INX H MOV M,A RST 6 INX H JC Ml INX B ... CALL HLDE DATAD :PUSH H JC M2 PUSH B POP B M2 :LDAX B POP H ADD M RET MOV M,A ... INX H HLDE :MOV A,H INX B CMP D RST 6 RNZ JC M2 MOV A,L POP B CMP E POP H RET RET В варианте слева задача решается традиционно. Для сравнения регистровых пар HL и DE введена подпрограмма HLDE, обращение к ней производится обычным способом - командой CALL HLDE. В варианте справа подпрограмма HLDE размещается с адреса 0030H (директива ORG 30H), таким образом она становится подпрограммой прерывания по вектору 30H. Теперь ее можно вызвать командой RST 6 (6 * 8 = 48 --> 30H), хотя мы име- ем полное право на использование команды CALL 30H или CALL HLDE. В EXAM43 об- ращение к HLDE производится при помощи RST 6, что предпочтительнее с точки зрения экономии памяти и быстродействия. Специальные команды ------------------- В отдельную группу можно выделить 4 команды, которые выполняют специфи- ческие функции: 31 EI - разрешение прерываний; DI - запрет прерываний; NOP- нет операции; HLT- останов. Команды EI, DI включают / выключают систему прерываний, их применение имеет смысл, если в компьютере есть контроллер прерываний и организована система прерываний. В этом случае с их помощью можно регулировать доступ внешних уст- ройств к ресурсам центрального процессора. Например, при разработке драйверов обслуживания магнитной ленты, чтобы избежать сбоев в записи, необходимо в на- чале процедуры поставить команду запрета пргрываний - DI, а в конце - разреше- ния прерывания - EI. По команде NOP процессор не производит никаких действий, программа будет выполняться дальше. Команда HLT переводит процессор в режим останова, компьютер "зависает". Применять ее в пользовательских программах не рекомендуется (как STOP в Бейси- ке). Заканчивать программу лучше всего командой перехода на точку старта сис- темы, например, JMP 0F800H. Команды и директивы ассемблера ------------------------------ Некоторые приемы программирования и полезные подпрограммы --------------------------------------------------------- В программировании на ассемблере существуют некоторые широко используемые приемы программирования. Чтобы читатель "не изобретал велосипед", рассмотрим наиболее тривиальные. 1. Обнуление аккумулятора Перед различными вычислениями бывает необходимо обнулить аккумулятор и сбро- сить в 0 признак переноса C и знак результата S. С этим успешно "справляется" команда XRA A. MVI A,0 в отличие от нее занимает 2 байта, дольше выполняется и не изменяет состояния признаков.
Поделиться32024-04-01 14:30:45
Код:
32 2. Приращение адреса В процедуре обработки некоторого массива приращение адреса может быть не через 1 байт, а больше. Тогда логично было бы ввести следующую группу команд: ... LXI B,3 DAD B ... Здесь в HL текущий адрес, приращение производится через 3 байта. Однако такая конструкция занимает 4 байта в памяти, и приходится задействовать регистровую пару BC. Если ввести еще PUSH В и POP B, то будет недопустимо большой перерас- ход памяти и потеря быстродействия. Гораздо "симпатичнее" другая конструкция: ... INX H INX H INX H ... Выполняется всего за 15 тактов, занимает 3 байта и не задействует лишних ре- гистров. 3. Сравнение регистровых пар Для сравнения двухбайтных чисел, находящихся в регистровых парах HL и DE лучше всего воспользоваться подпрограммой HLDE, приводимой в EXAM42 (стр. 31). Ее результатом будет состояние признаков: - при HL > DE C=0, Z=0 (JNC, JNZ); - при HL = DE C=0, Z=1 (JZ); - при HL < DE C=l, Z=0 (JC). Действие подпрограммы HLDE схоже с действием команды CMP, где результатом яв- ляется также состояние признаков. 4. Организация цикла с числом исполнения больше 255 В качестве счетчика цикла применяется не регистр, а регистровая пара, напри- мер, BC: LXI B,1F4H ; BC=500 CYCL :PUSH B ... ; тело цикла POP B DCX B ; BC=BC-1 MOV A,B ORA C ; BC=0 ? JNZ CYCL ; если нет, то продолжить Если в теле цикла не задействуются регистры B и C, то команды PUSH B и POP B можно исключить. 5. Ветвящийся процесс с возвратом в одну точку Предположим, что в программе принимается какое-то многовариантное решение, и по каждому варианту отрабатывается индивидуальная процедура, а после этого процесс вновь выполняется по одной ветви. Например: ... LDA PARAM MM1 :... ; процедура 1 CPI 3 JMP MET JZ MM1 MM2 :... ; процедура 2 CPI 4 JMP MET JZ MM2 MM3 :... ; процедура 3 CPI 8 JMP MET JC MM3 ... ... ; процедура 4 MET :. . ; продолжение JMP MET 33 В конце каждой процедуры следует команда JMP MET. Если в стек занести адрес перехода, то ее можно заменить командой RET. Переделаем наш пример: ... LXI H,MET; адрес возврата MM1 :... ; процедура 1 PUSH H ; занести в стек RET LDA PARAM MM2 :... ; процедура 2 CPI 3 RET JZ MM1 MM3 :... ; процедура 3 CPI 4 RET JZ MM2 ... CPI 8 MET :... ; продолжение JC MM3 ... ; процедура 4 RET Теперь в конце каждой процедуры по команде RET из стека будет извлекаться ад- рес метки с именем MET и осуществляться переход. Такой прием при большом коли- честве отрабатываемых процедур дает значительную экономию памяти, т.к. трех- байтная команда JMP MET заменяется на однобайтную RET. Если содержимое HL изменять нельзя, тогда две первых команды надо заме- нить на конструкцию: PUSH H LXI H,MET ==> LXI H,MET PUSH H XTHL Здесь сначала HL сохраняется в стеке, а затем заменяется командой XTHL на ад- рес возврата. Сохраненное значение вернется в HL. 6. Подпрограмма умножения Для операции умножения специальной команды в ас- MULT :LXI B,80H семблере К580 нет. Умножение двух однобайтных MULT1 :MOV A,D чисел можно производить при помощи приведенной RAR здесь подпрограммы MULT. Перед обращением к ней MOV D,A перемножаемые числа необходимо занести в регистры JNC MULT2 D и E. Результат - 16-разрядное число - будет в MOV A,B регистровой паре BC. ADD E MOV B,A Умножение производится по принципу: если очеред- MULT2 :MOV A,B ной бит регистра D равен 1, то прибавить к ре- RAR зультату содержимое регистра E. Специально для MOV B,A счета циклов никакой регистр не выделен. По про- MOV A,C шествии 8-ми сдвигов в регистре C в признак пере- RAR носа попадет 1, что и явится сигналом окончания. MOV C,A JNC MULT1 В подпрограмме не участвует регистровая пара HL. RET Остальные регистры (DE и PSW) при необходимости можно сохранить в стеке. 7. Подпрограмма деления Аналогичным образом составлена подпрограмма деле- DIV :LXI B,100H ния DIV. Здесь производится деление однобайтных DIV1 :MOV A,D чисел D / E, при этом в B будет частное, а в L - RAL остаток. MOV D,A В подпрограмме не участвует HL. Регистры DE и PSW MOV A,C при необходимости можно сохранить в стеке. RAL SUB E MOV A,B JNC DIV2 RAL ADD E MOV B,A DIV2 :MOV C,A JNC DIV1 CMC RET 34 8. Вывод текста на экран Традиционно для вывода сообщений на экран используют следующую конструкцию: LXI H,TXT1 Процедура вывода реализована в подпрограмме CALL STRING STRING. Обычно она есть в ПЗУ компьютера (у ... "Львова" - 0E4A4H, у "Радио" и "Микроши" - LXI H,TXT2 0F818H). Символы выводимого текста должны быть CALL STRING размещены в памяти один за другим и заканчи- ваться нулевым байтом. Перед обращением к под- TXT1 :DB 'НЕ ' программе в HL необходимо занести адрес начала TXT2 :DB 'ГОТОВ',0DH,0 текста. STRING:MOV A,M ORA A В приведенном примере при первом обращении к RZ STRING на экран выводится:"НЕ ГОТОВ", при вто- MOV C,A ром обращении:"ГОТОВ". Для вывода символа на CALL TTY экран используется подпрограмма TTY. В компью- INX H терах "Львов", "Радио", "Микроша" она тоже JMP STRING "зашита" в ПЗУ, ее адрес 0F809H. TTY :EQU 0F809H Недостатком этого метода является то, что задействуется регистровая пара HL, а тексты сообщений необходимо выносить в отдельные блоки данных. Подпрограмма PRINT, приведенная ниже, свободна от этих недостатков, а ее применение схоже с действием оператора PRINT в Бейсике. PRINT :XTHL Здесь выводимое сообщение также должно закан- PUSH B чиваться нулевым байтом, но располагается оно PUSH PSW не отдельно, а непосредственно в тексте прог- PRIN1 :MOV A,M раммы сразу за командой CALL PRINT. При отра- INX H ботке PRINT все регистры сохраняются. ORA A JZ PRIN2 Действие подпрограммы основано на том, что MOV C,A сразу после перехода на подпрограмму команда CALL TTY XTHL извлекает из стека адрес возврата. Это JMP PRIN1 будет адрес первого байта выводимого сообще- PRIN2 :POP PSW ния. Содержимое HL при этом помещается в стек. POP B Затем выполняется знакомая нам по STRING про- XTHL цедура вывода с использованием той же TTY. А RET вот когда МП "наткнется" на нулевой байт, то TTY :EQU 0F809H происходит переход к PRIN2, где опять стоит ... команда XTHL. Теперь в HL находится адрес бай- CALL PRINT та, следующего за нулевым. Это новый адрес DB 'СТРОКА1',0DН,0 возврата. По команде XTHL он будет занесен в ... стек, а из стека восстановится значение HL. По CALL PRINT команде RET из стека извлекается уже новый ад- DB 'STRING2',0DH,0 рес возврата и продолжается выполнение основ- XRA A ной программы (во втором случае, начиная с ... XRA A). Однако подпрограмма PRINT лишена приемущества STRING. Здесь нельзя выводить одно и тоже сообщение несколько раз или "нанизывать" сообщения одно на другое. Для вывода "ГОТОВ" и "НЕ ГОТОВ" оба сообщения придется указать в тексте прог- раммы раздельно. 9. Вывод значения переменной в десятичной форме Часто бывает необходимо вывести на экран значение переменной в десятичной фор- ме, например, в игровой программе - количество очков. Ниже приведена подпрог- рамма NUM, которая производит вывод на экран значения двухбайтной переменной 35 без знака (00000 ...65535). Перед обращением к ней выводимое значение необхо- димо занести в HL. NUM :PUSH H ; сохранение MVI B,5 PUSH D ; регистров NUM3 :MOV A,M PUSH B ADI 30H ; вывод N в десятич- PUSH H ; HL в стек MOV C,A ; ной форме, начиная LXI B,910H CALL TTY ; со старших разрядов LXI H,C DCX H MVI M,1 ; C=1 DCR B NUM0 :INX H JNZ NUM3 MVI M,0 ; N=0 POP H ; HL из стека DCR B POP B JNZ NUM0 POP D ; восстановление LXI D,C POP H ; регистров NUM1 :POP H ; HL из стека RET XRA A SUM :PUSH D ; сохранить DE MOV A,H ; сдвиг HL MVI B,5 RAR ; вправо XRA A MOV H,A ; и выделение SUM0 :LDAX D ; сложение двух MOV A,L ; младшего ADC M ; 5-байтных перемен- RAR ; бита CPI 10 ; ных по адресам MOV L,A JC SUM1 ; HL и DE с учетом PUSH H ; HL в стек SUI 10 ; десятичного JNC NUM2 SUM1 :CMC ; переноса LXI H,N ; если бит=1, MOV M,A CALL SUM ; то N=N+C INX H ; результат сокраня- NUM2 :LXI H,C INX D ; ется в переменной CALL SUM ; C=C*2 DCR B ; по HL DCR C JNZ SUM0 JNZ NUM1 ; цикл (16 раз) POP D ; восстановить DE LXI H,N RET INX H C :DS 5 ; основание разряда INX H N :DS 5 ; результат INX H TTY :EQU 0FB09H INX H ; HL=N+4 Для работы подпрограммы введены две 5-байтные переменные C и N. C - промежу- точная переменная, N - результат, где производится распаковка двоичного числа в двоично-десятичный код. Вывод результата на экран осуществляется при помощи подпрограммы TTY (0F809H). Программирование в кодах ------------------------ Программирование на ассемблере предполагает обязательное транслирование текста программы в машинные коды. В принципе можно писать программу сразу в кодах. Некоторые программисты-профессионалы владеют этим искусством не хуже, чем языками высокого уровня. Вообще, иметь навык работы с машинными кодами очень полезно. Вы без труда сможете разобраться в чужой программе, это приго- дится и при отладке программ, и при "склеивании" нескольких загрузочных моду- лей в единое целое. Для перевода мнемоники команды в машинный код или наоборот используйте таблицу 9 (на вкладыше). Слева по вертикали старший разряд кода (старшая тет- рада байта), а вверху по горизонтали - младший разряд (младшая тетрада). Если в клеточке команды есть еще "*" или "**", это значит, что команда двух- или трехбайтная. 36 Пример: перевести в коды фрагмент MVI A,30H STA 76A0H XRA A Код команды MVI A - 3E, кроме того эта команда двухбайтная, необходимо указать байт, заносимый в аккумулятор. Получается 3E 30. Код STA будет 32. Дополни- тельно необходимо указать адрес ЯП - два байта. Как и все двухбайтные величины адрес записывается в следующем порядке: сначала младший байт, а затем - стар- ший. Получается 32 A0 76. Затем пишем код команды XRA A - AF. Команда одно- байтная, больше ничего указывать не надо. Получилось шесть байт машинных ко- дов: 3E 30 32 A0 76 AF Машинные коды принято записывать в шестнадцатиричном формате, т.к. боль- шинство программ, работающих с кодами (мониторы, отладчики и т.д.) оперируют шестнадцатиричными числами. Для удобства программирования в кодах ниже приве- дены таблицы, помогающие переводить числа в двоичный (BIN), десятичный (DEC) или шестнадцатиричный формат (HEX). Таблица 10 ---------------------------------------------------------------------------- |DEC|BIN |HEX| 0 1 2 3 4 5 6 7 8 9 A B C D E F | |---|----|---|---------------------------------------------------------------| | | | | | | 0 |0000| 0 | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15| | 1 |0001| 1 | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31| | 2 |0010| 2 | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47| | 3 |0011| 3 | 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63| | 4 |0100| 4 | 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79| | 5 |0101| 5 | 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95| | 6 |0110| 6 | 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111| | 7 |0111| 7 |112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127| | 8 |1000| 8 |128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143| | 9 |1001| 9 |144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159| |10 |1010| A |160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175| |11 |1011| B |176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191| |12 |1100| C |192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207| |13 |1101| D |208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223| |14 |1110| E |224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239| |15 |1111| F |240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255| | | | | | ---------------------------------------------------------------------------- Таблица 10, кроме того, будет полезна при переводе шестнадцатиричных машинных кодов в десятичные числа для последующего занесения их в Бейсик-программу опе- ратором DATA. Сопряжение Бейсик-программы с подпрограммами в кодах ---------------------------------------------------- Программирование на ассемблере сопряжено с трудностями при необходимости каких-либо математических вычислений или ввода-вывода различных числовых дан- ных. В тоже время Бейсик существенно ограничен по части доступа к аппаратным ресурсам компьютера и особенно по части быстродействия. Разумный компромисс достигается при подключении к Бейсик-программе программных модулей в машинных кодах. Рассмотрим такое сопряжение на примере. 37 Составим программу простейшего синтезатора речи к компьютеру "Львов" ПК- 01. Для ввода речевого сигнала в память задействуем магнитофонный ввод. Коди- рование речи производится по принципу дельта-модуляции. Вывод сигнала на вос- произведение осуществляется на внутренний динамик или магнитофон. Частота дис- кретизации около 8000 Гц. Естественно Бейсик с этой задачей не справится. Про- цедуры ввода речевого сигнала в память и выдачи на динамик реализуются на ас- семблере. ORG 0AD01H AD32 C5 OUTRAM:PUSH B AD01 CONST :DS 1 AD33 D5 PUSH D AD02 DEL :DS 2 AD34 E5 PUSH H NACH :EQU 3000H AD35 F5 PUSH PSW AD04 C5 INRAM :PUSH B AD36 110030 LXI D,NACH AD05 D5 PUSH D AD39 2A02AD LHLD DEL AD06 E5 PUSH H AD3C EB XCHG AD07 F5 PUSH PSW AD3D 7E OUT1 :MOV A,M AD08 110030 LXI D,NACH AD3E CD4DAD CALL OUTB AD0B 2A02AD LHLD DEL AD41 23 INX H AD0E EB XCHG AD42 1B DCX D AD0F CD1FAD INR1 :CALL INBYT AD43 7A MOV A,D AD12 77 MOV M,A AD44 B3 ORA E AD13 23 INX H AD45 C23DAD JNZ OUT1 AD14 1B DCX D AD48 F1 POP PSW AD15 7A MOV A,D AD49 El POP H AD16 B3 ORA E AD4A D1 POP D AD17 C20FAD JNZ INR1 AD4B C1 POP B AD1A F1 POP PSW AD4C C9 RET AD1B E1 POP H AD4D 0E0B OUTB :MVI C,8 AD1C D1 POP D AD4F 47 MOV B,A AD1D Cl POP B AD50 78 OUT2 :MOV A,B AD1E C9 RET AD51 07 RLC AD1F 0E08 INBYT :MVI C,8 AD52 47 MOV B,A AD21 CD61AD INB1 :CALL TIME AD53 E601 ANI 1 AD24 DBC2 IN 0C2H AD55 F602 ORI 2 AD26 17 RAL AD57 D3C2 OUT 0C2H AD27 17 RAL AD59 CD61AD CALL TIME AD28 17 RAL AD5C 0D DCR C AD29 17 RAL AD5D C250AD JNZ OUT2 AD2A 78 MOV A,B AD60 C9 RET AD2B 17 RAL AD61 3A01AD TIME :LDA CONST AD2C 47 MOV B,A AD64 3D TIM1 :DCR A AD2D 0D DCR C AD65 C264AD JNZ TIM1 AD2E C221AD JNZ INB1 AD68 C9 RET AD31 C9 RET Кодирование и запись сигнала в память осуществляет подпрограмма INRAM, ее адрес 0AD04H. Ввод сигнала и формирование байта информации производит подпрог- рамма INBYT. Частота дискретизации регулируется подпрограммой задержки TIME. Величину задержки определяет содержимое ЯП CONST (адрес 0AD01H). Вывод сигнала на динамик и магнитофонный выход производит подпрограмма OUTRAM, ее адрес 0AD32H. Вывод осуществляется при помощи OUTB - подпрограммы выдачи байта информации в последовательном коде. Скорость выдачи определяется подпрограммой TIME. Начальный адрес записи / воспроизведения речевого сигнала 3000H. Длина массива задается в DEL - ЯП 0AD02H и 0AD03H. Параметры CONST и DEL передаются из Бейсик-программы, по этому ЯП с адре- сами 0AD01H ...0AD03H (44289 ...44291) являются ячейками связи. Слева от текста ассемблерной программы расположены адреса и машинные коды команд (объектный модуль). Шестнадцатиричные коды необходимо перевести в деся- тичные числа и занести в Бейсик-программу при помощи оператора DATA. Ниже представлен текст программы синтезатора речи на Бейсике. 38 10 DATA 197,213,229,245,17,0,48,42,2,173 500 REM ВОСПРОИЗВЕДЕНИЕ 20 DATA 235,205,31,173,119,35,27,122,179 510 POKE 44289,S 30 DATA 194,15,173,241,225,209,193,201 520 X=INT(V/256) 40 DATA 14,8,205,97,173,219,194,23,23,23 530 POKE 44290,V-X*256 50 DATA 23,120,23,71,13,194,33,173,201 540 POKE 44291,X 60 DATA 197,213,229,245,17,0,48,42,2,173 550 POKE 73,50: POKE 74,173 70 DATA 235,126,205,77,173,35,27,122,179 560 US=USR(US) 80 DATA 194,61,173,241,225,209,193,201 570 RETURN 90 DATA 14,8,71,120,7,71,230,1,246,2,211 600 REM СКОРОСТЬ 100 DATA 194,205,97,173,13,194,80,173,201 610 LOCATE 0,8,1 110 DATA 58,1,173,61,194,100,173,201,-1 620 PRINT"СКОРОСТЬ (1/2) ==>"; 120 REM 630 GOSUB 800 130 REM РАЗМЕЩЕНИЕ П/ПР. В ОЗУ 640 IF I¤="1" THEN S=5 140 REM 650 IF I¤="2" THEN S=1 150 A=44292: REM 0AD04H 660 IF I¤<>"1"ANDI¤<>"2" THEN 610 160 READ X: IF X<0 THEN 180 670 GOSUB 900: RETURN 170 POKE A,X: A=A+1: GOTO 160 700 REM ОБ'EM 180 REM 710 LOCATE 0,8,1 190 REM ОСНОВНАЯ ПРОГРАММА 720 INPUT"ОБ'ЕМ (НЕ > 32000)=";V 200 REM 730 IF V>32000 THEN 710 210 CLS: PRINT 740 GOSUB 900: RETURN 220 PRINT"СИНТЕЗАТОР РЕЧИ" 800 I¤=INKEY¤ 230 PRINT"**** МЕНЮ *****" 810 IF LEN(I¤)=0 THEN 800 240 PRINT"1-ВВОД РЕЧИ" 820 PRINT I¤: BEEP 250 PRINT"2-ВОСПРОИЗВЕДЕНИЕ" 830 RETURN 260 PRINT"3-СКОРОСТЬ" 900 LOCATE 0,8,1 270 PRINT"4-ОБ'ЕМ" 910 FOR I=1 TO 64 280 V=16000: S=1 920 PRINT" "; 300 LOCATE 0,7,1: PRINT"==>"; 930 NEXT I 310 GOSUB 800: IN=ASC(I¤>-47 940 RETURN 340 ON IN GOSUB 300,400,500,600,700,300 350 GOTO 300 400 REM ВВОД РЕЧИ 410 POKE 44289,S 420 X=INT(V/256) 430 POKE 44290,V-X*256 440 POKE 44291,X 450 POKE 73,4: POKE 74,173 460 PRINT"ВКЛЮЧИТЕ МАГНИТОФОН В РЕЖИМ" 465 PRINT"ЗАПИСЬ+ПАУЗА И НАЖМИТЕ <ВК>" 470 GOSUB 800: US=USR(US) 480 BEEP: GOSUB 900: BEEP 490 RETURN Строки 10-110 - это программные модули в машинных кодах. Они заносятся в ОЗУ при помощи оператора POKE (строки 150-170) в область с адресами 0AD04H ... 0AD68H. Именно для этой области были оттранслированы подпрограммы. Собственно программа начинается со строки 210 - меню программы - и состоит из 4-х частей: ввод речи - 400, воспроизведение - 500, установка скорости - 600, установка объема массива - 700. Скорость определяется переменной S. Если на запрос "СКОРОСТЬ (1/2) ==>" нажать клавишу "1", то будет установлено значение S=5 - низкая скорость, для "2" - S=1 - высокая скорость. Значение переменной S перед обращением к подпро- грамме INRAM или OUTRAM заносится в ЯП по адресу 44289 (0AD01H - CONST). Переменная V - объем массива. V не должно превышать 32000, иначе массив данных наложится на подпрограммы в кодах, располагающиеся с адреса 0AD01H (вместе с ячейками связи). 39 Ввод речи заключается в том, что в ячейки связи заносятся требуемые пара- метры: 44289 (0AD01H) - задержка S, 44290 (0AD02H) - младший байт переменной V, 44291 (0AD03H) - старший байт V. Затем в ячейки 73, 74 заносится адрес вы- зова подпрограммы INRAM - 4 (04H), 173 (0ADH) - и производится ее вызов US= USR(US). Окончание ввода сигнализируется звуковым сигналом - оператор BEEP. Аналогичным образом осуществляется воспроизведение звука. Разница заклю- чается в том, что в ячейки 73, 74 заносится адрес подпрограммы OUTRAM - 50 (32H), 173 (0ADH). Для ввода речи используется магнитофон со встроенным микрофоном. При по- мощи регулировки уровня записи можно добиться достаточно разборчивого звучания речи. Качество повышается, если в тракт ввода-вывода включить ФНЧ с частотой среза около 4 кГц. На низкой скорости и при V=32000 время записи / воспроизве- дения достигает 30 секунд.
Страница: 1