Пильщиков
.pdf80 |
Программирование на языке ассемблера IBM PC Глава 1 |
|
|
|||
Пример 4 |
|
|
|
|
|
|
Ятя ввода задана |
последовательность из |
200 |
знаковых |
чисел |
(размером |
|
в слово). |
Требуется |
определить, сколько |
раз |
наименьшее |
из |
этих чисел |
встречается в данной последовательности, и вывести в одной строке экрана ПК само минимальное число и количество его вхождений.
Решение
Введем первое число и будем пока считать его минимальным и встретившимся только раз. Затем в цикле вводим остальные 199 чисел и для каждого из них выполняем следующие действия: если оно больше минимального, то ничего не делаем, если равно минимальному, то увеличиваем количество его вхождений на 1, а если оно меньше минимального, тогда запоминаем это число как новый минимум с количеством вхождений 1.
По завершению цикла минимальное число выводим как знаковое (по OUTINT), а число его вхождений как беззнаковое (по OUTWORD), причем, чтобы эти два чйсла не "слиплись", для второго числа указываем ширину поля вывода с запасом.
N |
EQU |
200 |
; к о л и ч е с т в о |
вводимых |
ч и с е л |
|
|||||||
|
OUTCH |
' > ' |
;приглашение к |
вводу |
ч и с е л |
|
|||||||
|
ININT |
АХ |
; к а к min |
б е р е т с я |
п е р в о е |
из |
чисел |
||||||
|
HOV |
ВХ,1 |
; к о л и ч е с т в о |
е г о |
|
вхождений |
|
||||||
|
MOV |
CX,N-1 |
; с ч е т ч и к |
цикла |
( к о л и ч е с т в о |
оставшихся ч и с е л ) |
|||||||
IN: |
ININT |
DX |
; в в о д очередного |
числа |
|
|
|||||||
|
CMP DX,АХ |
|
|
|
|
|
|
|
|
|
|
||
|
JG NEXT |
; очередное |
число |
> |
min |
—> |
NEXT |
||||||
|
JL NEWMIN |
; о ч е р е д н о е |
число |
< |
min |
—> |
NEWMIN |
||||||
|
INC |
BX |
; у ч е с т ь повторное |
вхождение |
min |
||||||||
|
JMP NEXT |
|
|
|
|
|
|
|
|
|
|
||
NEWMIN: MOV AX,DX |
;сменить |
min |
|
|
|
|
|
|
|||||
|
MOV BX,1 |
|
|
|
|
|
|
|
|
|
|
||
NEXT: |
LOOP |
IN |
;цикл |
N - l |
р а з |
|
|
|
|
|
|
||
|
OUTINT AX |
;вывод |
min |
( к а к |
|
з н а к о в о г о ) |
|
||||||
|
OUTWORD BX,5 |
;вывод числа вхождений |
( к а к б е з з н а к о в о г о ) |
||||||||||
|
NEWLINE |
; п е р е в о д |
строки |
|
|
|
|
|
|
||||
|
FINISH |
|
|
|
|
|
|
|
|
|
|
||
Пример 5
Ввести последовательность (возможно, пустую) символов, за которой следует точка (это признак конца последовательности), и определить, упорядочена ли эта последовательность по неубыванию кодов символов. В качестве ответа выдать "УПОРЯДОЧЕНО" или "НЕ УПОРЯДОЧЕНО".
Решение
Будем вводить по одному символу (до точки), храня при этом предыдущий символ последовательности. Если эта пара символов неправильно упорядочена,
Переходы. Циклы |
81 |
тогда прекращаем цикл, очищаем буфер ввода от символов, которые пользователь мог набрать загодя, и выдаем ответ. Если же пара соседних символов упорядочена как надо, тогда очередной символ запоминаем как предыдущий и повторяем цикл. Если в качестве очередного символа была введена точка, то это значит, что последовательность упорядочена.
Ответ будем выводить как строку (по OUTSTR). Для этого описываем в прог-
рамме строку |
"НЕ УПОРЯДОЧЕНО", за которой следует знак $, |
и |
записываем |
в регистр DX |
начальный адрес этой строки, для чего определяем |
в |
программе |
еще одну переменную, начальным значением которой является адрес этой строки. Если исходная последовательность не упорядочена, тогда сразу выполняем операцию OUTSTR, а иначе увеличиваем значение регистра DX на 3, чтобы пропустить первые три символа нашей строки, чтобы DX указывал на начало подстроки "УПОРЯДОЧЕНО", и только после этого выполняем OUTSTR.
ANS DB "НЕ УПОРЯДОЧЕНО","$" |
|
|
|
|
|
||||||
ДА DW ANS |
; а д р е с строки ANS |
|
|
* |
|
|
|||||
|
MOV |
DX, АА |
;DX - |
на |
начало с т р о к и |
ABS |
|
|
|||
|
OUTCH ' > ' ;приглашение к вводу |
|
|
|
|
||||||
|
MOV |
AL,0 |
предыдущий |
символ |
( в н а ч а л е - |
с |
кодом 0) |
||||
IN: |
INCH |
АН |
;очередной |
символ |
|
|
|
|
|
||
|
СМР |
А Н , ' |
|
|
|
|
|
|
|
|
|
|
JE YES |
; введена |
т о ч к а —> YES |
|
|
|
|
||||
|
CMP |
AL,АН |
; с р а в н и т ь |
предыдущий и |
очередной |
символы |
|||||
|
JA NO |
; неправильный порядок —> N0 |
|
|
|||||||
|
MOV |
AL, АН |
;очередной |
символ |
с т а н о в и т с я |
предыдущим |
|||||
|
JMP |
IN |
;в цикл |
|
|
|
|
|
|
|
|
NO: |
FLUSH |
;очистка |
буфера в в о д а |
от |
оставшихся символов |
||||||
|
JMP OUT |
|
|
|
|
|
|
|
|
|
|
YES: |
ADD |
DX,3 |
;DX - |
на |
н а ч а л о п о д с т р о к и |
"УПОРЯДОЧЕНО" |
|||||
OUT: |
OUTSTR |
;вывод |
о т в е т а |
|
|
|
|
|
|||
|
FINISH |
|
|
|
|
|
|
|
|
|
|
Пример 6
Осуществить посимвольный ввод (использовать только команду INCH) десятичного числа и записать его в переменную N размером в слово.
Предполагается, что число имеет величину от -215 до 216-1 и задано для ввода без ошибок: в нем указаны только цифры, причем не менее одной, перед числом возможен знак + или -. Признаком конца числа считать пробел.
Решение
Сначала введем первый символ и проверим, знак ли это. Если это плюс или знака нет, тогда запоминаем, что это число положительно, а при минусе фиксируем отрицательность числа. Знак числа будет учтен в конце, после ввода всех цифр числа. Если число начинается со знака, тогда вводим следующий символ, чтобы в любом случае уже была введена первая цифра числа.
"ДИАЛОГ-МИФИ•
82 Программирование на языке ассемблера IBM PC Глава 1
Далее по очереди вводим цифры и формируем число по следующей схеме (схеме Горнера). Пусть уже введены первые цифры числа, скажем 3 и 7, и по ним сформировано число 37 и пусть следующей введена цифра 4. Тогда
умножаем предыдущее |
число |
на |
Ш |
и добавляем |
к нему |
новую |
цифру: |
||
37 * 10+4=374, |
Й так |
делаем |
для |
каждой |
новой |
цифры: умножаем |
ранее |
||
полученной чисДО на, 10 и прибавляем эту цифру. |
|
|
|
||||||
щ*кл |
заканчивается, |
когда |
будет |
введен |
признак |
конца |
числа, |
||
% с: пробел. Далее учитываем знак числа: заменяем число на противоположное, если в начале числа был минус,
; а н а л и з знака |
числа |
|
|
|
|
|
|
|
|
|
|||||
SGN: |
MOV |
S I , 1 |
;SI—l |
- |
для |
н е о т р и ц а т е л ь н о г о числа |
|
||||||||
|
INCH AL |
|
|
|
|
|
|
|
|
|
|
|
|||
|
CMP AL, |
|
|
|
|
|
|
|
|
|
|
|
|||
|
DtQl |
|
|
|
|
|
|
|
|
|
|
|
|||
|
CMP |
|
A L , ' - / |
|
|
|
|
|
|
|
|
|
|
||
•.'•..' |
JftEDXGS |
; н е т |
з н а к а |
|
в |
AL ухе е с т ь |
п е р в а я |
цифра |
|||||||
|
MOV |
|
SI «0 |
; S I « 0 |
- |
для |
о т р и ц а т е л ь н о г о |
числа |
|
||||||
DIG1: |
INCH |
|
AL |
|
; п о с л е з н а к а в в е с т и |
первую |
цифру |
|
|||||||
; ввод цифр И формирование модуля |
числа в |
р е г и с т р е АХ |
|||||||||||||
DIGS: SUB |
AL, ' 0 ' |
|
|
|
,>5 |
|
|
|
|
|
|||||
|
MOV |
|
AH/0 |
; А Х : с п е р в а * |
цифра как число размером в слово |
||||||||||
• HOV &Х, I Ф >МйЬжйТель |
|
(основание системы счисления) |
|||||||||||||
' |
:М0У |
C |
F |
L > |
0 |
Щ |
|
С Х |
( с м . |
ниже) |
|
||||
. Ш: • TILCE |
CI. |
|
; в в о д , о ч е р е д н о г о |
символа |
|
|
|
||||||||
•* -у: ••• С |
М |
Р |
' * |
' |
' |
' |
' |
|
|
|
|
|
|
||
|
J% |
02 |
|
|
; пробел |
|
|
конец Bfcoда |
|
|
|
||||
|
&0B. fcWг 0 ' * о ч е р е д н а я |
цифра |
как |
число |
|
|
|||||||||
|
|
|
|
|
|
CPXfAX)t«10*AX |
(DX=0 - |
см . |
у с л о в и е |
з а д а ч и ) |
|||||
; |
.М>Р |
AX;T:X |
; A X : « A X + C L |
|
(CL*CX> |
|
|
|
|
||||||
%; • ' . |
JMP |
|
DI |
|
|
|
|
|
|
|
|
|
|
|
|
; у ч е т |
знака |
числа |
|
|
|
|
|
|
|
|
|
||||
D2: |
CMP |
S I , 1 |
|
|
|
|
|
|
|
|
|
|
|||
|
JE |
D3 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NEG |
|
AX |
|
;6ыл |
минус |
|
- замена |
з н а к а |
|
|
||||
D3: MOV N,АХ
Глава 10
МАССИВЫ. СТРУКТУРЫ
В этой главе рассматриваются способы описания и обработки на ЯА таких составных объектов, как массивы и структуры.
5.1.Об индексах элементов массива
Мы уже знаем, что в ЯА массивы описываются по директивам определения данных с использованием конструкции повторения DUP. Однако кое-что здесь требует уточнения.
Пусть имеется массив X из 30 элементов-слов:
X DW 30 DUP(?)
Как видно, при описании массива указывается количество элементов в нем и их тип, но не указывается, как нумеруются (индексируются) его элементы. Поэтому такому описанию может соответствовать и массив, в котором элементы нумеруются с 0, т. е. Х[0..29], и массив, в котором нумерация начинается с 1, т. е. Х[1..30], и массив с любым другим начальным индексом к, т. е. Х[к..29+к]. Таким образом, автор программы может "накладывать" на массив различные диапазоны изменения индекса. Какой диапазон выбрать? Иногда границы
изменения индекса могут жестко определяться условиями |
задачи |
(например, |
в задаче явно сказано, что элементы нумеруются с 1). |
Но если |
нумерация |
не навязывается извне, тогда лучше выбрать нумерацию с 0. Почему? |
|
|
Чтобы ответить на этот вопрос, рассмотрим, как зависит адрес элемента массива от индекса этого элемента. Пусть мы решили, что элементы массива X нумеруются с к:
X DB 30 DUP(?) ;Х[к .. 29+к]
Тогда верно следующее соотношение:
адрес(Х[д.]) = X+2*(i-k)
или в более общем виде, где явный размер (2) элементов массива завуалирован:
адрес(Х[±]) = Х+(type X ) * ( i - k )
Эта зависимость становится наиболее простой при к=0:
а д р е с ( Х [ i ] ) = X+(type X)*i
Поэтому обычно и считают при программировании на ЯА, что элементы массива нумеруются с 0:
X DW 30 DUP(?) ; Х [ 0 . . 2 9 ]
В дальнейшем именно так мы и будем делать.
"ДИАЛОГ-МИФИ•
84 Программирование на языке ассемблера IBM PC Глава 1
Для многомерных массивов ситуация аналогична. Пусть, к примеру, имеется двумерный массив (матрица) А, в котором N строк и М столбцов (N и М - константы) и все элементы - двойные слова, причем строки нумеруются с kl, а столбцы - с к2:
A DD N DUP(M DUP(?)) |
; A [ k l . . N + ( k l - l ) , k 2 . . M + ( k 2 - l ) ] |
Здесь мы предполагаем, что элементы матрицы размещаются в памяти по строкам: первые М ячеек (двойных слов) занимают элементы первой строки матрицы, следующие М ячеек - элементы второй строки и т. д. Конечно, элементы матрицы можно размещать и по столбцам, но традиционно принято построчное размещение; его мы и будем придерживаться.
При этом предположении зависимость адреса элемента матрицы от индексов элемента выглядит так:
а д р е с ( А [ ± , j ] ) - A+M*(type A ) * ( i - k l ) + ( t y p e A ) * ( j - k 2 )
И здесь наиболее простой вид эта зависимость приобретает при нумерации с О, при kl=0 и к2=0:
а д р е с ( А [ i , j ] ) * A+M*(type A ) * i + ( t y p e A ) * j
5.2.Реализация переменных с индексом
Следующий вопрос, который возникает при работе с массивами, - это как осуществляется доступ к их элементам, как реализуются переменные с индексом. Чтобы ответить на этот вопрос, надо предварительно познакомиться с такой особенностью ЭВМ, как модификация адресов.
5.2.1.Модификация адресов
До сих пор мы рассматривали команды, в которых для операндов из памяти указывались их точные адреса (имена), например: MOV СХ,А. Однако в общем случае в команде вместе с адресом может быть указан в квадратных скобках некоторый регистр, например: MOV СХ,А[ВХ]. Тогда команда будет работать не с указанным в ней адресом А, а с так называемым исполнительным (другое название - эффективным) адресом Аисп, который вычисляется по следующей формуле:
Лисп • (А + [BXJ) mod 2 U ,
где [BX] обозначает содержимое регистра ВХ. Другими словами, прежде чем
выполнить |
команду, |
центральный процессор прибавит к адресу А, указанному |
в команде* |
текущее |
содержимое регистра ВХ, получит некоторый новый адрес |
и именно из ячейки с этим адресом возьмет второй операнд. (Сама команда при этом не меняется, суммирование происходит внутри центрального процессора.) Если в результате сложения получилась слишком большая сумма, то от нее берутся только последние 16 битов, на что и указывает операция mod в приведенной формуле. (Отметим, что если в команде рядом с адресом не указан регистр, то исполнительный адрес считается равным адресу из команды.)
Массивы. Структуры |
85 |
Замена адреса из команды на исполнительный адрес называется модификацией адреса, а регистр, участвующий в модификации, принято называть регистром-мо- дификатором или просто модификатором. Отметим при этом, что в ПК в качестве модификатора можно использовать не любой регистр, а только один из следующих четырех: ВХ, BP, SI или DI.
Возьмем, к примеру, команду ADD A[SI],5. Здесь в роли модификатора выступает регистр SI. Пусть сейчас в нем находится число 100. Тогда Аисп=А+[81]=А+100. Значит, по данной команде число 5 будет прибавлено к числу из ячейки с адресом А+100, а не из ячейки с адресом А. Если же в SI находится величина -2 (OFFFEh), тогда Аисп=А-2 и потому число 5 будет складываться с числом из ячейки с адресом А-2.
Этот пример показывает, что одна и та же команда может работать с разными адресами. Это очень важно, ради этого и вводится модификация адресов. Одним из случаев, где полезна модификация адресов, является индексирование, используемое для реализации переменных с индексом.
5.22.Индексирование
Рассмотрим следующий пример: пусть имеется массив
X DW 100 DUP(?) ; Х [ 0 . . 9 9 ]
и требуется записать в регистр АХ сумму его элементов.
Для нахождения суммы надо сначала в АХ записать 0, а затем в цикле выполнять операцию AX:=AX+X[i] при i от 0 до 99. Поскольку адрес элемента X[i] равен X+2*i, то команда, соответствующая этой операции, должна быть следующей:
ADD AX,X+2*i
Но такая команда запрещена правилами и машинного языка, и ЯА: в любой команде все ее части, в том числе и адрес, должны быть фиксированными, не должны меняться. У нас же адрес меняется вместе с изменением индекса i.
Итак, мы столкнулись со следующей проблемой: по алгоритму наша команда должна работать с разными адресами (как говорят, должна работать с переменным адресом), а правила машинного языка допускают только фиксированный адрес. Именно для устранения этого противоречия и была введена в вычислительные машины модификация адресов, с помощью которой эта проблема решается следующим образом.
Разобьем переменный адрес Х+2 * i на два слагаемых - на постоянное слагаемое X, которое не зависит от индекса i, и на переменное слагаемое 2*i, зависящее от индекса. Постоянное слагаемое записываем в саму команду, а переменное слагаемое заносим в какой-нибудь регистр-модификатор (скажем, в SI) и название этого регистра также записываем в команду в качестве модификатора:
X+2*i |
^ |
||
ADD AX,X[SI] |
SI HFi~l |
||
* |
|
|
I |
1ДИАЛОГ-МИФИ-
86 Программирование на языке ассемблера IBM PC Глава 1
Что получилось? Поскольку регистр-модификатор один и тот же, то такая команда имеет фиксированный вид, т. е. удовлетворяет правилам машинного языка. С другой стороны, команда работает с исполнительным адресом, а он получается сложением адреса X из команды с содержимым (2*i) регистра SI, которое может меняться. Поэтому, меняя значение SI, мы заставим неменяющуюся команду работать с разными адресами. Тем самым удовлетворяются требования как машинного языка, так и алгоритма. Единственное, что осталось сделать, - это правильно менять содержимое регистра SI. Но это уже делается просто: вначале в SI надо заслать 0, а затем увеличивать его значение с шагом 2; в результате наша команда будет работать с адресами X, Х+2, Х+4, ..., Х+198.
Поскольку в данном случае регистр-модификатор используется для хранения индекса (точнее - выражения, зависящего от индекса), то такой регистр называют индексным регистром, а описанный способ получения адреса переменной с индексом - индексированием.
С учетом всего сказанного фрагмент программы нахождения суммы элементов массива X выглядит так:
MOV АХ,0 |
; н а ч а л ь н о е |
значение |
суммы |
|
MOV |
CX,100 |
; с ч е т ч и к цикла |
|
|
MOV |
S I , 0 |
; н а ч а л ь н о е |
значение |
( у д в о е н н о г о ) индекса |
L: ADD |
AX,X[SI] |
;AX:=AX+X[i] |
|
|
ADD |
S I , 2 |
;следующий |
индекс |
|
LOOP |
L |
;цикл 100 |
р а з |
|
5.23.Косвенные ссылки
Рассмотрим еще один случай применения модификации адресов.
Пусть нам надо решить следующую задачу: имеется некоторая ячейка размером в слово, адрес которой нам не известен, но известно, что этот адрес находится в регистре ВХ, и надо записать, скажем, число 300 в эту ячейку:
Если бы мы заранее знали адрес (х) этой ячейки, то наша задача решалась бы командой MOV х,300. Но в момент составления программы мы не знаем этот адрес, а потому и не можем указать его в команде. Что делать? Вспомним, что команды работают с исполнительными адресами, поэтому нам надо взять такой адрес и такой модификатор, чтобы в сумме они давали этот заранее не известный нам адрес. Легко сообразить, что в нашем случае надо взять нулевой адрес и регистр ВХ, поскольку тогда Аисп=0+[ВХ]=0+х=х. Поэтому наша задача решается командой
MOV [ВХ],300 |
|
Особенность используемого |
здесь способа модификации адреса заключается |
в том, что мы, как и прежде, |
представляем адрес в виде суммы двух слагаемых, |
Массивы. Структуры |
87 |
одно из которых записываем в команду, а другое - в регистр, но если ранее у нас оба слагаемых были ненулевыми, то теперь одно слагаемое, которое мы помещаем в команду, нулевое и потому весь адрес "упрятан" в регистре. Получается, что в команде мы указывается лишь место (регистр), где находится адрес. Такой способ задания адреса через промежуточное звено называют косвенной ссылкой или косвенной адресацией.
Отметим попутно, что при косвенной ссылке обычно приходится уточнять размер ячейки, на которую она указывает. Если, к примеру, в ячейку, адрес которой находится в регистре ВХ, надо записать число 0, тогда использовать для этого команду MOV [ВХ],0 нельзя, т. к. в ней непонятны размеры операндов: 0 может быть как байтом, так и словом, да и адрес из ВХ Также может быть адресом как байта, так и слова (в приведенном выше примере такой неоднозначности не было, т. к. число 300 может быть только словом). Поэтому с помощью оператора PTR надо указать, операнды какого размера мы имеем в виду:
MOV |
BYTE |
PTR |
[BX],0 |
;пересылка |
б а й т а |
MOV |
WORD |
PTR |
[ВХ],0 |
;пересылка |
с л о в а |
5.2.4.Модификация по нескольким регистрам
Мы рассмотрели ситуации, когда модификация адресов осуществлялась по одному регистру-модификатору. Однако идею модификации легко обобщить на случай нескольких модификаторов. Для этого надо в командах вместе с адресом указывать несколько таких регистров. В ПК разрешено указывать сразу два модификатора, причем один из них обязательно должен быть регистром ВХ или BP, а другой - регистром SI или DI (модифицировать по парам ВХ и BP или SI и DI нельзя). Возможный пример:
MOV AX,А[ВХ][SI]
В данном случае исполнительный адрес вычисляется по формуле
Лисп = (А + [BX] + [ S I ] ) mod 21 6
Модификация по двум регистрам обычно используется при работе с двумерными массивами. Пусть, к примеру, имеется матрица А размером 10x20:
A DB 10 DUP(20 DUP(?)) ; А [ 0 . . 9 , 0 . . 1 9 ]
и требуется записать в регистр AL количество таких строк дтой матрицы, в которых начальный элемент строки встречается в ней еще раз.
При расположении элементов матрицы в памяти по строкам (гГервые 20 байтов - начатьная строка матрицы, следующие 20 байтов - вторая строка и т. д.) адрес элемента A[i,j] равен A+20*i+j. Для хранения величины 20*i отведем регистр ВХ, а для хранения j - регистр SI. Тогда А[ВХ] - это начальный адрес i-й строки матрицы, a A[BX][SI] - адрес j-ro элемент этой строки.
1ДИАЛОГ-МИФИ-
88 |
Программирование на языке ассемблера IBM PC |
|
|
||||||||
MOV |
AL, О |
|
к о л и ч е с т в о искомых |
с т р о к |
|
||||||
;внешний цикл (по |
строкам) |
|
|
|
|
|
|
|
|
||
HOV |
СХ,10 |
|
;счетчик |
|
внешнего |
цикла |
|
|
|||
HOV |
ВХ,0 |
|
;смещение |
от А |
до |
н а ч а л а |
строки ( 2 0 * i ) |
||||
L: HOV |
АН,А[BX] |
|
;АН - |
начальный |
элемент |
строки |
|
||||
MOV |
DX,CX |
|
; с п а с т и |
CX внешнего |
цикла |
|
|||||
;внутренний цикл |
(по |
столбцам) |
|
|
|
|
|
|
|
|
|
MOV |
СХ,19 |
|
;счетчик |
|
внутреннего |
цикла |
|
||||
MOV |
S I , 0 |
|
;индекс |
элемента |
внутри |
строки |
( j ) |
||||
L I : INC |
S I |
|
; j : = j + l |
|
|
|
|
|
|
|
|
CMP |
А[BX] [ S I ],АН |
; A [ i , j ]=АН? |
|
|
|
|
|
||||
LOOPNE L1 |
|
;цикл, |
пока A f i / j J O A H , |
но не |
более 19 р а з |
||||||
JNE |
L2 |
|
;АН не |
повторился |
—> L2 |
|
|
||||
INC |
AL |
|
; у ч е т |
строки |
|
|
|
|
|
||
;конец |
в н у т р е н н е г о цикла |
|
|
|
|
|
|
|
|
||
L2: MOV |
CX/DX |
|
в о с с т а н о в и т ь CX |
для |
внешнего |
цикла |
|||||
ADD |
BX,20 |
|
;на начало следующей |
строки |
|
||||||
LOOP L |
|
;цикл |
10 |
р а з |
|
|
|
|
|
||
5.2.5.Запись модифицируемых адресов в ЯА
Уточним правила записи модифицируемых адресов в Я А.
Пусть А обозначает адресное выражение, а Е - любое выражение (адресное или константное), тогда в ЯА допустимы следующие три основные формы записи адресов в командах, которые задают следующие исполнительные адреса:
А : |
Аисп=А |
|
|
|
Е[М] : |
Аисп=(Е+[Н]) mod 2 |
1 6 |
(И: |
B X , B P , S I , D I ) |
Е[М1][М2] : |
Аисп=(Е+[М1]+[М2]) |
mod 21 6 |
(His |
ВХ,ВР; Н2: S I , D I ) |
(Замечание: если Е=0, то 0 можно опустить: 0[М] = [М].)
Напомним еще раз, что в ПК в качестве регистра-модификатора можно использовать не любой регистр, а только один из следующих четырех: BX, BP, SI или DI. При модификации только по одному регистру модификатором может быть любой из этих четырех регистров. Однако при модификации по двум регистрам в ПК разрешается указывать не любую пару регистров-модификаторов, а только такую, где один регистр - это ВХ или BP, а другой регистр - SI или DI.
Замечание о регистре BP. Этот регистр используется обычно для работы со стеком, для доступа к его элементам, о чем будет рассказано в гл. 8. Использовать этот регистр для модификации адресов из других участков памяти нельзя (точнее, можно, но особым образом). Поэтому мы пока забудем про этот модификатор, как будто бы его и нет.
Отметим, что модификация адреса не меняет тип адреса: например, если X - имя байтовой переменной, то TYPE X[SI] = BYTE. Если же перед модификатором указано константное выражение (например, 1[ВХ]), то тип такого адреса считается неопределенным.
Массивы. Структуры |
89 |
Помимо трех указанных основных способов записи адресов в ЯА допускаются и другие, являющиеся производными от этих трех. Но прежде чем рассмотреть их, опишем принятые в ЯА соглашения об использовании квадратных скобок при записи операндов команд.
1) Запись в квадратных скобках имени регистра-модификатора (ВХ, BP, SI или DI) эквивалентна выписыванию содержимого этого регистра (тогда как имя регистра без квадратных скобок обозначает сам регистр).
Примеры:
A DW 99
АА DW А |
|
|
|
MOV |
ВХ,АА |
; в ВХ - |
а д р е с А |
MOV |
СХ,(ВХ] |
;СХ:=А |
(СХ:«99) |
MOV |
СХ,БХ |
;СХ:=ВХ |
( С Х : - а д р е с А) |
Отметим, что заключать в квадратные скобки имена регистров, не являющихся модификаторами (АХ, SP, DS, AL и т. п.), нельзя,
2) Любое выражение можно заключить в квадратные скобки, от этого его смысл не изменится (в то же время снятие скобок может изменить смысл).
Примеры:
MOV |
С Х , [ 2 ] |
;= HOV |
СХ,2 |
MOV |
СХ, {А) |
; — MOV СХ,А . |
|
MOV СХ,[А+2[ВХ]) |
MOV |
СХ,А+2[ВХ] |
|
3) Стедующие записи эквивалентны: |
|||
[ Х ] [ У ] = [ х ] + { у ] |
= [х+у] |
|
|
Другими словами, выписывание рядом двух выражений в квадратных, скобках
означает сумму этих выражений. |
|
|
|
Пример: |
' ' |
• : |
'./•• |
MOV CX,[BX][SI] |
; = MQV CX,[BX]t[SX] |
= HOV СХ,[BX+SI] |
|
Так вот, используя эти соглашения вместе со Свойством коммутативности сложения и отталкиваясь от трех основных способов записи адресов в. командах, можно получить новые варианты записи адресов. Например, в каждой из следующих строк указаны эквивалентные формы записи одного и того Же адреса:
А + 1 , [ А + 1 ] , [ А ] + [ 1 ] , [ А ] [ 1 ] , А [ 1 ] , 1 [ A J , [ A ] + L , |
I . . |
|
5 [ S I ] , [ 5 ] [ S I ] , [ 5 ] + [ S I J , [ S J + S ' B [ S I 3 + 5 / |
. ..У |
\ |
A - 2 [ B X ] , [ A - 2 ] + [ B X ] , [ A - 2 + B X J , Д F&X - 2 < |
. Ц BX J - 2 |
, ; V . V . |
|
' |
/ |
- , |
• |
\ |
' • : |
' |
; |
/ ' |
|
|
A [ в х ] [ D I ] , |
A[BX+DI], |
[А+вх+Di], |
A[BX)+[PI-]',, ^ V v ^ . v |
0 [ B X ] [ S I ] , |
[ B X ] [ S I ] , |
[ B X ] + [ S I ] , |
[ B X + S I L ^ T S I N B X ] , . . . |
1ДИАЛОГ-МИФИ-
