┌──────────────────────────────────────────────────────────────┐
│ ████▓▓▓▓▒▒▒▒░░░░ АССЕМБЛЕР ДЛЯ НАЧИНАЮЩИХ ░░░░▒▒▒▒▓▓▓▓█████ │
└──────────────────────────────────────────────────────────────┘
(C) THINKER
───────────
Привет всем тем, кто все еще пытается научиться создавать
свои программы на ассемблере. Давно уже в нашей газете не было
этой рубрики, в чем виноват я и наше всеми любимое министерство
образования, однако я обещаю сегодня рассчитаться за все. Гото-
вы? Поехали!
Как Вы уже наверное поняли, если не отказываться от Бейсика,
то работа Вашей программы будет подобна работе "Windows" на
286-м IBM процессоре. Для того, чтобы избавиться от уз Бейсика,
необходимо напрямую работать с экраном, для чего нужно знать его
строение, а строение у него непростое! Экран делится на 3 части,
вот их адреса: 1-я - 16384 (#4000), 2-я - 18432 (#4800), 3-я -
20480 (#5000). (Напомню, что символ "#" перед цифрой означает,
что число переведено в шестнадцатиричную систему, а символ "%"
означает, что число в двоичной) Так, как это адреса ОЗУ, мы мо-
жем посылать туда различные значения (помните что такое 'LD'?).
Как же представляются на мониторе байты, которые мы помещаем в
область экрана? Очень просто: как числа в двоичной системе, где
0 - выключеный пиксель (точка), а 1 - включеный. Например, не-
обходимо вывести точку в верхний левый угол экрана. Для начала
рассчитаем адрес экрана: это начало первой трети, значит адрес -
16384 (#4000).
Вот как будет выглядеть угол:
┌───────────── █-включеный пиксель ░-выключеный
│█░░░░░░░░░░
│░░░░░░░░░ Вот какой байт мы должны послать в экран:
│░░░░░░░ █░░░░░░ = %10000000 = 128
│░░░░ └──√──┘
8 пикселей
Значит мы должны послать число "128" по адресу 16384 (#4000),
после чего в верхнем левом углу будет стоять точка. Вот програм-
мка на ассемблере, которая отражает это:
LD A,128
LD (16384),A
RET
Теперь сделаем вот что:
┌────────────
│░█░█░█░█░░░ ░█░█░█░█ = %01010101 = 85
│░░░░░░░░░
│░░░░░░░
│░░░░
LD A,85
LD (16384),A
RET
Скажу, что обычно в ассемблере можно писать сразу двоичное
число, не переводя его в десятичное.
Теперь о том, как располагаются байты в каждой трети. Помни-
те, как грузились экраны с магнитофона? Сначала заполняется са-
мая верхняя строчка пикселей, потом начинает заполнятся строка
на 8 пикселей ниже и так 8 раз, после чего заполняется вторая
строка пикселей и все повторяется до того момента, когда будет
заполнена первая треть, потом все повториться для 2-й и 3-й. Для
ого, чтобы понять все это, наберите следующую программы на Бей-
сике, которая заполняет область экрана значением 255:
10 FOR F=16384 TO 22528
20 POKE F,255
30 NEXT F
Как Вы уже, возможно, успели заметить, прежде чем перейти от
первой строчки пикселей ко второй, вышепреведенная программа
заполняет 256 байт (то есть 8*32). Значит, для того, чтобы уз-
нать адрес начала 2-й строки пикселей, необходимо к 16384
(#4000) прибавить 256. Так же найдем адрес 3-й, 4-й...8-й. Вот,
как располагаются байты в экране:
Адреса в десятичной системе: В шестнадцатиричной системе:
┌─────┬─────┬─────┬─────┬───── ┌─────┬─────┬─────┬─────┬─────
│16384│16385│16386│16387│16388 │#4000│#4001│#4002│#4003│#4004
├─────┼─────┼─────┼─────┼───── ├─────┼─────┼─────┼─────┼─────
│16640│16641│16642│16643│ │#4100│#4101│#4102│#4103│
├─────┼─────┼─────┼─────┼─ ├─────┼─────┼─────┼─────┼─
│16896│16897│16898│16899│ │#4200│#4201│#4202│#4203│
├─────┼─────┼─────┼─────┼ ├─────┼─────┼─────┼─────┼
│17152│17153│17154│ │#4300│#4301│#4302│
├─────┼─────┼─────┼ ├─────┼─────┼─────┼
Заметили зависимость в правой таблице? Возьмем адрес #4001.
Это двухбайтовое (шестнадцатибитное) число, которое при занесе-
нии в рег.пару, например 'HL', представится следующим образом:
первый рег. будет содержать значение #40 (в нашем случае H=#40),
а второй-#01 (L=#01):
LD HL,#4001; H=#40, L=#01
Теперь понятно: для того, чтобы перейти к следующей строке
пикселей, необходимо к текущему адресу прибавить 256 байт или,
что тоже самое, увеличить старший байт на 1. Однако, это работа-
ет только в пределах одной строки знакомест, то есть, если Вы
захотите переместиться на символ ниже путем увеличения старшего
байта адреса, у Вас ничего не получится, и вот почему: допустим,
что мы хотим переместиться с нулевого символа, адрес начала ко-
торого-16384 (#4000), на символ ниже, для этого нужно сдвинуть
адрес экрана на 8 пиксельных строк вниз: 16384 + 8 * 256= 18432.
Вроде все верно, но посмотрите на получившееся число: ведь это
уже вторая треть экрана, значит мы переместились не нa 1 символ,
а на 8!
Tеперь атрибуты. Тут все гораздо проще: начало - (#5800),
строение построчное. То есть, если Вы заполните первые 32 знако-
места цветом, то переместитесь на
строку ниже. При засылании значения ┌───────────┐
в область атрибутов цвет соответст- │* ▓ ███ ░░░│ *-мерцание
вующего знакоместа меняется следую- └√─√──√───√─┘ ▓-яркость
щим образом: чернила берутся из 3-х 7 6 543 210 █-бумага
первых бит (биты 0..2), бумага из ░-чернила
из битов 3..5, яркость и мерцание
устанавливаются в соответствии с 6-м и 7-м битом. Вот трехбитные
значения чисел 0-7:
╔════════════════════════════════╗
║ 0-%000 2-%010 4-%100 6-%110 ║ Например, нам нужно в верх-
║ 1-%001 3-%011 5-%101 7-%111 ║ нем левом углу получить си-
╚════════════════════════════════╝ нюю бумагу, желтые чернила
(оригинально уже само по се-
бе), с выключенной яркостью и включеным мерцанием. Желтые черни-
ла - 6=%110, синяя бумага - 1=%001, мерцание и яркость - 1 и 0
=%10. Теперь составляем из этих кусочков один байт: %10 001 110
= %10001110=142. А вот программка:
LD A,142
LD (#5800),A
RET
На сегодня, наверное, достаточно. Оставляю Вас переваривать
полученную информацию. А в следующем номере, мы начнем подробно
знакомиться с наиболее важными командами языка ассемблер.
До новых встреч.