Передовица (меню разделов)
⇓
Документы
⇓
Не сортировано
⇓
Программирование для ПЭВМ АГАТ
****************************** * * * A L V * * COMPUTER AND PROGRAMME * * CORPORATION * * * ******************************
Сей документ не является руководством по программированию на языках высокого уровня - Бейсик, Рапира, а освещает приёмы составления программ на языке ассемблера и в машинных кодах.
В микро-ЭВМ "Агат" установлен микропроцессор 6502 (USA), система команд которого и будет рассматриваться далее. В основном программное обеспечения компьютера APPLE II подходит для использования в "Агате", но в деталях отличается (по вине конструкторов: за это давайте их коллективно поругаем. Если уж взялись делать новую машину - должны быть за неё ответственны!)
1. МИКРОПРОЦЕССОР
Каждый микропроцессор, в том числе и 6502, характеризуется определённой системой команд. Система команд - это полный перечень элементарных действий, которые способен производить микропроцессор. Управляемый этими командами микропроцессор выполняет очень простые действия, такие, как элементарные арифметические и логические операции, операции пересылки данных, сравнения двух величин и другие. Однако, составив программу из последовательности таких команд, можно запрограммировать выполнение алгоритма любой сложности. Память, адресуемая микропроцессором, представляет собой последовательность байтов (байт - это машинное слово, содержащее 8 бит).
По формату (числу отведённых для неё разрядов) команды делятся на одно-, двух-, трёхбайтовые. Байты команды последовательно друг за другом располагаются соответственно в одной, двух или трёх ячейках ЗУ (запоминающего устройства) микро-ЭВМ. Первый байт любой команды содержит код операции. Он определяет формат команды и те действия, которые должны быть произведены микропроцессором над данными в процессе её выполнения. Эти данные обычно называются операндами.
Микропроцессор имеет сложную структуру, но с точки зрения программиста он состоит только из пяти 8-разрядных (речь идёт о двоичных числах) регистров A, X, Y, регистра признаков выполнения операции F, регистра указателя стека S и 16-разрядного регистра указателя очереди команд PC.
Рассмотрим назначение внутренних регистров микропроцессора. Регистр A, так называемый аккумулятор, используется для хранения операнда, с которым работает арифметико-логическое устройство (АЛУ) микропроцессора. Результат по окончании обработки данных вновь помещают в регистр A.
Для изучения системы команд и написания программ важно знать способы адресации, которые заложены в микропроцессоре, т.е. знать, как происходит формирование кода на шине адресов.
При обращении к памяти и для чтения кода очередной команды из микропроцессора на шину адресов поступает содержимое 16-разрядного регистра PC, называемого счётчиком команд. В этом регистре к моменту окончания выполнения текущей команды всегда подготавливается адрес следующей команды программы. Во время выполнения программы микропроцессору необходимо обращаться к определённым ячейкам памяти для чтения и записи промежуточных данных. В системе команд имеется команды, с помощью которых можно задать адрес обращения к памяти непосредственно (команды с непосредственной адресацией). Они имеют двух или трёхбайтовый формат. В первом случае во втором байте команды находится адрес одной из первых 256 ячеек памяти. Во втором - адрес ячейки определяется вторым и третьим байтами команды.
В системе команд есть также двухбайтовые команды для косвенной адресации по двум соседним ячейкам, находящимся в области первых 256 адресов.
Кроме описанных двух способов адресации возможна адресация к ячейкам памяти по 8-разрядному регистру указателя стека S.
Под стеком в микропроцессоре 6502 подразумевается область памяти из 256 ячеек, расположенных непосредственно за ячейками данных с короткой адресацией. Адресация к ним осуществляется с помощью указателя стека S. При обращении к ячейке памяти, расположенной в стековой области, на шину адресов передаётся содержимое регистра S. С помощью команд, использующих стековую адресацию, в стек можно переслать любое 8-разрядное число из аккумулятора.
Запись числа в память в ячейку с адресом на единицу меньше указателя стека (т.е. в ячейку с адресом S-1). Таким образом, после записи содержимое указателя стека становится равным (S-1).
В системе команд микропроцессора есть команды, которые позволяют осуществить обратную операцию, т.е. переслать содержимое стека в аккумулятор или в счётчик команд PC. При этом сначала в регистр PC переписывается младший байт из ячейки памяти, адресуемый текущим положением указателя стека, затем старший байт из ячейки памяти с адресом S+1. После выполнения команды указатель стека принимает значение S+2.
Достоинством команд с адресацией по указателю стека является то, что программист может не заботиться каждый раз о конкретных адресах ячеек памяти, куда записывают и откуда считывают данные. Ему необходимо только соблюдать последовательность при записи данных в стек и их извлечении. При этом говорят, что при работе со стеком используется принцип "последний пришёл - первый вышел".
Для хранения в памяти 16-разрядного числа всегда отводятся две смежные ячейки. Запись чисел в эти ячейки происходит побайтно, причём в ячейку с меньшим адресом записывается младший байт, а в ячейку с большим адресом заносится старший байт числа. Это правило выполняется при любых способах адресации, а также при записи в память трёхбайтовых команд, где второй и третий байты являются соответственно младшим и старшим байтами 16-разрядного числа.
2.СИСТЕМА КОМАНД
При написании программ для микро-ЭВМ программисту необходимо хорошо знать её систему команд. Это означает, что программист должен помнить весь перечень команд, хорошо представлять себе те действия, которые будут выполняться микропроцессором при выполнении каждой из них.
Код операции любой команды (для однобайтовой команды - это просто код команды) в ЗУ микро-ЭВМ представляется двоичным 8-разрядным числом. Всего двоичным кодом можно представить 256 различных комбинаций. Почти столько же команд, около 200, имеет и микропроцессор 6502.
Естественно, что запомнить такое количество двоичных чисел почти невозможно. Поэтому каждому коду команды ставится в соответствие мнемоническое название (мнемоника) команды, которая является сокращением от английских слов, описывающих её действие. Мнемонический код команды позволяет легче запомнить их функции и значительно упрощает написание программ.
После мнемоники для двухбайтовых команд записывается 8-разрядный операнд, обозначаемый при описании системы команд "8"; "8,X"; "8,Y"; "(8,X)"; "(8),Y", а для трёхбайтовых команд - "16"; "16,X"; "16,Y". Разберём что это означает: "8" - восьмиразрядный операнд для непосредственного использования. "8,X" - здесь к 8-разрядному числу предварительно прибавляется содержимое регистра X. "8,Y" - то же, только предварительно прибавляется содержимое регистра Y. "(8,X)" - косвенная адресация по двум соседним ячейкам, адрес младшей указывается в поле команды. Перед исполнением команды к операнду 8 прибавляется содержимое регистра X. Получившееся число и является адресом младшей ячейки, используемой при косвенной адресации. "(8),Y" - используется так же для косвенной адресации, но назначение регистра Y здесь другое. Его значение прибавляется к уже вычисленному значению по двум ячейкам. Т.е. его изменение приводит к изменению косвенного адреса, а не адреса ячеек для косвенной адресации. "16" - шестнадцатиразрядный операнд для непосредственного использования. "16;X" и "16;Y" - тоже что и "8,X", "8,Y", только с шестнадцатиразрядным операндом.
Все команды микропроцессора 6502 приведены ниже. Слева указан код команды, справа её мнемоническое обозначение. Далее для наглядности и упрощения записи все двоичные коды будем представлять в шестнадцатеричном виде. Для этого двоичный код числа делится на группы по 4 разряда. Для 8-разрядного кода операции или операнда таких групп будет две, а для 16-разрядного адреса таких групп будет четыре. Четырёхразрядным двоичным кодом можно представить любое десятичное число от 0 до 15. Обозначив эти величины цифрами от 0 до 9 и далее буквами латинского алфавита от A де F, мы получим шестнадцатеричные цифры. В таблице приведено соответствие между десятичными, двоичными, шестнадцатеричными значениями величин.
десятичное двоичное шестнадцат. 0 0000 0 1 0001 1 2 0010 2 3 0011 3 4 0100 4 5 0101 5 6 0110 6 7 0111 7 8 1000 8 9 1001 9 10 1010 A 11 1011 B 12 1100 C 13 1101 D 14 1110 E 15 1111 F
Например, двоичный код 11000011 можно представить в виде шестнадцатеричного числа C3, операнду или коду B8 соответствует код 10111000, а адресу F204 - код 1111001000000100.
Таблица кодов команд Код команды - Мнемоника Тип адресации 00 - BRK 01 - ORA (8,X) 05 - ORA 8 06 - ASL 8 08 - PHP 09 - ORA #8 0A - ASL 0D - ORA 16 0E - ASL 16 10 - BPL 8 11 - ORA (8),Y 15 - ORA 8,X 16 - ASL 8,X 18 - CLC 19 - ORA 16,Y 1D - ORA 16,X 1E - ASL 16,X 20 - JSR 16 21 - AND (8,X) 24 - BIT 8 25 - AND 8 26 - ROL 8 28 - PLP 29 - AND #8 2A - ROL 2C - BIT 16 2D - AND 16 2E - ROL 16 30 - BMI 8 31 - AND (8),Y 35 - AND 8,X 36 - ROL 8,X 38 - SEC 39 - AND 16,Y 3D - AND 16,X 3E - ROL 16,X 40 - RTI 41 - EOR (8,X) 45 - EOR 8 46 - LSR 8 48 - PHA 49 - EOR #8 4A - LSR 4C - JMP 16 4D - EOR 16 4E - LSR 16 50 - BVS 8 51 - EOR (8),Y 55 - EOR 8,X 56 - LSR 8,X 58 - CLI 59 - EOR 16,Y 5D - EOR 16,X 5E - LSR 16,X 60 - RTS 61 - ADC (8,X) 65 - ADC 8 66 - ROR 8 68 - PLA 69 - ADC #8 6A - ROR 6C - JMP (16) 6D - ADC 16 6E - ROR 16 70 - BVS 8 71 - ADC (8),Y 75 - ADC 8,X 76 - ROR 8,X 78 - SEI 79 - ADC 16,Y 7D - ADC 16,X 7E - ROR 16,X 81 - STA (8,X) 84 - STY 8 85 - STA 8 86 - STX 8 88 - DEY 8A - TXA 8C - STY 16 8D - STA 16 8E - STX 16 90 - BCC 8 91 - STA (8),Y 94 - STY 8,X 95 - STA 8,X 96 - STX 8,Y 98 - TYA 99 - STA 16,Y 9A - TXS 9D - STA 16,X A0 - LDY #8 A1 - LDA (8,X) A2 - LDX #8 A4 - LDY 8 A5 - LDA 8 A6 - LDX 8 A8 - TAY A9 - LDA #8 AA - TAX AC - LDY 16 AD - LDA 16 AE - LDX 16 B0 - BCS 8 B1 - LDA (8),Y B4 - LDY 8,X B5 - LDA 8,X B6 - LDX 8,Y B8 - CLV B9 - LDA 16,Y BA - TSX BC - LDY 16,X BD - LDA 16,X BE - LDX 16,Y C0 - CPY #8 C1 - CMP (8,X) C4 - CPY 8 C5 - CMP 8 C6 - DEC 8 C8 - INY C9 - CMP #8 CA - DEX CC - CPY 16 CD - CMP 16 CE - DEC 16 D0 - BNE 8 D1 - CMP (8),Y D5 - CMP 8,X D6 - DEC 8,X D8 - CLD D9 - CMP 16,Y DD - CMP 16,X DE - DEC 16,X E0 - CPX #8 E1 - SBC (8,X) E4 - CPX 8 E5 - SBC 8 E6 - INC 8 E8 - INX E9 - SBC #8 EA - NOP EC - CPX 16 ED - SBC 16 EE - INC 16 F0 - BEQ 8 F1 - SBC (8),Y F5 - SBC 8,X F6 - INC 8,X F8 - SED F9 - SBC 16,Y FD - SBC 16,X FE - INC 16,X
Полный список команд включает в себя все коды. На самом же деле команд меньше (56). В полном списке они отличаются лишь операндами, а сама операция, производимая командой, остаётся такой же.
Список команд в алфавитном порядке: ADC, AND, ASL, BCC, BCS, BEQ, BIT, BMI BNE, BPL, BRK, BVC, BVS, CLC, CLD, CLI CLV, CMP, CPX, CPY, DEC, DEX, DEY, EOR INC, INX, INY, JMP, JSR, LDA, LDX, LDY LSR, NOP, ORA, PHA, PHP, PLA, PLP, ROL ROR, RTI, RTS, SBC, SEC, SED, SEI, STA STX, STY, TAX, TAY, TSX, TXA, TXS, TYA
В полном списке команд встречается ещё один операнд, который не был описан ранее - #8. Он означает, что операция производится с константой, записанной в поле команды. Разберём подробно каждую команду.
ADC
Команда сложения двух операндов, учитывает признак переноса C, т.е. если признак переноса установлен в 1, то к полученной сумме прибавится 1. Если он равен 0, то сумма не изменяется. Команда ADC устанавливает признаки C, Z, N, V.
AND
Команда, выполняющая логическую операцию "И". Для 8-разрядного числа это выглядит так (пример):
10101010 10010011 -------- 10000010
т.е. если в одноимённых разрядах стоят единицы, то и в полученном разряде будет 1. В других случаях там будет 0.
ASL
Команда сдвига байта. Если операнд не указан, т.е. команда однобайтовая, то сдвигается содержимое аккумулятора. То же правило сохраняется во всех командах сдвига. Команда ASL производит сдвиг влево через признак C, т.е. 8-й разряд записывается в признак переноса, а в 1 разряд записывается 0.
признак C - байт 0 - 10101101 после сдвига: 1 - 01011010
BCC
Команда условного перехода по нулевому значению признака C.
BCS
Команда условного перехода по единичному значению признака C.
BEQ
Команда условного перехода по единичному значению признака Z.
BIT
Команда аналогична команде AND, но в отличие от неё не изменяет содержимое аккумулятора, а лишь устанавливает признаки в соответствии с тем, что бы было, если бы AND выполнился.
BMI
Команда условного перехода по единичному значению признака N.
BNE
Команда условного перехода по нулевому значению признака Z
BPL
Команда условного перехода по нулевому значению признака N.
В поле команд условных переходов надо указать адрес перехода. На самом деле это не реальный адрес, а переход относительно регистра PC-программного счётчика. Цифра в поле команды перехода от 0 до 80 (не забывайте про шестнадцатеричную систему счисления) - это переход вперёд относительно программного счётчика, от 80 до FF назад. Причём при переходе вперёд, чтобы получить нужный операнд, записываемый в поле команды, надо из адреса "куда перейти" вычесть адрес "откуда перейти" и ещё 1. Адрес "откуда перейти" - имеется ввиду адрес ячейки, непосредственно следующей за операндом команды перехода. Назад переход осуществляется по-другому - из адреса "куда перейти" вычитается адрес "откуда перейти", потом прибавляется 1. Реальный код в поле команды образуется, если полученное значение вычесть из числа FF. Пример:
4000 - FF 02 BEQ $4004 4002 - A9 00 LDA #$00 4004 - 00 BRK
Здесь команда перехода BEQ осуществляет переход на адрес $4004 (знак "$" означает, что число шестнадцатеричное), т.е. цифра 02, указанная в поле команды, говорит о том, что надо пропустить 2 ячейки. Пример:
4000 - A9 00 LDA #$00 4002 - D0 FC BNE $4000 4004 - 00 BRK
Здесь команда перехода BNE осуществляет переход назад к ячейке $4000.
BRK
Останов выполнения программы. При этом на экран будет выведено содержимое всех регистров микропроцессора.
BVS
Команда условного перехода по единичному значению признака V.
BVC
Команда условного перехода па нулевому значению признака V.
CLC
Установка признака C в единичное значение.
CLD
Установка признака D в единичное значение. Вит D является признаком включения режима работы с десятичными числами. При этом перенос возникает, если число превышает 10 (десятичное).
CLI
Установка признака I в единицу. Бит I разрешает таймерное прерывание микропроцессора.
CLV
Установка признака V в единичное состояние.
CMP
Команда CMP позволяет сравнить два операнда. При выполнении этой команды из аккумулятора вычитается операнд (содержимое ячейки или непосредственный операнд) и устанавливаются все признаки. Содержимое регистров и ячеек не изменяется.
CPX
Выполняет такие же действия, что и команда CMP, только с регистром X.
CPY
То же, что и CMP, только с регистром Y.
DEC
Команда уменьшения содержимого ячейки на единицу. Воздействует на все признаки.
DEX
Уменьшает на единицу содержимое регистра X.
DEY
Уменьшает на единицу регистр Y.
EOR
Логическая операция "ИСКЛЮЧАЮЩЕЕ ИЛИ". Как меняется содержимое аккумулятора при такой команде показывает рисунок:
11100101 10101001 -------- 01001100
Другими словами, если в двух разрядах - единицы или ноли, то получается ноль.
INC
Увеличивает на единицу содержимое ячейки. Воздействует на все признаки.
INX
Команда увеличения содержимого регистра X на единицу. Воздействует на все признаки.
INY
Увеличивает на единицу содержимое регистра Y.
JMP
Команда, осуществляющая безусловный переход. Адрес перехода указывается в поле команды - сначала младший байт адреса затем старший, как указывалось ранее. Команда JMP (16) осуществляет косвенный переход по содержимому любых двух ячеек, не только первых 256. Адрес состоит из двух байтов.
JSR
Команда перехода на подпрограмму. При переходах надо учитывать, что вложенность подпрограмм не должна превышать 128 (из-за ограниченного размера стека 256). Каждый адрес возврата из подпрограммы записывается в стек двумя байтами. Для возврата есть однобайтовая команда, которая будет описана далее.
LDA
Команда загрузки аккумулятора содержимым ячейки, адресуемой в соответствии с операндом.
LDX
Загрузка регистра X.
LDY
Загрузка регистра Y.
LSR
Операция сдвига байта вправо циклически. Содержимое бита 0 пересылается в C.
признак C - байт 0 - 10010011 после сдвига 1 - 01001001