Сегодня у нас
первый номер рассылки, в которой мы
начнем изучение Ассемблера.
Убедительная просьба для вновь
подписавшихся: достаньте из архива предыдущий выпуск и
ознакомьтесь с ним. В нем
содержится информация, необходимая
для написания программ на
Ассемблере.
Итак, начнем!
Сегодня у нас:
Тема:
Шестнадцатеричная система
счисления.
Наша
первая программа.
Для написания
программ на Ассемблере, необходимо
разобраться с шестнадцатеричной
системой счисления. Ничего
сложного в ней нет. Мы используем в
жизни десятичную систему. Уверен,
что вы все ее знаете, поэтому я
постараюсь объяснить
шестнадцатеричную систему, проводя
аналогию с десятичной.
Итак, в десятичной
системе если мы к какому-нибудь
числу справа добавим нуль, то это
число увеличится в 10 раз. Например: 1
х 10 = 10; 10 х 10 = 100; 100 х 10 = 1000 и т.д. В
этой системе мы используем цифры от
0 до 9, т.е. десять разных цифр
(собственно, поэтому она и
называется десятичная).
В
шестнадцатеричной системе мы
используем, соответственно,
шестнадцать "цифр". Я специально
написал слово "цифр" в кавычках,
т.к. в ней используются не только
цифры. Да и в самом деле как так?
Объясняю: от 0 до 9 мы считаем так же,
как и в десятичной, а вот дальше
будет так: A, B, C, D, E, F. Число F, как не
трудно посчитать,
будет равно 15 в десятичной системе
(см. табл. 1).
Десятичное
число
Шестнадцатеричное
число
0
1
2
9
10
11
12
13
14
15
16
17
24
25
26
27
28
29
30
31
32
33
158
159
160
161
162
252
253
254
255
256
257
0
1
2
9
A
B
C
D
E
F
10
11
18
19
1A
1B
1C
1D
1E
1F
20
21
9E
9F
A0
A1
A2
FC
FD
FE
FF
100
101
Таблица 1. Десятичная и шестнадцатеричная системы.
Т.о., если мы к
какому-нибудь числу в
шестнадцатеричной системе добавим
справа нуль, то это число
увеличится в 16 раз.
Пример 1: 1 х
16 = 10; 10 х 16 = 100; 100 х 16 = 1000 и т.д.
Вы смогли
отличить в Примере 1
шестнадцатеричные числа от
десятичных? А из этого ряда: 10, 12, 45,
64, 12, 8, 19? Это могут быть как
шестнадцатеричные, так и
десятичные. Для того, чтобы не было
путаницы, и компьютер смог бы
однозначно отличить одни числа от
других, в Ассемблере принято после
шестнадцатеричного числа ставить
символ h или H (H это
сокращение от англ. hexadecimal (шестнадцатеричное).
Для краткости его иногда называют
просто Hex). А после десятичного
ничего не ставить. Т.к. числа от 0 до 9
в обоих системах имеют одинаковые
значения, то числа, записанные как 5
и 5h одно и тоже.
Т.о. Пример 1 (см.
выше) правильнее будет записать
так: 1 х 16 = 10h; 10h x 16 = 100h; 100h x 16 = 1000h.
Либо так: 1h x 10h = 10h; 10h x 10h = 100h; 100h x 10h =
1000h.
Для чего нужна
шестнадцатеричная система, мы
рассмотрим в последующих выпусках.
А в данный момент для нашего
примера программы, который будет
рассмотрен ниже, нам необходимо
знать о существовании
шестнадцатеричных чисел.
Итак, подведем
итог. Шестнадцатеричная система
счисления состоит из 10 цифр (от 0 до
9) и 6 букв латинского алфавита (A, B, C,
D, E, F). Если к какому-нибудь числу в
шестнадцатеричной системе добавим
справа нуль, то это число
увеличится в 16 раз. Очень важно
уяснить данную тему, так как мы
будем постоянно использовать ее
при написании программ.
Теперь немного о
том, как я буду строить примеры на
Ассемблере. Не совсем удобно
приводить их в HTML-формате, поэтому
сперва будет сам код программы с
пронумерованными строчками, а
сразу же после него объяснения и
примечания.
Примерно так:
строк
Код программы
(1)
(2)
(15)
mov ah,9
mov
al,8
mov dl,5Ah
Объяснения:
В строке (1) мы
делаем то-то, а в строке (15) то-то.
Огромная
просьба: НЕ копируйте
программы со страницы в буфер, а
затем не вставляйте их в Блокнот
(или еще куда-нибудь)!
Перепечатывайте их вручную в
текстовом редакторе. Если есть
принтер, то выделите программу,
распечатайте выделенный фрагмент,
а затем перебейте в редактор с
бумаги. Все примеры нужно
набирать самостоятельно! Это
ускорит запоминание операторов.
И еще. Строчные и
ПРОПИСНЫЕ буквы в Ассемблере не
различаются. Записи вида:
mov ah,9
И
MOV AH,9
Ассемблером
воспринимаются одинаково. Можно,
конечно, заставить Ассемблер
различать строчные и ПРОПИСНЫЕ
символы, но мы пока этого делать не
будем. Для удобства чтения
программы лучше всего операторы
печатать строчными буквами, а
названия подпрограмм и меток
начинать с прописной. Но это как
кому будет удобно.
Итак,
переходим к нашей первой программе:
(1) CSEG segment
(2) org 100h
(3)
(4) Begin:
(5)
(6) mov ah,9
(7) mov dx,offset Message
(8) int 21h
(9)
(10) int 20h
(11)
(12) Message db 'Hello,
world!$'
(13) CSEG ends
(14) end Begin
Для того, чтобы
объяснить все операторы данного
примера, нам потребуется несколько
выпусков. Поэтому описание
некоторых команд мы просто опустим
на данном этапе. Просто считайте,
что так должно быть. В самое
ближайшее время мы рассмотрим эти
операторы подробно. Итак, строки с
номерами (1), (2) и (13) вы просто
игнорируете.
Строки (3), (5), (9) и
(11) остаются пустыми. Это делается
для наглядности. Ассемблер их будет
просто опускать.
Теперь перейдем к
рассмотрению остальных операторов.
Со строки (4) начинается код
программы. Это метка, указывающая
Ассемблеру на начало кода. В строке
(14) стоят операторы end Begin (Begin англ. начало; end конец). Это конец
программы. Вообще вместо слова Begin
можно было бы
использовать что-нибудь другое.
Например, Start:. В
таком случае, нам пришлось бы и
завершать программу End Start (14).
Строки (6) (8)
выводят на экран сообщение Hello, world!.
Здесь придется вкратце рассказать
о регистрах процессора (более
подробно эту тему мы рассмотрим в
следующем выпуске).
Регистр
процессора это специально
отведенная память для хранения
какого-нибудь числа.
Например:
Если мы хотим
сложить два числа, то в математике
запишем так:
A=5
B=8
C=A+B.
A, B и C это своего рода
регистры (если говорить о
компьютере), в которых могут
хранится некоторые данные. А=5 можно
прочитать как: Присваиваем А
число 5.
Для присвоения
регистру какого-нибудь значения, в
Ассемблере существует оператор mov
(от англ. move загрузить). Строку (6)
следует читать так: Загружаем в
регистр AH число
9 (проще говоря, присваиваем
AH число 9).
Ниже рассмотрим зачем это надо.
В строке (7)
загружаем в регистр DX адрес сообщения для
вывода (в данном примере это будет
строка Hello, world!$).
Далее, в строке (8),
вызываем прерывание MS-DOS, которое и выведет
нашу строку на экран.
Прерывания
будут подробно рассматриваться в
последующих выпусках. Здесь я скажу
несколько слов.
Прерывание MS-DOS это своего рода
подпрограмма (часть MS-DOS), которая находится
постоянно в памяти и может
вызываться в любое время из любой
программы.
Рассмотрим
вышесказанное на примере (мелким шрифтом
выделим примечания):
Программа
сложения двух чисел
НачалоПрограммы
A=5 в переменную A заносим
значение 5
B=8 в переменную B значение
8
ВызовПодпрограммы
Сложение
теперь С
равно 13
A=10 тоже самое, только
другие числа
B=25
ВызовПодпрограммы
Сложение
теперь С
равно 35
КонецПрограммы
Подпрограмма
Сложение
C=A+B
ВозвратИзПодпрограммы возвращаемся
в то место, откуда вызывали
КонецПодпрограммы
В данном примере
мы дважды вызвали подпрограмму Сложение,
которая сложила два числа,
переданные ей в переменных A и B.
Результат помещается в переменную
С. Когда вызывается подпрограмма,
компьютер запоминает с какого
места она была вызвана, а затем,
когда закончила работу
подпрограмма, компьютер
возвращается в то место, откуда она
вызывалась. Т.о. можно вызывать
подпрограммы неопределенное
количество раз с любого места.
При выполнении
строки (8) программы на Ассемблере
мы вызываем подпрограмму (в данном
случае это называется прерывание),
которая выводит на экран строку.
Для этого мы, собственно, и помещаем
необходимые значения в регистры.
Всю необходимую работу (вывод
строки, перемещение курсора) берет
на себя подпрограмма. Эту строку
можно прочитать так: вызываем
двадцать первое прерывание (int от англ. interrupt прерывание). Обратите
внимание, что после числа 21 стоит
буква h. Это, как
мы уже знаем, шестнадцатеричное
число (33 в десятичной системе).
Конечно, нам ничего не мешает
заменить строку int 21h на int 33. Программа будет
работать корректно. Просто в
Ассемблере принято указывать номер
прерывания в шестнадцатеричной
системе.
В строке (10) мы, как
вы уже догадались, вызываем
прерывание 20h.
Для вызова данного прерывания не
нужно указывать какие-либо
значения в регистрах. Оно выполняет
только одну задачу: выход из
программы (выход в DOS). В результате
выполнения прерывания 20h, программа
вернется туда, откуда ее запускали
(загружали, вызывали). Например, в Norton
Commander или DOS
Navigator.
Строка (12)
содержит сообщение для вывода.
Первое слово (message сообщение) название
сообщения. Оно может быть любым
(например, mess или
string и пр.). Обратите внимание на
строку (7), в которой мы загружаем в
регистр DX адрес
нашего сообщения.
Можно создать еще
одну строку, которую назовем Mess2. Затем, начиная со
строки (9) вставим следующие
команды:
(9) mov ah,9
(10) mov dx,offset Mess2
(11) int 21h
(12) int 20h
(13) Message db 'Hello, world!$'
(14) Mess2 db 'Это Я!$'
(15) CSEG ends
(16) end Begin
и ассемблировать
нашу программу заново. Надеюсь, что вы
догадались, что произойдет
Обратите внимание
на последний символ в строках Message
и Mess2 - $. Он указывает на конец
строки. Если мы его уберем, то 21h прерывание продолжит
вывод до тех пор, пока не встретится
где-нибудь в памяти символ $. На экране мы увидим мусор .
Если у вас есть отладчик, то можно
посмотреть как будет работать наша
программа.
Целю настоящего выпуска не было
разобраться подробно с каждым
оператором. Это невозможно, т.к. у
вас еще недостаточно знаний. Я
полагаю, что уже через 3-4 выпуска вы
поймете принцип и структуру
программы на Ассемблере. Может
быть, вам показался язык Ассемблера
чрезвычайно сложным, но это,
поверьте, с первого взгляда.
На сегодня все. В следующем
выпуске мы подробно рассмотрим
регистры процессора и напишем еще
одну простенькую программку.