Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:
реклама
Профессиональное средство для снятия макияжа - качество и результат

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

СПРАВОЧНИК по системе программирования ТУРБО АССЕМБЛЕР 2.0


Оглавление

                    Директивы .STACK, .CODE и .DATA
-----------------------------------------------------------------

     Директивы  определения  сегментов  .STACK,  .CODE  и   .DATA
определяют, соответственно, сегмент стека, сегмент кода и сегмент
данных. Например, директива:

       .STACK   200h

определяет стек  размером в 200h (512) байт.  Что касается стека,
то это все,  что вы сможете сделать. Необходимо просто убедиться,
что в вашей программе имеется директива .STACK, и Турбо Ассемблер
выделит для вас стек.  Для обычных программ вполне подходит  стек
размером  200h,  хотя в программах,  интенсивно использующих стек
(например,  в программах,  содержащих рекурсивные  вызовы)  может
потребоваться  стек большего размера.  (Информация об исключениях
при использовании директивы .STACK приведена в разделе "Невыделе-
ние стека или выделение слишком маленького стека" в Главе 6.)

     Директива .CODE отмечает начало  сегмента  кода.  Вы  можете
посчитать,  что для Турбо Ассемблера достаточно очевидно, что все
ваши инструкции относятся к сегменту кода. На  самом  деле  Турбо
Ассемблер позволяет вам (с помощью стандартных директив определе-
ния сегментов) использовать несколько сегментов кода, а директива
.CODE указывает Турбо Ассемблеру, в какой именно сегмент надо по-
местить ваши инструкции. Определение сегмента кода еще проще, чем
определение сегмента стека, так как аргументы для директивы .CODE
указывать не требуется. Например:

        .
        .
        .
        .CODE
        sub     ax,ax   ; установить аккумулятор в значение 0
        mov     cx,100  ; число выполняемых циклов
        .
        .
        .

     Директива .DATA несколько более сложна.  Как  можно  понять,
директива .DATA отмечает начало сегмента данных.  В этом сегменте
следует размещать ваши переменные памяти. Например:

        .
        .
        .
        .DATA
TopBoundary     DW      100
Counter         DW      ?
ErrorMessage    BD      0dh,0dh,'***Ошибка***',0dh,0ah,'$'
        .
        .
        .

     Это довольно просто.  Вся "сложность" директивы .DATA заклю-
чается в том, что до того, как вы будете обращаться к ячейкам па-
мяти  в сегменте,  определенном с помощью директивы .DATA,  нужно
явно загружать сегментный регистр DS идентификатором  @data.  Так
как  сегментный регистр можно загрузить из регистра общего назна-
чения или ячейки памяти,  но в него нельзя  загрузить  константу,
регистр  DS  обычно  загружается  с помощью последовательности из
двух инструкций:

        .
        .
        .
        mov     ax,@data
        mov     ds,ax
        .
        .
        .

(Вместо регистра AX можно использовать любой общий регистр.) Дан-
ная последовательность инструкций устанавливает DS таким образом,
чтобы он указывал на сегмент данных, который начинается по дирек-
тиве .DATA.

     Следующая программа выводит на  экран  текст,  хранящийся  в
строке DataString:

        DOSSEG
        .MODEL
        .STACK  small
        .DATA
DataString      DB      'Этот текст находится в сегменте данных'
        .CODE
ProgramStart:
        mov     bx,@data
        mov     ds,bx   ; устанавливает регистр DS на сегмент
                        ; данных
        mov     dx,OFFSET DataString ; DX указывает на смещение
                        ; DataString в сегменте .DATA
        mov     ah,9    ; номер функции DOS печати строки
        int     21h     ; вызвать DOS для печати строки
        mov     ah,4ch  ; вызвать DOS для завершения программы
        END     ProgramStart

     Без двух инструкций, которые устанавливают регистр DS в зна-
чение сегмента,  определенного с помощью директивы .DATA, функция
печати строки не будет правильно работать.  Строка DataString на-
ходится в сегменте данных и недоступна,  пока регистр DS не будет
установлен  в  значение  этого сегмента.  Это можно рассматривать
следующим образом:  когда вы вызываете операционную  систему  DOS
для печати строки, в паре регистров DS:DX вы передаете полный ад-
рес в формате "сегмент:смещение". Полный указатель вида "сегмент:
смещение"  вы получите только после того,  как в регистр DS будет
загружен сегмент данных, а в DX - смещение DataString.

     У вас может возникнуть вопрос,  почему нужно  загружать  ре-
гистр DS, а не CS или SS (или ES)?

     Во первых,  регистр CS никогда не загружается явно,  так как
при запуске программы за вас это делает операционная система DOS.
Кроме того, если бы регистр CS уже не был установлен, когда приш-
ло время выполнить первую инструкцию программы, процессор 8086 не
знал бы,  где найти эту инструкцию, и программа не стала бы рабо-
тать.  Пока для вас это может быть недостаточно очевидно,  но по-
верьте нам на слово: регистр CS загружается при запуске программы
автоматически, и у вас нет необходимости загружать его явно.

     Аналогично, при запуске программы DOS загружает  регистр SS,
значение  которого при выполнении программы обычно остается неиз-
менным. Хотя изменять содержимое регистра  SS  можно,  это  редко
оказывается желательным,  и определенно это не стоит делать, если
вы не знаете точно,  что вы делаете.  Таким образом,  регистр  SS
аналогично регистру  CS  устанавливается  при  начале  выполнения
программы автоматически, и далее его трогать не нужно.

     Регистр DS существенно от них отличается. В то время как ре-
гистр CS указывает на инструкции, а SS - на стек, регистр DS ука-
зывает на данные.  Программы не работают непосредственно  с  инс-
трукциями  или  стеком,  однако с данными они работают постоянно.
Кроме того, программы могут в любой момент пожелать получить дан-
ные в нескольких разных сегментах.  Нужно помнить о том, что про-
цессор 8086 в любое время позволяет вам получить доступ  к  любой
ячейке памяти в пределах 1 Мбайта, но только в блоках по 64К (от-
носительно сегментного регистра).

     Вы можете захотеть загрузить регистр DS одним сегментом, по-
лучить доступ к данным в этом сегменте, а затем загрузить DS дру-
гим сегментом, чтобы обратиться к другому блоку данных. В малень-
ких и средних программах (таких, как в приведенных нами примерах)
вам не потребуется использовать более одного сегмента  данных, но
в больших программах несколько сегментов данных используется час-
то.  Кроме того,  вам потребуется загружать регистр DS  различным
значениями,  если  вы хотите получить доступ к системным областям
памяти, например, к ячейкам памяти, используемым базовой системой
ввода-вывода (BIOS).

     Из всего этого можно сделать следующий краткий  вывод: Турбо
Ассемблер  позволяет  вам  в любой момент установить регистр DS в
значение любого сегмента.  За эту гибкость  приходится  расплачи-
ваться тем,  что вы должны явно устанавливать регистр DS в значе-
ние нужного сегмента (обычно @data),  что эквивалентно  сегменту,
который начинается с директивы .DATA.  После этого вы сможете по-
лучить доступ к ячейкам памяти этого сегмента.

     Сегментный регистр  ES  загружается  аналогично регистру DS.
Чаще всего вам не потребуется использовать регистр ES,  но  когда
появится  необходимость получить доступ к ячейке памяти в сегмен-
те, на который указывает регистр ES, вы должны сначала загрузить
регистр ES значением этого сегмента.  Например,  следующая прог-
рамма загружает регистр ES значением  сегмента  .DATA,  а  затем
загружает  через  ES  символ,  который нужно напечатать из этого
сегмента:

        DOSSEG
        .MODEL  small
        .STACK  200h
        .DATA
OutputChar      DB      'B'
        .CODE
ProgramStart:
          mov     dx,@data
          mov     es,dx      ; установить ES в значение
                             ; сегмента .DATA
          mov   bx,OFFSET OutputChar ; BX указывает на
                             ; смещение OutputChar
          mov   al,es:[bx]   ; получить выводимый символ
                             ; из сегмента, на который
                             ; указывает регистр ES
          mov   ah,2         ; функция DOS вывода символа
          int   21h          ; вызвать DOS для вывода
                             ; символа на экран
          END   ProgramStart

     Обратите внимание,  что  регистр ES (как и регистр DS ранее)
загружается последовательностью из двух инструкций:

          .
          .
          .
          mov   dx,@Data
          mov   es,dx
          .
          .
          .

     Положим, в данном примере нет конкретной  причины  использо-
вать вместо DS регистр ES.  Фактически, использование регистра ES
означает,  что мы применили префикс переопределения сегмента  ES:
(как это описывается в Главе 9). Однако во многих случаях чрезвы-
чайно удобно,  когда регистр DS указывает на один сегмент,  а ре-
гистр ES - на другой (особенно это касается использования строко-
вых инструкций).



Оглавление

Оставить комментарий

Комментарий:
можно использовать BB-коды
Максимальная длина комментария - 4000 символов.
 

Комментарии

1.
75K
21 сентября 2011 года
Irina***
0 / / 21.09.2011
+3 / -0
Мне нравитсяМне не нравится
21 сентября 2011, 05:53:24
Опечатка: в программе должно быть написано .model small и .stack без слова small, так же в конце программы после mov ah,4ch пропущено int 21h
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог