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

Ваш аккаунт

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

Последние темы форума

Показать новые сообщения »

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

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

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


Оглавление

                       Режимы адресации к памяти
-----------------------------------------------------------------

     Как при использовании операнда в памяти задать ту ячейку па-
мяти,  с  которой  вы  хотите работать? Очевидный ответ состоит в
том, чтобы присвоить нужной переменной в памяти имя (как  мы  это
делали  в последнем разделе). С помощью, например, следующих опе-
раторов вы можете вычесть переменную памяти Debts (долги) из  пе-
ременной памяти Assets (имущество):

          .
          .
          .
  Assets  DW   ?
  Debts   DW   ?
          .
          .
          .
          mov   ax,[Debts]
          sub   [Assets],ax
          .
          .
          .

     Однако адресация к памяти имеет и более глубокий смысл,  ко-
торый не бросается в глаза. Предположим, у вас имеется символьная
строка с именем CharString, содержащая буквы ABCDEFGHIGKLM, кото-
рые начинаются в сегменте данных со смещения 100, как показано на
Рис. 4.1. Каким образом можно считать девятый символ (I), который
расположен  по  адресу 108? В языке Си вы можете просто использо-
вать оператор:

        C = CharString[8];

(в Си элементы нумеруются с 0), а в Паскале:

        C := CharString[9];

     Как же это можно сделать  в  Ассемблере?  Прямая  ссылка  на
строку  CharString  здесь,  конечно,  не подходит, так как первым
символом является символ A.

                                        .              .
                                        .              .
                                        |              |
                                        |--------------|

TASM2 #1-5/Док              = 137 =

                                     99 |      ?       |
                                        |--------------|
        CharString -------------->  100 |     'A'      |
                                        |--------------|
                                    101 |     'B'      |
                                        |--------------|
                                    102 |     'C'      |
                                        |--------------|
                                    103 |     'D'      |
                                        |--------------|
                                    104 |     'E'      |
                                        |--------------|
                                    105 |     'F'      |
                                        |--------------|
                                    106 |     'G'      |
                                        |--------------|
                                    107 |     'H'      |
                                        |--------------|
                                    108 |     'I'      |
                                        |--------------|
                                    109 |     'J'      |
                                        |--------------|
                                    110 |     'K'      |
                                        |--------------|
                                    111 |     'L'      |
                                        |--------------|
                                    112 |     'M'      |
                                        |--------------|
                                    113 |      0       |
                                        |--------------|
                                    114 |      ?       |
                                        |--------------|
                                        .              .
                                        .              .

     Рис. 5.1 Ячейки памяти со строкой символов CharString.

     В действительности язык  Ассемблера  обеспечивает  несколько
различных способов адресации к строкам символов, массивам и буфе-
рам данных. Наиболее простой способ состоит в том, чтобы  считать
девятый по счету символ строки CharString:

          .
          .
          .
          .DATA
  CharString  DB  'ABCDEFGHIJKLM'
          .
          .
          .
          .CODE
          .
          .
          .
          mov   ax,@Data
          mov   ds,ax
          mov   al,[CharString+8]
          .
          .
          .

     В данном случае это тоже самое, что:

          mov   al,[100+8]

так как CharString начинается со смещения 100. Все, что заключено
в  квадратные скобки, интерпретируется Турбо Ассемблером, как ад-
рес, поэтому смещение CharString и 8 складывается и  используется
в качестве адреса памяти. Инструкция принимает вид:

          mov   al,[108]

как показано на Рис. 5.2.

                                      .              .
                                      .              .
                                      |              |
                                      |--------------|
                                   99 |      ?       |
                                      |--------------|
      CharString -------------->  100 |     'A'      |
                                      |--------------|
                                  101 |     'B'      |
                                      |--------------|
                                  102 |     'C'      |
                                      |--------------|
                                  103 |     'D'      |
                                      |--------------|
                                  104 |     'E'      |
                                      |--------------|
                                  105 |     'F'      |
                                      |--------------|
                                  106 |     'G'      |
                                      |--------------|
                                  107 |     'H'      |-------
                                      |--------------|      |
      CharString+8 ----------->   108 |     'I'      |      |
                                      |--------------|      V
                                  109 |     'J'      |   --------
                                      |--------------|   |      |
                                  110 |     'K'      |   --------
                                      |--------------|      AL
                                  111 |     'L'      |
                                      |--------------|
                                  112 |     'M'      |
                                      |--------------|
                                  113 |      0       |
                                      |--------------|
                                  114 |      ?       |
                                      |--------------|
                                      .              .
                                      .              .

     Рис. 5.1 Адресация строки символов строки CharString.

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

     Рассмотрим следующий фрагмент программы, где  в  регистр  AL
также загружается девятый символ CharString:

          .
          .
          .
          mov   bx,OFFSET CharString+8
          mov   al,[bx]
          .
          .
          .

     В данном примере для ссылки на девятый  символ  используется
регистр BX.  Первая  инструкция  загружает  в регистр BX смещение
CharString (вспомните о том,  что операция OFFSET возвращает сме-
щение метки в памяти),  плюс 8. (Вычисление OFFSET и сложение для
этого выражения выполняется Турбо Ассемблером во время  ассембли-
рования.)  Вторая  инструкция определяет,  что AL нужно сложить с
содержимым по смещению в памяти,  на которое указывает регистр BX
(см. Рис. 5.3).

          mov   al,[108]

как показано на Рис. 5.2.

                                      .              .
                                      .              .
                                      |              |
                                      |--------------|
                                   99 |      ?       |
                                      |--------------|
      CharString -------------->  100 |     'A'      |
                                      |--------------|
                                  101 |     'B'      |
                                      |--------------|
                                  102 |     'C'      |
                                      |--------------|
                                  103 |     'D'      |
                                      |--------------|
                                  104 |     'E'      |
                                      |--------------|
                                  105 |     'F'      |
                                      |--------------|
                                  106 |     'G'      |
                                      |--------------|
                                  107 |     'H'      |-------
      -----------                     |--------------|      |
   BX |   108   | ------------>   108 |     'I'      |      |
      -----------                     |--------------|      V
                                  109 |     'J'      |   --------
                                      |--------------|   |      |
                                  110 |     'K'      |   --------
                                      |--------------|      AL
                                  111 |     'L'      |
                                      |--------------|
                                  112 |     'M'      |
                                      |--------------|
                                  113 |      0       |
                                      |--------------|
                                  114 |      ?       |
                                      |--------------|
                                      .              .
                                      .              .

     Рис. 5.3 Использование регистра BX для адресации  к  строке
CharString.

     Квадратные скобки показывают, что в качестве операнда-источ-
ника должна быть использоваться ячейка, на которую указывает ре-
гистр BX а не сам регистр BX.  Не забывайте указывать квадратные
скобки при использовании BX в качестве указателя памяти.  Напри-
мер:

             mov   ax,[bx]    ; загрузить AX из ячейки памяти,
                              ; на которую указывает BX
и
             mov   ax,bx      ; загрузить в AX содержимое
                              ; регистра BX

это две совершенно различные инструкции.

     Может возникнуть  вопрос,  зачем сначала загружать в регистр
BX смещение ячейки памяти и затем использовать BX, как указатель,
если тоже самое можно сделать с помощью одной инструкции с непос-
редственным операндом?  Особое свойство регистров, используемых в
качестве указателей,  состоит в том, что в отличие от инструкций,
использующих непосредственные операнды,  инструкции, использующие
в качестве указателей регистры, могут ссылаться в разное время (в
процессе выполнения программы) на разные ячейки памяти.

     Предположим, вы хотите определить последний символ завершаю-
щейся  нулем строки CharString. Чтобы это сделать, вы должны, на-
чиная с первого  символа  строки  CharString,  найти  завершающий
строку нулевой байт,  затем вернуться назад на один символ и счи-
тать этот последний символ.  Это невозможно сделать с помощью не-
посредственной адресации, так как строка может иметь произвольную
длину. Использование регистра BX значительно облегчает задачу:

          .
          .
          .
          mov   bx,OFFSET CharString  ; указывает на строку
  FindLastCharLoop:
          mov   al,[bx]               ; получить следующий
                                      ; символ строки
          cmp   al,0                  ; это нулевой байт?
          je    FoundEndOfString      ; да, вернуться на
                                      ; один символ
          inc   bx
          jmp   FilnLastCharLoop      ; проверить следующий
                                      ; символ
  FoundEndOfString:
          dec   bx                    ; снова указывает на
                                      ; последний символ
          mov   al,[bx]               ; получить последний
          .                           ; символ строки
          .
          .

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

     BX - это не единственный регистр, который можно использовать
для ссылка на память. Допускается также использовать вместе с не-
обязательным значением-константой или меткой регистры  BP,  SI  и
DI. Общий вид операндов в памяти выглядит следующим образом:

     [базовый регистр + индексный регистр + смещение]

где базовый регистр - это BX или BP, индексный регистр -  SI  или
DI,  а смещение - любая 16-битовая константа, включая метки и вы-
ражения. Каждый раз, когда выполняется  инструкция,  использующая
операнд в памяти, процессором 8086 эти три компоненты складывают-
ся. Каждая из трех частей операнда в памяти является необязатель-
ной, хотя (это очевидно) вы должны использовать один из трех эле-
ментов, иначе вы не получите адреса в памяти.  Вот  как  элементы
операнда в памяти выглядят в другом формате:

          BX      SI
          или  +  или  + Смещение
          BP      DI
        (база)  (индекс)

     Существует 16 способов задания адреса в памяти:

   [смещение]          [bp+смещение]
   [bx]                [bx+смещение]
   [si]                [si+смещение]
   [di]                [di+смещение]
   [bx+si]             [bx+si+смещение]
   [bx+di]             [bx+di+смещение]
   [bp+si]             [bp+si+смещение]
   [bp+di]             [bp+di+смещение]

где смещение - это то, что можно свести к 16-битовому постоянному
значению.

     Может показаться, что 16 режимов адресации - это очень  мно-
го, но если вы еще раз посмотрите на этот список, вы увидите, что
все режимы адресации получаются всего  из  нескольких  элементов,
комбинируемых  различными  путями.  Вот еще несколько способов, с
помощью которых можно, используя различные режимы адресации, заг-
рузить девятый символ строки CharString в регистр AL:

          .
          .
          .
          .DATA
  CharString  DB  'ABCDEFGHIJKLM',0
          .
          .
          .
          .CODE
          mov  ax,@Data
          mov  ds,ax
          .
          .
          .
          mov  si,OFFSET CharString+8
          mov  al,[si]
          .
          .
          .
          mov  bx,8
          mov  al,[Charstring+bx]
          .
          .
          .
          mov  ..,OFFSET CharString
          mov  al,[bx+8]
          .
          .
          .
          mov  si,8
          mov  al,[CharString+si]
          .
          .
          .
          mov  bx,OFFSET CharString
          mov  di,8
          mov  al,[bx+di]
          .
          .
          .
          mov  si,OFFSET CharString
          mov  bx,8
          mov  al,[si+bx]
          .
          .
          .
          mov  bx,OFFSET CharString
          mov  si,7
          mov  al,[bx+si+1]
          .
          .
          .
          mov  bx,3
          mov  si,5
          mov  al,[bx+CharString+si]
          .
          .
          .

     Все эти инструкции ссылаются на одну и ту же ячейку памяти -
[CharString]+8.

     В данном примере можно найти несколько интересных  моментов.
Во-первых,  вы  должны  понимать, что знак плюс (+), используемый
внутри квадратных скобок, имеет специальное  значение.  Во  время
ассемблирования  Турбо Ассемблер складывает все постоянные значе-
ния (константы) внутри квадратных скобок, поэтому инструкция:

         mov   [10+bx+si+100],cl

принимает вид:

         mov   [bx+si+111],cl

     После этого при реальном  выполнении  инструкции  (во  время
прогона  программы) операнды в памяти складываются вместе процес-
сором 8086. Если регистр BX содержит значение 25, а  SI  содержит
52,  то  при  выполнении инструкции MOV CL записывается по адресу
памяти 25 + 52 + 111 = 188. Ключевой момент состоит  в  том,  что
базовый регистр, индексный регистр и смещение складываются вместе
процессором 8086 при выполнении инструкции. Таким образом,  Турбо
Ассемблер  складывает  константы во время ассемблирования, а про-
цессор 8086 складывает содержимое базового  регистра,  индексного
регистра  и смещения во время действительного выполнения инструк-
ции.

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

     Пояснение использования регистра BP для адресации к сегменту
стека приводится в Главе 4. В данный момент достаточно знать, что
регистр BP можно использовать так же, как мы использовали в  при-
мерах  регистр  BX, только адресуемые данные должны в этом случае
находиться в стеке.

     (На самом деле регистр BP можно использовать и для адресации
к  сегменту данных, а BX, SI и DI - для адресации к сегменту сте-
ка, дополнительному сегменту или сегменту кода. Для этого исполь-
зуются  префиксы переопределения сегментов (segment override pre-
fixes). О некоторых из них мы расскажем  в  Главе  10.  Однако  в
большинстве случаев они вам не понадобятся, поэтому пока мы прос-
то забудем об их существовании.)

     Наконец, квадратные скобки,  в  которые  заключаются  непос-
редственные адреса, являются необязательными. То есть инструкции:

       mov   al,[MemVar]
и
       mov   al,MemVar

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

     Вы можете использовать также такую форму адресации к памяти:

        mov   al,CharString[bx]

или даже

        mov   al,CharString[bx][si]+1

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

        mov   al,[charString+bx+si+1]

     Здесь снова нужно выбрать ту форму записи, которая вам боль-
ше нравится, и придерживаться ее.

     Квадратные скобки, в которые заключаются регистры, указываю-
щие  на  ячейки  памяти, являются обязательными. Без этих скобок,
BX, например,  интерпретируется, как операнд, а не как ссылка на
операнд.




Оглавление

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

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

Комментарии

1.
53K
02 сентября 2009 года
Vadik94
0 / / 02.09.2009
+1 / -0
Мне нравитсяМне не нравится
25 ноября 2009, 23:04:12
как получилось 111?!
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог