мета-данные страницы
  •  
Загрузка не удалась. Возможно, проблемы с правами доступа?

Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

Предыдущая версия справа и слеваПредыдущая версия
Следующая версия
Предыдущая версия
asm:lesson3 [29/09/2010 19:15] arabusovasm:lesson3 [07/02/2012 18:38] (текущий) arabusov
Строка 1: Строка 1:
-======Урок 3 ====== +======Начало работы с ассемблером ====== 
-Первым делом проверим конфигурацию dosbox. Зайдём в домашний каталог, затем в папку asm. Проверим наличие в ней файлов debug.exe, папок tasm и tc, в которых содержится turbo assembler и turbo c. Если чего-то нет, то переходите к началу страницы, скачивайте необходимые файлы и распаковывайте их в нужные каталоги. Затем запустим и выключим dosbox, затем в терминале введём команду gedit ~/.dosbox/dosbox-0.73.conf В конце файла должны быть следующие строки:+Первым делом проверим конфигурацию dosbox. Зайдём в домашний каталог, затем в папку asm. Проверим наличие в ней файлов debug.exe, папок tasm и tc, в которых содержится turbo assembler и turbo c. Если чего-то нет, то переходите к началу [[http://wiki.nsunc.com/asm]], скачивайте необходимые файлы и распаковывайте их в нужные каталоги. Затем запустим и выключим dosbox (Приложения -> Игры -> Эмулятор DosBox), затем в терминале (Приложения -> Стандартные -> Терминал) введём команду gedit ~/.dosbox/dosbox-0.74.conf В конце файла должны быть следующие строки:
   * mount c ~/asm   * mount c ~/asm
   * path=z:\;c:\;c:\tasm;c:\tc   * path=z:\;c:\;c:\tasm;c:\tc
   * c:   * c:
 +  * keyb ru
 Если что-то не так, то доредактируем файл. После этого dosbox будет сконфигурирован. Если что-то не так, то доредактируем файл. После этого dosbox будет сконфигурирован.
 +
 ===== Сегментация программы ===== ===== Сегментация программы =====
 По знаменитой формуле Никлауса Вирта (создателя языка Pascal, [[http://ru.wikipedia.org/wiki/%D0%92%D0%B8%D1%80%D1%82,_%D0%9D%D0%B8%D0%BA%D0%BB%D0%B0%D1%83%D1%81]]) программа = алгоритм + данные. Этот принцип в программировании реализуется повсеместно. Процессор 8086 на аппаратном уровне производит разделение программы на код и данные. Для этого вводится понятие сегмента: это участок памяти объёмом в 64 KB, в котором процессор подразумевает нахождение либо данных, либо кода. Адрес начала сегмента хранят сегментные (системные) регистры: cs, ds, ss, es. При выполнении программы процессор обращается по адресу cs:ip и выполняет команду, которая содержится в этой ячейке памяти. Регистр ds указывает на начало сегмента данных, многие команды процессора, которые связаны с работой с памятью, вычисляют физический адрес данных, начиная от ds. Однако мы рассмотрели не все системные регистры: осталось ещё два. es - это дополнительный сегмент данных, он функционирует практически так же, как и ds. А вот ss - сегмнт стека (stack segment), он по-сложнее... По знаменитой формуле Никлауса Вирта (создателя языка Pascal, [[http://ru.wikipedia.org/wiki/%D0%92%D0%B8%D1%80%D1%82,_%D0%9D%D0%B8%D0%BA%D0%BB%D0%B0%D1%83%D1%81]]) программа = алгоритм + данные. Этот принцип в программировании реализуется повсеместно. Процессор 8086 на аппаратном уровне производит разделение программы на код и данные. Для этого вводится понятие сегмента: это участок памяти объёмом в 64 KB, в котором процессор подразумевает нахождение либо данных, либо кода. Адрес начала сегмента хранят сегментные (системные) регистры: cs, ds, ss, es. При выполнении программы процессор обращается по адресу cs:ip и выполняет команду, которая содержится в этой ячейке памяти. Регистр ds указывает на начало сегмента данных, многие команды процессора, которые связаны с работой с памятью, вычисляют физический адрес данных, начиная от ds. Однако мы рассмотрели не все системные регистры: осталось ещё два. es - это дополнительный сегмент данных, он функционирует практически так же, как и ds. А вот ss - сегмнт стека (stack segment), он по-сложнее...
Строка 19: Строка 21:
 ===== Написание программ на ассемблере ===== ===== Написание программ на ассемблере =====
 Первое, с чем мы столкнёмся: для ассемблера нет оболочки. Исторически сложилось, что программу вводят в текстовом редакторе, а затем запускают сам ассемблер и получают исполняемый файл - файл, который можно (а может и нельзя) запустить на компьютере. Итак, чтобы написать программу мы должны создать файл в папке asm, отредактировать его с помощью gedit (особо одарённые могут использовать vi или emacs) и скомпилировать его в dosbox. Компиляция проходит в два этапа. Первый: собственно ассемблирование (команда tasm имя_файла). В результате получится файл имя_файла.obj. Этот файл запустить в dosbox просто так не удастся. Вы можете подключить к этому файлу другие с аналогичным расширением. Это действие называется линковкой. В нашем случае почти всегда мы будем линковать только один файл командой tlink имя_файла.obj. Если программа была написана без ошибок, то на выходе мы получим имя_файла.exe или имя_файла.com. Первое, с чем мы столкнёмся: для ассемблера нет оболочки. Исторически сложилось, что программу вводят в текстовом редакторе, а затем запускают сам ассемблер и получают исполняемый файл - файл, который можно (а может и нельзя) запустить на компьютере. Итак, чтобы написать программу мы должны создать файл в папке asm, отредактировать его с помощью gedit (особо одарённые могут использовать vi или emacs) и скомпилировать его в dosbox. Компиляция проходит в два этапа. Первый: собственно ассемблирование (команда tasm имя_файла). В результате получится файл имя_файла.obj. Этот файл запустить в dosbox просто так не удастся. Вы можете подключить к этому файлу другие с аналогичным расширением. Это действие называется линковкой. В нашем случае почти всегда мы будем линковать только один файл командой tlink имя_файла.obj. Если программа была написана без ошибок, то на выходе мы получим имя_файла.exe или имя_файла.com.
 +== ВНИМАНИЕ!!! ==
 +Имя файла в MS-DOS и в DOSBox не может превышать восьми символов!!!
 +
 ===== Программы типа *.com ===== ===== Программы типа *.com =====
-Главная особенность com-программ: cs, ds, es и ss указывают на один и тот же сегмент, тем самым смешивая всё в одну кучу! При компиляции +Главная особенность com-программ: cs, ds, es и ss указывают на один и тот же сегмент, тем самым смешивая всё в одну кучу! При компиляции tasm тщательно следит за тем, чтобы вы не меняли содержимого системных регистров. Так как на всю программу выделен всего один сегмент, то максимальный размер программы: 64 КБайт. Обычно этот тип файлов используется в качестве драйверов для MS-DOS. 
 +==== Программы типа *.exe ===== 
 +В exe-программе под код данные и стек может отводится несколько сегментов. Компилятор никак не отслеживает изменение системных регистров, в этом варианте вы можете делать с компьютером всё, что хотите (или можете). 
 +===== Программа на ассемблере ===== 
 +Для того, чтобы приступить к работе, мы должны познакомится с синтаксисом языка ассемблер. 
 +==== Команды ==== 
 +      [метка:] опкод [операнды] [;комментарий] 
 +где опкод (код операции) — непосредственно мнемоника инструкции процессору. К ней могут быть добавлены префиксы (повторения, изменения типа адресации и пр.). 
 +Метка (если имеется),  команда  и операнд  (если имеется) 
 +pазделяются по  крайней  мере  одним  пробелом  или символом 
 +табуляции.  Максимальная длина строки - 132 символа, однако, 
 +большинство предпочитают работать со строками в  80 символов 
 +(соответственно ширине экрана). Примеры кодирования: 
 + 
 +     Метка     Команда   Операнд 
 +     COUNT     DB        1    ;Имя, команда, один операнд 
 +               MOV       AX,0 ;Команда, два операнда 
 + 
 +=== Метки === 
 + 
 +Метка в языке ассемблера может содержать  следующие симво 
 +лы: 
 +          Буквы:         от A до Z и от a до z 
 +          Цифры:         от 0 до 9 
 +          Спецсимволы:   знак вопроса (?) 
 +                         точка (.) (только первый символ) 
 +                         знак "коммерческое эт" (@) 
 +                         подчеркивание (-) 
 +                         доллар ($) 
 + 
 +Первым символом  в метке должна  быть  буква или спецсимвол. 
 +Ассемблер  не  делает различия между заглавными  и строчными 
 +буквами.  Максимальная  длина  метки  -  31  символ. Примеры 
 +меток:   COUNT,  PAGE25,  $E10.  Рекомендуется  использовать 
 +описательные  и смысловые метки.  Имена регистров, например, 
 +AX,  DI  или AL  являются  зарезервированными и используются 
 +только для указания  соответствующих регистров.  Например, в 
 +команде 
 +                    ADD  AX,BX 
 + 
 +ассемблер "знает",  что  AX  и  BX  относится  к  регистрам. 
 +Однако, в команде 
 + 
 +                    MOV  REGSAVE,AX 
 + 
 +ассемблер воспримет имя REGSAVE только  в  том  случае, если 
 +оно  будет определено  в сегменте  данных.   В  приложении 3 
 +приведен cписок всех зарезервированных слов ассемблера. 
 + 
 +=== Команда === 
 + 
 +Мнемоническая команда указывает ассемблеру какое действие 
 +должен выполнить данный оператор.  В сегменте данных команда 
 +(или   директива)   определяет  поле,  рабочую  oбласть  или 
 +константу.  В  сегменте  кода  команда  определяет действие, 
 +например, пересылка (MOV) или сложение (ADD). 
 + 
 +=== Операнд === 
 + 
 +Если команда специфирует выполняемое действие, то операнд 
 +определяет  а)  начальное значение  данных  или б) элементы, 
 +над которыми  выполняется действие  по  команде. В следующем 
 +примере  байт COUNTER  определен в сегменте  данных и  имеет 
 +нулевое значение: 
 + 
 +          Метка     Команда   Операнд 
 +          COUNTER   DB      ;Определить байт (DB) 
 +                              ;  с нулевым значением 
 + 
 +Команда может иметь  один  или  два операнда,  или вообще 
 +быть без операндов. Рассмотрим следующие три примера: 
 + 
 +                    Команда Операнд     Комментарий 
 +     Нет операндов    RET               ;Вернуться 
 +     Один операнд     INC     CX        ;Увеличить CX 
 +     Два операнда     ADD     AX,12     ;Прибавить 12 к AX 
 + 
 +Метка, команда и операнд не обязательно должны начинаться 
 +с какой-либо определенной позиции в  строке. Однако, рекомен 
 +дуется записывать  их в колонку  для большей yдобочитаемости 
 +программы.  Для этого, например, редактор DOS EDLIN обеспечи 
 +вает табуляцию чепез каждые восемь позиций. 
 +==== Комментарии ==== 
 +Использование  комментариев  в   программе   улучшает  ее 
 +ясность,   oсобенно  там,   где  назначение   набора  команд 
 +непонятно.  Комментаpий  всегда  начинаются  на любой строке 
 +исходного модуля с символа  точка с запятой (;)  и ассемблер 
 +полагает в этом случае,  что все символы, находящиеся справа 
 +от  ;  являются  комментарием.  Комментарий  может содержать 
 +любые печатные символы, включая пробел. 
 +Комментарий может занимать  всю строку  или  следовать за 
 +командой на той же строке, как это показано в двух следующих 
 +примерах: 
 + 
 +   1.     ;Эта строка полностью является комментарием 
 +   2.     ADD AX,BX  ;Комментарий на одной строке с командой 
 + 
 +==== Директивы ==== 
 + 
 +Программа на языке ассемблера может содержать директивы: инструкции, не переводящиеся непосредственно в машинные команды, а управляющие работой компилятора. Набор и синтаксис их значительно разнятся и зависят не от аппаратной платформы, а от используемого транслятора (порождая диалекты языков в пределах одного семейства архитектур). В качестве «джентельменского набора» директив можно выделить следующие: 
 + 
 +    * определение данных (констант и переменных), 
 +    * управление организацией программы в памяти и параметрами выходного файла, 
 +    * задание режима работы компилятора, 
 +    * всевозможные абстракции (то есть элементы языков высокого уровня) — от оформления процедур и функций (для упрощения реализации парадигмы процедурного программирования) до условных конструкций и циклов (для парадигмы структурного программирования), 
 +    * макросы. 
 +Директивы управления листингом: PAGE и TITLE 
 + 
 + 
 +Ассемблер  содержит  ряд  директив,  управляющих форматом 
 +печати (или  листинга).  Обе директивы  PAGE  и  TITLE можно 
 +использовать в любой программе. 
 + 
 +=== Директива PAGE === 
 +В начале программы можно указать количест 
 +во строк,  распечатываемых на одной странице, и максимальное 
 +количество  символов на одной строке.  Для  этой цели cлужит 
 +директива  PAGE.  Следующей  директивой  устанавливается  60 
 +строк на страницу и 132 символа в строке: 
 + 
 +                         PAGE 60,132 
 + 
 +Количество строк на странице межет быть в пределах  от 10 до 
 +255,  а  символов в  строке -  от 60  до 132. По умолчанию в 
 +ассемблере установлено PAGE 66,80. 
 +Предположим,  что счетчик строк установлен на 60.  В этом 
 +случае  ассемблер,  распечатав  60  строк,  выполняет прогон 
 +листа  на  начало  следующей  страницы  и  увеличивает номер 
 +страницы  на  eдиницу.  Кроме того можно заставить ассемблер 
 +сделать прогон листа на конкретной строке, например, в конце 
 +сегмента.  Для этого необходимо записать  директиву PAGE без 
 +операндов.  Ассемблер автоматически делает  прогон листа при 
 +обработке диpективы PAGE. 
 + 
 +=== Директива TITLE === 
 +Для того,  чтобы вверху каждой страницы 
 +листинга печатался заголовок (титул) программы, используется 
 +диpектива TITLE в следующем формате: 
 + 
 +                         TITLE   текст 
 + 
 +Рекомендуется в качестве текста использовать  имя програм 
 +мы, под которым она находится в каталоге на диске. Например, 
 +если программа называется ASMSORT, то можно использовать это 
 +имя и описательный комментарий общей длиной до 60 символов: 
 + 
 +     TITLE ASMSORT - Ассемблерная программа сортировки имен 
 + 
 +В ассемблере также имеется директива подзаголовка SUBTTL, 
 +которая может оказаться полезной для очень больших программ, 
 +содержащих много подпрограмм. 
 + 
 +=== Директива SEGMENT === 
 + 
 +Любые ассемблерные  программы  содержат  по  крайней мере 
 +один  сегмент  -   сегмент  кода.   В  некоторых  программах 
 +используется  сегмент для стековой  памяти  и сегмент данных 
 +для определения данных.  Асcемблерная директива для описания 
 +сегмента SEGMENT имеет следующий формат: 
 + 
 +               Имя       Директива      Операнд 
 +               имя       SEGMENT        [параметры] 
 +                         . 
 +                         . 
 +                         . 
 +               имя       ENDS 
 + 
 +Имя  сегмента  должно  обязательно  присутствовать,  быть 
 +уникальным  и   соответствовать   соглашениям   для  имен  в 
 +ассемблере.  Директива  ENDS обозначает конец  сегмента. Обе 
 +директивы  SEGMENT и  ENDS  должны  иметь  одинаковые имена. 
 +Директива  SEGMENT  может  содержать  три  типа  параметров, 
 +определяющих выравнивание, объединение и класс. 
 +== Выравнивание == 
 +Данный параметр определяет границу начала 
 +сегмента.  Обычным значением является PARA,  по которму 
 +сегмент устанавливается на  границу  параграфа.  В этом 
 +случае начальный адрес делится на 16  без остатка, т.е. 
 +имеет  шест.  адрес  nnn0.  В  случае  отсутствия этого 
 +операнда ассемблер принимает по умолчанию PARA. 
 +== Объединение == 
 +Этот элемент  определяет объединяется  ли 
 +данный   сегмент   с  другими  сегментами   в  процессе 
 +компановки  после  ассемблирования   (пояснения  см.  в 
 +следующем  разделе  "Компановка  программы").  Возможны 
 +следующие типы  объединений:  STACK, COMMON, PUBLIC, AT 
 +выражение   и   MEMORY.   Сегмент   стека  определяется 
 +следующим образом: 
 + 
 +               имя  SEGMENT   PARA STACK 
 + 
 +Когда отдельно ассемблированные программы должны объединяться  компановщиком,   то  можно  использовать  типы: 
 +PUBLIC,  COMMON и  MEMORY.  В случае, если программа не 
 +должна объединяться  с другими  программами,  то данная опция может быть опущена. 
 +== Класс == 
 +Данный элемент, заключенный в апострофы,  используется  для группирования  относительных  сегментов при 
 +компановке: 
 + 
 +               имя  SEGMENT   PARA   STACK   'Stack' 
 + 
 +Фрагмент  программы  на  рис.  3.1.  в  следующем разделе 
 +иллюстрирует директиву SEGMENT и ее различные опции. 
 + 
 +=== Директива PROC === 
 + 
 +Сегмент  кода  содержит  выполняемые  команды  программы. 
 +Кроме  того  этот  сегмент также включает  в  себя  одну или 
 +несколько процедур,  определенных директивой  PROC. Сегмент, 
 +содержащий только одну процедуру имеет следующий вид: 
 + 
 +     имя-сегмента   SEGMENT   PARA 
 +     имя-процедуры  PROC      FAR       Сегмент 
 +                    .                   кода 
 +                    .                   с 
 +                    .                   одной 
 +                    RET                 процедурой 
 +     имя-процедуры  ENDP 
 +     имя-сегмента   ENDS 
 +Имя  процедуры  должно  обязательно  присутствовать, быть 
 +уникальным и удовлетворять соглашениям по именам  в ассембле 
 +ре.  Операнд FAR указывает загрузчику DOS, что начало данной 
 +процедуры является точкой входа для выполнения программы. 
 +Директива  ENDP  определяет конец процедуры  и имеет имя, 
 +аналогичное  имени в директиве PROC.  Команда  RET завершает 
 +выполнение программы и в данном случае возвращает управление 
 +в DOS. 
 +Сегмент может содержать несколько процедур. 
 + 
 +=== Директива  ASSUME === 
 + 
 +Процессор  использует  регистр  SS  для  адресации стека, 
 +ркгистр  DS для адресации  сегмента данных и регистр  CS для 
 +адресации  cегмента  кода.  Ассемблеру  необходимо  сообщить 
 +назначение каждого сегмента.  Для этой цели служит директива 
 +ASSUME, кодируемая в сегменте кода следующим образом: 
 + 
 +     Директива Операнд 
 +     ASSUME     SS:имя_стека,DS:имя_с_данных,CS:имя_с_кода 
 + 
 +Например,  SS:имя_стека  указывает,  что ассемблер должен 
 +ассоциировать  имя сегмента  стека с регистром  SS. Операнды 
 +могут  записываться  в любой последовательности.  Регистр ES 
 +также может присутствовать в числе операндов. Если программа 
 +не использует регистр ES,  то его можно опустить или указать 
 +ES:NOTHING. 
 + 
 +=== Директива END === 
 + 
 +Как уже показано,  директива  ENDS  завершает  сегмент, а 
 +директива  ENDP  завершает процедуру.  Директива END  в свою 
 +очередь полностью завершает всю программу: 
 + 
 +          Директива      Операнд 
 +          END            [имя_процедуры] 
 + 
 +Операнд может быть опущен,  если программа не предназначе 
 +на для выполнения, например, если ассемблируются только определения данных, или эта программа должна быть скомпанована с 
 +другим  (главным)  модулем.  Для  обычной программы  с одним 
 +модулем oперанд содержит  имя,  указанное в  директиве PROC, 
 +которое было oбозначено как FAR.
  
 +===== Hello, world! =====
 +[[http://www.roesler-ac.de/wolfram/hello.htm]]