Из журнала ZX Format #1, Санкт-Петербург, 11.1995 Ассемблер В Картинках для "чайников" и не только. Автор:Михаил Спицын. ________________________________ Мы начинаем цикл статей по ассемблеру для начинающих, с целью побудить людей к изучению данного языка. В этих статьях мы раскажем о строении компьютера, графике, звуке (48 и 128) и, естественно, о самом ассемблере. Итак... 1.ПРОЦЕССОР КОМПЬЮТЕРА Как человек, так и любой ком- пьютер имеет мозг; этим мозгом у компьютера является процессор. А что же за "мозг" у нашего Speccy? "Мозг" Spectrum'а - это про- цессор Z80 фирмы ZILOG. Процес- сор Z80 является псевдошестнад- цатиразрядным. Как это понять? Дело в том, что каждый про- цессор может понимать числа определенной разрядности. К при- меру восьмиразрядное число запи- сывается как комбинация из восьми двоичных нулей и единиц и может обозначать любое целое число от 0 до 255. Каждый разряд такого числа, это степень двойки, например двоичное число 01100110 соот- ветствует десятичному 102, а перевести из десятичной в двоич- ную систему можно так: 2^7*0+2^6*1+2^5*1+2^4*0+2^3*0+ 2^2*1+2^1*1+2^0*0=102 Продолжим. Z80 имеет двадцать восьмиразрядных регистров (ре- гистр это ячейка внутри процес- сора, куда можно записывать чис- ла) и все регистры объединяются в пары, каждая из которых так и называется: "регистровая пара". Вот мы и добрались до ответа на наш вопрос, - 8+8=16, следо- вательно регистровая пара дает шестнадцатиразрядное число. Теперь о том, почему Speccy не просто шестнадцатиразрядный, а "псевдо" такой. Итак регистры нам нужны для того, чтобы выполнять над ними арифметические операции, а имен- но сложение и вычетание. К сожа- лению наш маленький Speccy не умеет делить и умножать, а уж ни о каких более "страшных" дейст- виях и говорить не приходится. Так вот, процесор может скла- дывать/вычитать как регистры, так и регистровые пары, т.е. вы- полнять арифметические операции над восьми и шестнадцатиразряд- ными числами, а так как регистры имеют лишь восемь разрядов (это вам не IBM), то и процессор "псевдошестнадцатиразрядный". Вот таблица всех регистров с их назначением: +-------+----------------------+ |Регистр|Основное назначение | +-------+----------------------+ | A | 8-ый аккумулятор | | F | Флаговый регистр | | B | 8-ый счетчик | | BC | 16-ый счетчик | | DE | Регистр приемник | | HL | 16-ый аккумулятор | | IX | Индексный регистр | | IY | Системный индекс | | I | Вектор прерывания | | R | Регистр регенерации | | SP | Вершина стека | | PC | Счетчик команд | +-------+----------------------+ | Примечание: | | 8-ый - восьмиразрядный | +------------------------------+ 2.ПРОСТЕЙШИЕ КОМАНДЫ Теперь рассмотрим простейшие операции ассемблера, используя в качестве примера бейсик, с кото- рым, я надеюсь, Вы знакомы. Первое, что нужно сделать для изучения ассемблера - это выб- рать себе "оболочку-ассемблер", в которой Вы будете работать. Могу Вам посоветовать TASM128 если у Вас ZX128 или, для ZX48, ZEUS ASSEMBLER. Итак приступим : BASIC ASSEMBLER 10 LET A=1 LD A,1 20 STOP RET Команда "LET" эквивалентна команде "LD" , если Вы наберете и запустите ее, то в регистр "A" будет занесена единица. По ко- манде "RET" произойдет выход в вызывающую программу (если прог- рамма была запущена из BASIC'а, то по команде "RET" она вернет управление BASIC'у). Во все регистры, за исключе- нием "F" и "PC", можно заносить числа, например: LD A,1 ; 1-->A LD B,15 ; 15-->B LD HL,16384 ; 16384-->HL LD IX,50000 ; 50000-->IX Но обычно программисту не хватает регистров, тогда прихо- дится использовать память компь- ютера, например: BASIC ASSEMBLER LET A=PEEK 23556 LD A,(23556) После выполнения этой команды в "A" будет находиться число, записаное в указанной ячейке па- мяти, а учитывая то, что в этой ячейке BASIC хранит код послед- ней нажатой клавиши, данная ко- манда не лишена практического смысла. Также используются и обратные команды : BASIC ASSEMBLER POKE 23607,A LD (23607),A Но часто приходиться записы- вать/считывать значение ячейки, адрес которой рассчитывается или берется из таблицы. В таком случае используются следующие команды: ЗАПИСЬ ЧТЕНИЕ LD (BC),A LD A,(BC) LD (DE),A LD A,(DE) LD (HL),0 LD E,(HL) Примечание: Хочу заметить, что не сушествует команды пря- мой записи числа в ячейку па- мяти, как и записи из ячейки в ячейку. А теперь я хочу привести про- грамму, которая печатает любое сообщение (она аналогична опе- ратору "PRINT"). В программе используется ко- манда "CALL", для вызова проце- дуры ПЗУ, эту команду можно сравнить с командой BASIC'а "GO SUB", например: BASIC ASSEMBLER 10 GO SUB 999 CALL M1 .... .... 999 LET A=1 M1 LD A,1 1000 RETURN RET Здесь "М1"-это метка, вместо которой при ассемблировании программы будет поставлен соот- ветствующий адрес. ПРИМЕР ПРОГРАММЫ После точки с запятой в ас- семблере, также как после REM в бейсике пишутся комментарии. ;Программа печати текстовых ;сообщений. -= PRINT TEXT =- ORG 30000 ENT START LD A,1 ;Открываем 1 CALL #1601;канал для ;печати. LD DE,TEXT;Адрес текста LD BC,LEN ;Длина текста CALL #203C;Печать текста RET TEXT DEFB 22 ;Код "AT" DEFB Y,X ;Позиция печати DEFM "HELLO, EVEREBODY!" LEN EQU 20 ;LEN=20 Y EQU 10 ;Y=10 X EQU 5 ;X=5 Эта программа аналогична строке BASIC'a: 10 PRINT AT 10,5;"HELLO, EVEREBODY!" В следующем номере я расскажу об арифметических командах и ко- мандах сравнения, и приведу при- мер маленькой игры. До встречи ! ________________________________ Из журнала ZX Format #2, Санкт-Петербург, 12.1995 Ассемблер для чайников. (#2) (C) Михаил Спицын 1995 ________________________________ Флаги Регистр "F" процессора назы- вается флаговым. Что это такое ? Флаг - это переменная, кото- рая может иметь два состояния, - установлено (равно единице) и сброшено (равно нулю). Поэтому регистр "F" можно рассматривать как набор восьми флаговых битов. Мы можем использовать только четыре из них: флаг нуля, флаг переноса, флаг знака и флаг чет- ности-переполнения. Арифметические операции. Арифметика - наука весьма и весьма полезная, мы постоянно что-нибудь считаем: складываем, отнимаем, делим, умножаем. О том, как сделать это на ассемб- лере, мы сейчас и поговорим. Начнем мы с самого простого, прибавим единицу к чему-нибудь, например к регистру "А": ******************************** LD A,NUBER INC A RET ******************************** Как видите, это очень просто, для этого существует команда "INC" - инкремент (увеличение на единицу), после нее идет опе- ранд, т.е. какой-нибудь регистр или регистровая пара: ******************************** INC A INC HL INC H INC DE INC E INC IY INC E INC (HL) INC (IX+N) INC (IY+N) ******************************** Если Вам нужно увеличить на единицу какую-либо ячейку памя- ти, то следует поступить так: ******************************** LD HL,ADDRES LD IX,ADDRES INC (HL) INC (IX+0) RET RET ******************************** Первый вариант работает бы- стрее и удобен, если работа идет с одной ячейкой памяти, но если вы работаете в таблице, то это не экономично и некрасиво. Срав- ните: нам нужно увеличить на единицу первый, пятый и десятый байты в таблице: ******************************** LD HL,TABL+1 LD IX,TABL INC (HL) INC (IX+1) LD HL,TABL+5 INC (IX+5) INC (HL) INC (IX+10) LD HL,TABL+10 RET INC (HL) RET ******************************** Все, что сказано выше о уве- личении на единицу, справедливо и для декремента, т.е. для уменьшения на единицу: ******************************** DEC A DEC HL DEC L DEC IX DEC H DEC DE DEC E DEC BC DEC D DEC IY DEC C DEC IX DEC B DEC (HL) DEC (IX+N) DEC (IX+N) ******************************** А теперь предположим, что нам надо увеличить регистр "A" не на единицу, а скажем, на десять: ******************************** LD A,NUMBER ADD A,10 RET ******************************** Складывать можно регистр "A" с числом и другими регистрами и с ячейкой памяти, адресованной регистровыми парами "HL", "IX" и "IY". Так же можно складывать регистровые пары с "HL", "IX" и "IY". ******************************** ADD A,N ADD A,(HL) ADD A,A ADD A,(IX+N) ADD A,B ADD A,(IY+N) ADD A,C ADD HL,HL ADD A,D ADD HL,BC ADD A,E ADD HL,DE ADD A,H ADD HL,SP ADD IX,IX ADD IX,BC ADD IX,DE ADD IX,SP ******************************** Как видите, набор команд дос- таточно велик. При выполнении этой команды может возникнуть ошибка: ******************************** LD A,45 LD B,230 ADD A,B RET ******************************** Сумма "А" и "В" превысило 255 и поэтому в "А" окажется не 275, а 20 (регистр "А" не резиновый); чтобы мы знали, что произошло переполнение, процессор устанав- ливает флаг переноса в единицу. Остается только проверить его. Подобно тому, как у "INC" есть "DEC", у "АDD" тоже есть "парочка", это "SUB", и у нее имеются свои особенности. Коман- да "SUB" работает только с ре- гистром "А", поэтому при написа- нии мнемоники этой команды "А" опускается: ******************************** SUB N SUB C SUB A SUB H SUB B SUB D SUB E SUB (HL) SUB (IX+N) SUB (IY+N) ******************************** Команда влияет на флаг пере- носа так же, как и "АDD". Кроме пары команд "ADD" и "SUB" существуют еще одна пара. Команды "ADC" и "SBC" работают с учетом флага переноса, т.е. при сложении или вычитании к результату добавляется (отнима- ется) значение флага переноса. Для установки флага переноса есть две спецкоманды - это "SCF" и "CCF". "SCF" - установить флаг переноса в единицу. "CCF" - ус- тановить флаг переноса в ноль. ******************************** ADC A,N SBC A,N ADC A,A SBC A,A ADC A,H SBC A,H ADC A,L SBC A,L ADC A,D SBC A,D ADC A,E SBC A,E ADC A,B SBC A,B ADC A,C SBC A,C ADC A,(HL) SBC A,(HL) ADC A,(IX+N) SBC A,(IX+N) ADC A,(IY+N) SBC A,)IY+N) ADC HL,HL SBC HL,HL ADC HL,BC SBC HL,BC ADC HL,DE SBC HL,DE ADC HL,SP SBC HL,SP ******************************** А теперь примеры работы ко- манд "ADC" и "SBC" : ******************************** LD A,10 LD A,10 LD B,5 LD B,5 CCF CCF SBC A,B ADC A,B RET RET A=5 B=5 A=15 B=5 ******************************** Вместо двух команд "CCF" и "SBC A,B" можно поставить прос- то "SUB B", результат будет тот же. ******************************** LD A,10 LD A,10 LD B,5 LD B,5 SCF SCF SBC A,B ADC A,B RET RET A=4 B=5 A=16 B=5 ******************************** Как видно из результатов, флаг переноса значительно влияет на результат операции. При вычи- тании он отнимается от результа- та, а при сложении прибавляется к результату. По операциям сложения и вычи- тания рассказано почти все, те- перь мы поговорим о делении и умножении. К сожалению SPECCY не имеет команд деления и умноже- ния, но эти команды можно соста- вить из нескольких других. Нап- ример, нам нужно перемножить со- держимое двух регистров - "А" и "C" : ******************************** LD A,10 LD C,5 LD B,A XOR A LOOP ADD A,C DJNZ LOOP RET ******************************** В примере встречаются две но- вые команды - "XOR A" и "DJNZ LOOP". "XOR A" обнуляет регистр "А", а команда "DJNZ LOOP" пов- торяет все команды, с команды, помеченной меткой (например "LOOP"), до команды "DJNZ" (пос- ле нее должна стоять та же мет- ка, что и в начале цикла); число повторений задается в регистре "В". Используя то, что умножение M на N - это сложение числа М само с собой N раз, Вы можете разобратся с примером, приведен- ным выше. Можно использовать это свой- ство и для деления. Попробуй- те сделать это сами. В следующий раз поговорим о командах сравнения и работы с битами. ________________________________