Файл: О.А.Калашников. Ассемблер Это Просто. Учимся программировать.pdf

ВУЗ: Не указан

Категория: Книга

Дисциплина: Программирование

Добавлен: 16.02.2019

Просмотров: 29194

Скачиваний: 1689

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
background image

 

Часть I. Знакомьтесь: ассемблер 

10 

Таблица 1.1 (окончание) 

Десятичное  
число 

Шестнадцатеричное 
 

число 

Десятичное  
число 

Шестнадцатеричное  
число 

159 

9F 

10 

160 

A0 

11 

161 

A1 

12 

162 

A2 

13 

... 

... 

14 

254 

FE 

15 

255 

FF 

16 

10 

256 

100 

17 

11 

257 

101 

... 

... 

... 

... 

 
Таким  образом,  если мы к какому-нибудь числу в шестнадцатеричной системе 

добавим справа ноль, то это число увеличится в 16 раз (пример 1.1). 

Пример 1.1 

1 х 16 = 10 
10 х 16 = 100 
100 х 16 = 1000 

и т. д. 

Вы  смогли  отличить  в  примере 1.1  шестнадцатеричные  числа  от  десятичных?  

А из этого ряда: 10, 12, 45, 64, 12, 8, 19? Это могут быть как шестнадцатеричные 
числа,  так  и  десятичные.  Для  того  чтобы  не  было  путаницы,  а  компьютер  и  про-
граммист смогли бы однозначно отличить одни числа от других, в ассемблере при-
нято  после  шестнадцатеричного  числа  ставить  символ  h  или  H  (от  англ. 
hexadecimal — шестнадцатеричное), который для краткости часто называют просто 
hex. После десятичного числа, как правило, ничего не ставят. Так как числа от 0 до 
9  в  обеих  системах  имеют  одинаковые  значения,  то  числа,  записанные  как  5  и 
5h, —  одно  и  то  же.  Таким образом,  корректная  запись  чисел  из  примера  1  будет 
следующей (примеры 1.2 и 1.3). 

Пример 1.2. Корректная форма записи чисел 

1 х 16 = 10h 
10h x 16 = 100h 
100h x 16 = 1000h 


background image

Глава 1. Первая программа 

11 

Пример 1.3. Другой вариант записи чисел 

1h x 10h = 10h 

10h x 10h = 100h 

100h x 10h = 1000h 

Для чего нужна шестнадцатеричная система и в каких случаях она применяет-

ся — мы рассмотрим в следующих главах. А в данный момент для нашего примера 
программы, который будет рассмотрен далее, нам необходимо знать о существова-
нии шестнадцатеричных чисел. 

Итак, настала пора подвести промежуточный итог. Шестнадцатеричная система 

счисления состоит из 10 цифр (от 0 до 9) и 6 букв латинского алфавита (A, B, C, D, 
E, F). Если к какому-нибудь числу в шестнадцатеричной системе добавить справа 
ноль, то это число увеличится в 16 раз. Очень важно уяснить принцип шестнадца-
теричной системы счисления, т. к. мы будем постоянно использовать ее при напи-
сании наших программ на ассемблере. 

Теперь  немного  о  том,  как  будут  строиться  примеры  на  ассемблере  в  данной 

книге.  Не  совсем  удобно  приводить  их  сплошным  текстом,  поэтому  сперва будет 
идти сам код программы с пронумерованными строками, а сразу же после него — 
объяснения и примечания. Примерно так, как показано в листинге 1.1. 

Листинг 1.1. Пример записи ассемблерных инструкций, применяемой в книге 

... 

(01)    mov ah,9 

(02)    mov al,8 

... 

(15)    mov dl,5Ah 

... 

Обратите  внимание,  что  номера  строк  ставятся  только  в  книге,  и  при  наборе 

программ в текстовом редакторе эти номера ставить НЕ нужно! Номера строк ста-
вятся  для  того,  чтобы  удобно  было  давать  объяснения  к  каждой  строке:  в  строке 
(01) мы делаем то-то, а в строке (15) — то-то. 

Несмотря  на  то,  что  на  компакт-диске,  прилагаемом  к  книге,  имеются  набран-

ные и готовые для ассемблирования программы, мы рекомендуем все-таки первое 
время набирать их самостоятельно. Это ускорит запоминание операторов, а также 
облегчит привыкание к самому языку. 

И еще момент. Строчные и ПРОПИСНЫЕ символы программой-ассемблером не 

различаются. Записи вида: 

mov ah,9 

и 

MOV AH,9 


background image

 

Часть I. Знакомьтесь: ассемблер 

12 

воспринимаются  одинаково.  Можно,  конечно,  заставить  ассемблер  различать  ре-
гистр, но мы пока этого делать не будем. Для удобства чтения программы лучше 
всего операторы вводить строчными буквами, а названия подпрограмм и меток на-
чинать с прописной. 

1.2. Наша первая программа 

Итак, переходим к нашей первой программе (\001\prog01.asm) (листинг 1.2). 

Листинг 1.2. Наша первая программа на ассемблере 

(01) CSEG segment 

(02) org 100h 

(03) 

(04) Begin: 

(05) 

(06)    mov ah,9 

(07)    mov dx,offset Message 

(08)    int 21h 

(09) 

(10)    int 20h 

(11) 

(12) Message db 'Hello, world!$' 

(13) CSEG ends 

(14) end Begin 

Еще  раз  обратим  внимание:  когда  вы  будете  перепечатывать  примеры  про-

грамм, то номера строк ставить не нужно! 

В скобках указывается имя файла из архива файлов-приложений (в данном слу-

чае — \001\prog01.asm, где 001 — каталог, prog01.asm — имя ассемблерного файла 
в DOS-формате). 

Прежде чем пытаться ассемблировать, прочтите данную главу до конца! 
Для  того  чтобы  объяснить  все  операторы  из  листинга 1.2, нам потребуется не-

сколько  глав.  Поэтому описание некоторых команд мы на данном этапе опустим. 
Просто  считайте,  что  так  должно  быть.  В  ближайшее  время  мы  рассмотрим  эти 
операторы  подробно.  Итак,  строки  с  номерами  (01),  (02)  и  (13)  вы  игнорируете. 
Строки  (03),  (05),  (09)  и  (11)  остаются  пустыми.  Это  делается  для  наглядности  
и  удобства  программиста  при  просмотре  и  анализе  кода.  Программа-ассемблер 
пустые строки опускает. 

Теперь  перейдем  к  рассмотрению  остальных  операторов.  Со  строки  (04)  начи-

нается  код  программы.  Это  метка,  указывающая  ассемблеру  на  начало  кода.  
В строке (14) стоят операторы 

end Begin

 (

Begin

 — начало; 

end

 — конец). Это ко-

нец  программы.  Вообще  вместо  слова 

Begin

  можно  было  бы  использовать  любое 


background image

Глава 1. Первая программа 

13 

другое. Например, 

Start

. В таком случае, нам пришлось бы и завершать программу 

оператором 

End Start

 (14). 

Строки (06)—(08) выводят на экран сообщение "Hello, world!". Здесь придется 

вкратце рассказать о регистрах процессора (более подробно эту тему мы рассмот-
рим в последующих главах). 

Регистр процессора — это специально отведенная память для хранения какого-

нибудь числа. Например, если мы хотим сложить два числа, то в математике запи-
шем так: 

A = 5 
B = 8 
C = A + B 
AB и C — это своего рода регистры (если говорить о компьютере), в которых мо-

гут храниться некоторые данные. А = 5 следует читать как: "присваиваем А число 5"

Для присвоения регистру какого-нибудь значения в ассемблере существует опе-

ратор 

mov

 (от англ. move — в данном случае "загрузить"). Строку (06) следует чи-

тать  так:  "загружаем  в  регистр 

ah

  число  9"  (проще  говоря,  присваиваем 

ah

  чис-

ло 9). Далее рассмотрим, зачем это необходимо. В строке (07) загружаем в регистр 

dx

  адрес  сообщения  для  вывода  (в  данном  примере  это  будет  строка 

"Hello, 

world!$"

). Затем, в строке (08) вызываем прерывание MS-DOS, которое и выведет 

нашу  строку  на  экран.  Прерывания  будут  подробно  рассматриваться  в  последую-
щих главах, мы же пока коснемся только самых элементарных вещей. 

1.3. Введение в прерывания 

Прерывание MS-DOS — это своего рода подпрограмма (часть MS-DOS), которая 

находится постоянно в памяти и может вызываться в любое время из любой про-
граммы. Рассмотрим вышесказанное на примере (листинг 1.3). 

Сразу  стоит  отметить,  что  в  ассемблере  после  точки  с  запятой  располагаются 

комментарии.  Комментарии  будут  опускаться  MASM/TASM  при  ассемблирова-
нии. Примеры комментариев: 

;это комментарий 
mov ah,9    ;это комментарий 

В комментарии программист вставляет замечания по программе, которые помо-

гают сориентироваться в коде. 

Листинг 1.3. Программа (алгоритм) сложения двух чисел 

НачалоПрограммы 
A=5          ;в переменную A заносим значение 5 
B=8          ;в переменную B значение 8 

ВызовПодпрограммы Addition 
;теперь С равно 13 
 
A=10        ;то же самое, только другие числа 


background image

 

Часть I. Знакомьтесь: ассемблер 

14 

B=25 

ВызовПодпрограммы Addition 
;теперь С равно 35 

 

КонецПрограммы 

;выходим из программы 

 

... 

Подпрограмма Addition 

C = A + B 

ВозвратИзПодпрограммы 

;возвращаемся в то место, откуда вызывали 

КонецПодпрограммы 

В  данном  примере  мы  дважды  вызвали  подпрограмму  (процедуру) 

Addition

которая  произвела  сложение  двух  чисел,  переданных  ей  в  переменных 

A

  и 

B

.  Ре-

зультат математического действия сохраняется в  переменной 

С

. Когда вызывается 

подпрограмма,  компьютер  запоминает,  с  какого  места  она  была  вызвана,  и  после 
того, как процедура отработала, возвращается в то место, откуда она вызывалась. 
Таким образом,  можно  вызывать  подпрограммы  неопределенное  количество  раз  
с любого участка основной программы. 

При  выполнении  строки  (08)  (см. листинг 1.2)  мы  вызываем  подпрограмму  

(в данном случае это называется прерыванием), которая выводит на экран строку. 
Для этого мы, собственно, и помещаем нужные значения в регистры, т. е. готовим 
для прерывания необходимые параметры. Всю работу (вывод строки, перемещение 
курсора)  берет на себя эта процедура. Строку (08) следует читать так:  "вызываем 
двадцать  первое  прерывание"
    (

int

  от  англ.  interrupt —  прерывание).  Обратите 

внимание, что после числа 21 стоит буква h. Это, как мы уже знаем, шестнадцате-
ричное число (33 в десятичной системе). Конечно, нам ничего не мешает заменить 
строку 

int  21h

  строкой 

int  33

.  Программа  будет  работать  корректно.  Но  в  ас-

семблере принято указывать номера прерываний в шестнадцатеричной системе, да 
и все отладчики работают с этой системой. 

В  строке  (10)  мы,  как  вы  уже  догадались,  вызываем  прерывание 

20h

.  Для  его 

вызова не нужно указывать какие-либо значения в регистрах. Оно выполняет толь-
ко  одну  задачу —  выход  из  программы  (выход  в  DOS).  В  результате  выполнения 
прерывания 

20h

 программа вернется туда, откуда ее запускали (загружали, вызыва-

ли). Например, в Norton Commander или DOS Navigator. Это что-то вроде оператора 

exit

 в некоторых языках высокого уровня. 

Строка  (12)  содержит  сообщение  для  вывода.  Первое  слово  (

message

 —  сооб-

щение) — название этого сообщения. Оно может быть любым (например, 

mess

 или 

string

 и пр.). Обратите внимание на строку (07), в которой мы загружаем в регистр 

dx

 адрес этого сообщения.