 |
|--------------|
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
После этого при реальном выполнении инструкции (во время
прогона программы) операнды в памяти складываются вместе процес-
|