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

Различия

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

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

Следующая версия
Предыдущая версия
asm:lesson6 [20/10/2010 20:57] – создано arabusovasm:lesson6 [21/10/2010 21:30] (текущий) arabusov
Строка 1: Строка 1:
 ====== Урок 6 ====== ====== Урок 6 ======
 ===== Работа с памятью ===== ===== Работа с памятью =====
 +Сегмент  данных  предназначен  для  определения констант,
 +рабочих полей и областей  для  вводв-вывода.  В соответствии
 +с имеющимися директивами в ассемблере  разрешено определение
 +данных  различной длины:  например,  директива DB определяет
 +байт,  а директива DW oпределяет слово. Элемент данных может
 +содержать непосредственное значение или константу, определенную как символьная строка или как числовое значение.
 +Другим  способом определения  константы является непосредственное  значение,  т.е.  указанное  прямо  в  ассемблерной
 +команде, например:
 +
 +                    MOV  AL,20H
 +
 +В  этом  случае  шестнадцатеричное  число  20  становится
 +частью ма шинного объектного кода. Непосредственное значение
 +ограничено  oдним байтом или  одним словом,  но там, где оно
 +может быть  применено,  оно является  более эффективным, чем
 +использование конcтанты.
 +
 +==== Директивы определения данных ====
 +
 +Ассемблер  обеспечивает  два способа  определения данных:
 +во-первых,  через указание длины данных и,  во-вторых, по их
 +cодержимому. Рассмотрим основной формат определения данных:
 +
 +               [имя]     Dn   выражение
 +
 +  - Имя  элемента  данных  не  обязательно (это указывается
 +квадратными  скобками),  но  если  в  программе имеются
 +ссылки   на   некоторый   элемент,   то   это  делается
 +посредством имени.  Правила  написания имен приведены в
 +разделе "Формат кодирования" в  главе 3.
 + - Для  определения  элементов  данных  имеются  следующие
 +директивы:  DB (байт),  DW (слово), DD (двойное слово),
 +DQ (учетверенное слово) и DT (десять байт).
 + - Выражение может содержать константу, например:
 +
 +                    FLD1      DB   25
 +
 +или знак вопроса для неопределенного значения, например
 +
 +                    FLDB      DB   ?
 +
 +Выражение может содержать несколько констант, разделенных
 +запятыми и ограниченными только длиной строки:
 +
 +          FLD3      DB   11, 12, 13, 14, 15, 16, ...
 +
 +Ассемблер определяет эти константы в виде последовательности
 +cмежных  байт.  Ссылка по  имени  FLD3  указывает  на первую
 +константу,  11,  по FLD3+1  -  на  вторую,  12.  (FLD3 можно
 +представить как FLD3+0). Например команда
 +
 +                    MOV  AL,FLD3+3
 +
 +загружает  в регистр AL  значение  14  (шест. 0E). Выражение
 +допускает также повторение константы в следующем формате:
 +
 +          [имя]     Dn  число-повторений DUP (выражение) ...
 +
 +Следующие три примера иллюстрируют повторение:
 +
 +          DW   10 DUP(?     ;Десять неопределенных слов
 +          DB   5 DUP(14)      ;Пять байт, содержащих шест.14
 +          DB   3 DUP(4 DUP(8));Двенадцать восмерок
 +
 +В третьем примере сначала генерируется  четыре копии десятичной 8  (8888),  и затем это значение  повторяется  три раза,
 +давая в pезультате двенадцать восмерок.
 +Выражение может содержать символьную  строку или числовую
 +константу.
 +
 +==== Символьные строки ====
 +
 +
 +Символьная  строка  используются  для   описания  данных,
 +таких как,  например,  имена  людей  или  заголовки страниц.
 +Содержимое    строки    oтмечается   одиночными   кавычками,
 +например,  'PC'  или  двойными  кавычками -  "PC". Ассемблер
 +переводит  символьные  строки  в  объектный  код  в  обычном
 +формате ASCII.
 +Символьная  строка  определяется только директивой  DB, в
 +котоpой указывается более двух символов в нормальной последовательности  слева  направо.   Следовательно,  директива  DB
 +представляет единственно  возможный  формат  для определения
 +символьных данных.
 +
 +==== Числовые константы ====
 +Числовые   константы   используются   для  арифметических
 +величин и для aдресов памяти. Для описания константы кавычки
 +не ставятся.  Ассемблер преобразует все числовые константы в
 +шестнадцитеричные и  записывает  байты  в  объектном  коде в
 +обратной  последовательности -  справа налево. Ниже показаны
 +различные числовые форматы.
 +=== Десятичный формат ===
 +Десятичный формат допускает десятичные
 +цифры от 0  до 9  и обозначается последней буквой D, которую
 +можно не указывать,  например, 125 или 125D. Несмотря на то,
 +что  ассемблер позволяет кодирование  в  десятичном формате,
 +он  преобразует   эти   значения  в   шест.  объектный  код.
 +Например, десятичное число 125 преобразуется в шест. 7D.
 +
 +=== Шестнадцатиричный  формат ===
 +Шестнадцатиричный формат допускает шест.
 +цифры от 0  до F и обозначается последней буквой H.  Так как
 +ассемблер полагает,  что с  буквы начинаются идентификаторы,
 +то первой цифрой шест.  константы должна быть цифра  от 0 до
 +9.  Например,  2EH или 0FFFH,  которые ассемблер преобразует
 +соответственно в 2E и FF0F  (байты во втором  примере записы
 +ваются в объектный код в обратной последовательности).
 +=== Двоичный формат ===
 +Двоичный формат допускает двоичные цифры
 +0  и  1  и обозначается последней буквой  B. Двоичный формат
 +обычно используется для более  четкого представления битовых
 +значений  в  логических  командах  AND,   OR,  XOR  и  TEST.
 +Десятичное 12,  шест. C и двоичное 1100B все генерируют один
 +и тот же код:  шест. 0C или двоичное 0000 1100 в зависимости
 +от того, как вы рассматриваете содержимое байта.
 +
 +=== Восмеричный формат ===
 +Восмеричный формат допускает восмеричные цифры от 0 до 7 и обозначается последней буквой Q или O,
 +например,  253Q.  На сегодня восмеричный формат используется
 +весьма редко.
 +
 +При  записи  символьных  и   числовых   констант  следует
 +помнить,  что,  например, символьная константа, определенная
 +как DB '12',  представляет символы ASCII и  генерирует шест.
 +3132, а числовая константа, oпределенная как DB 12, представляет двоичное число и генерирует шест. 0C.
 +==== Директива опеделения байта ====
 +Из  различных  директив,  определяющих  элементы  данных,
 +наиболее полезной является DB (определить  байт). Символьное
 +выражение  в диpективе DB  может  содержать  строку символов
 +любой длины,  вплоть до конца строки.
 +Числовое выражение в директиве  DB  может  содержать одну
 +или более однобайтовых констант.  Один байт выражается двумя
 +шест.  цифpами. Наибольшее положительное шест. число в одном
 +байте это 7F, если подразумевается, что это число знаковое, и 0FF, если подразумевается, что число беззнаковое
 +
 +==== Директива определения слова (DW) ====
 +Директива DW определяет  элементы,  которые имеют длину в
 +одно слово (два байта). Символьное выражение в DW ограничено
 +двумя символами,  которые ассемблер представляет в объектном
 +коде   так,   что,   например,  'PC'  становится  'CP' Для
 +определения символьных строк директива DW имеет ограниченное
 +применение.
 +Числовое выражение в DW  может содержать  одно  или более
 +двухбайтовых  констант.  Два  байта  представляются четырьмя
 +шест.  цифрами.  Наибольшее положительное шест. число в двух
 +байтах  это  7FFF;  все  "большие"  числа  от  8000  до FFFF
 +представляют отрицательные значения. В десятичном исчислении
 +эти пределы выражаются числами +32767 и -32768.
 +Для форматов директив DW,  DD и DQ  ассемблер преобразует
 +константы  в  шест.  объектный  код,  но  записывает  его  в
 +обратной   последовательности.   Таким   образом  десятичное
 +значение 12345  преобразуется в шест.3039, но записывается в
 +объектном коде как 3930.
 +
 +==== Директива определения двойного слова (DD) ====
 +Директива DD определяет  элементы,  которые имеют длину в
 +два  cлова   (четыре   байта).   Числовое   выражение  может
 +содержать одну или  более констант,  каждая из которых имеет
 +максимум  четыре  байта  (восемь  шест.   цифр).  Наибольшее
 +положительное шест. число в четырех байтых это 7FFFFFFF; все
 +"большие"   числа  от  80000000   до  FFFFFFFF  представляют
 +отрицательные значения.  В десятичном исчислении эти пределы
 +выражаются числами +2147483647 и -2147483648.
 +Ассемблер преобразует все числовые  константы в директиве
 +DD  в шест.  представление,  но записывает  объектный  код в
 +обратной   последовательности.   Таким   образом  десятичное
 +значение   12345   преобразуется   в   шест.   00003039,  но
 +записывается в oбъектном коде как 39300000.
 +
 +
 +==== Директива определения учетверённого слова (DQ) ====
 +Директива DQ  определяет  элементы,  имеющие длину четыре
 +слова (восемь байт). Числовое выражение может содержать одну
 +или  более  констант,   каждая  из  которых  имеет  максимум
 +восемь байт или 16 шест.цифр. Наибольшее положительное шест.
 +число - это семерка и 15 цифр F. Для получения представления
 +о величине  этого числа,  покажем,  что шест.  1  и 15 нулей
 +эквивалентен следующему десятичному числу:
 +
 +                    1152921504606846976
 +Ассемблер преобразует  все числовые константы в директиве  DQ в шест.  представление, но записывает
 +объектный код в обратной последовательности,  как и в дирек-
 +тивах DD и DW.
 +Обработка ассемблером  символьных  строк  в  директиве DQ
 +aналогично директивам DD и DW.
 +
 +==== Директива определения десяти байт (DT)====
 +Директива DT определяет элементы данных,  имеющие длину в
 +десять   байт.   Назначение   этой   директивы   связано   с
 +"упакованными десятичными" числовыми величинами.
 +По  директиве   DT  генерируются   различные   константы,  в
 +зависимости   от   версии   ассемблера.
 +
 +==== Непосредственные операнды ====
 +Команда
 +
 +                    MOV   AX,0123H
 +
 +пересылает  непосредственную шест.  константу 0123 в регистр
 +AX.  Трехбайтный объектный код для этой команды есть B82301,
 +где B8  обозначает  "переслать  непосредственное  значение в
 +регистр AX",  a следующие два байта  содержат само значение.
 +Многие команды имеют два операнда: первый может быть регистр
 +или адрес памяти, а второй - непосредственная константа.
 +Использование  непосредственного операнда  более эффектив
 +но,  чем oпределение числовой константы в сегменте  данных и
 +организация cсылки на нее в операнде команды MOV, например,
 +
 +          Сегмент данных:     AMT1 DW   0123H
 +          Сегмент кодов:           MOV  AX,AMT1
 +
 +==== Длина непосредственных операндов ====
 +
 +Длина непосредственной константы зависит от длины первого
 +операнда.   Например,   следующий  непосредственный  операнд
 +является двухбайтовым, но регистр AL имеет только один байт:
 +
 +                    MOV  AL,0123H  (ошибка)
 +
 +однако, если непосредственный операнд короче, чем получающий
 +операнд, как в следующем примере
 +
 +                    ADD  AX,25H    (нет ошибки)
 +
 +то  ассемблер  расширяет  непосредственный  операнд  до двух
 +байт, 0025 и записывает объектный код в виде 2500.
 +
 +==== Непосредственные форматы ====
 +
 +Непосредственная константа  может быть шестнадцатиричной,
 +напpимер,   0123H;   десятичной,   например,   291  (которую
 +ассемблер   конвертирует   в   шест.0123);   или   двоичной,
 +например, 100100011В (которая преобразуется в шест. 0123).
 +Ниже   приведен   список    команд,   которые   допускают
 +непосредственные операнды:
 +
 +   Команды пересылки и сравнения:  MOV, CMP.
 +   Арифметические команды:         ADC, ADD, SBB, SUB.
 +   Команды сдвига:                 RCL, RCR, ROL, ROR, SHL, SAR, SHR.
 +   Логические команды:             AND, OR, TEST, XOR.
 +
 +==== Директива EQU ====
 +Директива EQU не определяет элемент данных, но определяет
 +значение,  которое может быть использовано для  постановки в
 +других   командах.   Предположим,   что  в  сегменте  данных
 +закодирована следующая директива EQU:
 +
 +                    TIMES     EQU  10
 +
 +Имя,  в данном  случае TIMES,  может быть представлено любым
 +допустимым в ассемблере  именем.  Теперь, в какой-бы команде
 +или  директиве  не  использовалось  слово   TIMES  ассемблер
 +подставит  значение  10.   Например,  ассемблер  преобразует
 +директиву
 +
 +                    FIELDA    DB   TIMES DUP (?)
 +в
 +                    FIELDA    DB   10 DUP (?)
 +
 +Имя, связанное с некоторым значением с помощью директивы
 +EQU, может использоваться в командах, например:
 +
 +              COUNTR    EQU  05
 +
 +
 +                  ...
 +              MOV  CX,COUNTR
 +
 +Ассемблер заменяет имя COUNTR  в команде MOV  на значение
 +05,  cоздавая операнд с непосредственным значением, как если
 +бы было закодировано
 +
 +                    MOV  CX,05     ;Ассемблер подставляет 05
 +
 +Здесь приемущество директивы EQU заключается  в  том, что
 +многие команды могут использовать  значение, определенное по
 +имени  COUNTR.  Если это значение  должно  быть изменено, то
 +изменению подлежит  лишь  одна  директива  EQU. Естественно,
 +что  использование  директивы  EQU  разумно  лишь  там,  где
 +подстановка имеет  смысл  для  ассемблера.  В  директиве EQU
 +можно использовать символические имена:
 +
 +               1.   TP   EQU  TOTALPAY
 +               2.   MPY  EQU  MUL
 +
 +Первый пример предполагает,  что в сегменте данных программы
 +опpеделено  имя  TOTALPAY.  Для  любой  команды,  содержащей
 +операнд TP,  ассемблер заменит его на адрес TOTALPAY. Второй
 +пример  показывает  возможность  использования  в  программе
 +слова MPY вместо обычного мнемокода MUL.
 +
 +===== Работа с файлами в MS-DOS =====
 +
 +==== Функции типа дескриптора ====
 +
 +В MS-DOS начиная со второй версии файловая система стала иерархической, т.е. появились каталоги (или их можно назвать папками, или директориями). С иерархической файловой системой вы знакомы из опыта общения с OS Windows. Полное имя файла представляет из себя обозначение дисковода, путь до файла и имя файла. По ограничениям MS-DOS размер имени файла не может превышать 8 символов на собственно имя и 3 символов на расширение. Полное имя файла в MS-DOS можно представить, например, так:
 +    C:\SYSTEM\COMMAND.COM
 +Специфика MS-DOS такова, что в имени файла регистр не учитывается, то есть вы можете записать как COMMAND.COM, так и command.com. Приведённый пример вообще говоря представляется в виде ASCIIZ последовательности - это значит, что каждому символу соответствует число из таблицы кодов ASCII символов, а также в конец строки добавляется число 0, то есть запись
 +   C:\SYSTEM\COMMAND.COM
 +преобразуется в
 +   43 3a 5c 53 59 53 54 45 4d 5c 43 4f 4d 4d 41 4e 44 2e 43 4f 4d 00
 +Для работы с файлом с помощью функции типа дескриптора, нужно поместить адрес имени файла в DS:DX. В регистр ah помещается номер функции, после чего вызывается прерывание int 21H. Все функции типа дескриптора после выполнения возвращают опущенный флаг переноса, если функция выполнена успешно и наоборот. Чтобы совершить переход к вашему обработчику ошибки, выполните команду
 +    jc      error
 +где error - указатель на начало обработчика.
 +Теперь рассмотрим некоторые функции типа дескриптора, которые нам сегодня пригодятся.
 +=== Создание файла ===
 +По заданному в коде ASCIIZ пути создаёт новый файл на указанном или текущем диске или на указанном или текущем каталоге. Если указанный файл существует, то он усекается до нулевой длины. В любом случае открывается файл и возвращается дескриптор (16-разрядное число, которое нужно просто запомнить - именно с помощью этого числа в дальнейшем программа сможет обратиться к именно этому файлу).
 +При вызове:
 +  * AH = 3cH
 +  * CX = атрибут (в нашем случае всегда 0)
 +  * DS:DX - адрес строки, содержащей имя файла
 +При возврате:
 +Успешно - флаг переноса сброшен
 +  * AX = дескриптор
 +Неудачно - флаг переноса установлен
 +  * AX = код ошибки
 +=== Открытие файла ===
 +По заданному в коде ASCIIZ пути открывает файл на указанном или текущем диске или на указанном или текущем каталоге. Возвращается дескриптор.
 +При вызове:
 +  * AH = 3dH
 +  * AL = режим доступа
 +   Биты      Описание
 +   0-2       000=чтение
 +             001=запись
 +             010=чтение/запись
 +  * DS:DX - адрес строки, содержащей имя файла
 +При возврате:
 +Успешно - флаг переноса сброшен
 +  * AX = дескриптор
 +Неудачно - флаг переноса установлен
 +  * AX = код ошибки
 +=== Закрытие файла ===
 +При вызове:
 +   * AH = 3Eh
 +   * BX =  дескриптор
 +При возврате:
 +Успешно - флаг переноса сброшен
 +Неудачно - флаг переноса установлен
 +  * AX = код ошибки
 +=== Чтение файла ===
 +При вызове:
 +  * AH = 3Fh
 +  * BX = дескриптор
 +  * CX = число байт для чтения
 +  * DS:DX = адрес буфера
 +При возврате:
 +Успешно - флаг переноса сброшен
 +  * AX = число переданных байтов (может быть меньше CX!)
 +Неудачно - флаг переноса установлен
 +  * AX = код ошибки
 +=== Запись в файл ===
 +При вызове:
 +  * AH = 40h
 +  * BX = дескриптор
 +  * CX = число байт для вывода записи
 +  * DS:DX = адрес буфера
 +При возврате:
 +Успешно - флаг переноса сброшен
 +  * AX = число переданных байтов (может быть меньше CX!)
 +Неудачно - флаг переноса установлен
 +  * AX = код ошибки