Goto... Search.. Hext Change.. Follou Previous 2 глава




mov BX,offset pat2;ВХ=смещение pat2

add BX,sex;ВХ=смещение pat2.sex

mov DL,[BX];DL='M'

mov SI,birth;SI=5 (сомнительная команда)

Записи

Записи, как и структуры, представляют собой шаблоны, накладывае­мые на реальные данные с целью ввдения удобных мнемонических обо­значений отдельных элементов данных. В отличие от структур, дающих имена байтам, словам, двойным словам или целым массивам, в записях определяются строки битов внутри байтов, слов или двойных слов.

Известно, что дата создания файла хранится в каталоге диска в виде 16-битового слова, в котором старшие 7 бит обозначают год (от 1980), следующие 4 бит — месяц и последние 5 бит — день (рис. 2.14).

Биты слова 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00

Год Месяц День

Рис. 2.14. Формат записи даты в каталоге диска.



Глава 2


Основы программирования



 


Эти данные удобно специфицировать с помощью записи filedate, оп­
ределяемой в программе следующим образом: <Й

fdate record year:7, month:4, day:5 pi

Ключевое слово record говорит о том, что имя fdate относится к запи­си, а мнемонические обозначения year, month и day являются произволь­ными именами отдельных битовых полей описываемого слова.

Включение в программу описания шаблона битовых полей позволяет отказаться от утомительного и чреватого ошибками определения «вруч­ную» содержимого полного данного по задаваемым значениям его от­дельных составляющих. Для приведенной выше записи объявления конк­ретных переменных будут выглядеть следующим образом:

fflel fdate <5,6,7> Ше2 fdate <18,12,30> ШеЗ fdate <>

;7 июня 1985г.

;30 декабря 1998г.

;»Пустая» (пока) переменная

Переменная filel будет определена, как число OAC7h, Ше2 — как чис­ло 259Eh, а ШеЗ — как число OOOOU. При необходимости программного заполнения переменной типа fdate можно пользоваться именами ее со­ставляющих, которые трактуются ассемблером, как индексы соответству­ющих битовых полей, отсчитываемые от младшего конца слова. Для при­веденного примера day=0, month=5, a year=9- Однако в системе команд МП 86 практически нет средств работы с битовыми полями. Поэтому про­граммное заполнение придется осуществлять с помощью команд сдвигов и логического сложения:

mov flle3,30
mov AX,12
mov CL, month
shl AX,CL
or ШеЗ, AX
mov AX,18
mov CL, month
shl AX,CL
or ШеЗ, AX

;Помещаем день

;Месяц пока в АХ

;Будем сдвигать на month бит

;Сдвинули месяц в АХ на 5 бит.

;Добавили биты месяца в ШеЗ

;Год пока в АХ

;Будем'сдвигать на year бит

;Сдвинули год в АХ на 9 бит

;Добавили биты года в ШеЗ

В итоге в переменной ШеЗ окажется тот же код 259Е11, что и в пере­менной file 2.

2.5. Способы адресации

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


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

Следует отметить неоднозначность термина «операнд» применительно к программам, написанным на языке ассемблера. Для машинной команды операндами являются те данные (в сущности, двоичные числа), с кото­рыми она имеет дело. Эти данные могут, как уже отмечалось, находиться в регистрах или в памяти. Если же рассматривать команду языка ассембле­ра, то для нее операндами (или, лучше сказать, параметрами) являются те обозначения, которые позволяют сначала транслятору, а потом про­цессору определить местонахождение операндов машинной команды. Так, для команды ассемблера

mov mem, AX

в качестве операндов используется обозначение ячейки памяти mem, a также обозначение регистра АХ. В то же время, для соответствующей ма­шинной команды операндами являются содержимое ячейки памяти и содержимое регистра. Было бы правильнее говорить об операндах машин­ных команд и о параметрах, или аргументах команд языка ассемблера.

По отношению к командам ассемблера было бы правильнее исполь­зовать термин «параметры», оставив за термином «операнд» обозначение тех физических объектов, с которыми имеет дело процессор при выпол­нении машинной команды, однако обычно эти тонкости не принимают в расчет, и говоря об операндах команд языка, понимают в действительно­сти операнды машинных команд.

В архитектуре современных 32-разрядных процессоров Intel предус­мотрены довольно изощренные способы адресации; в МП 86 способов адресации меньше. В настоящем разделе будут описаны режимы адреса­ции, используемые в МП 86.

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

Регистровая адресация. Операнд (байт или слово) находится в регис­тре. Этот способ адресации применим ко всем программно-адресуемым Регистрам процессора.



Глава 2


Основы программирования



 


 


inc СН;Плюс 1 к содержимому СН

push DS;;DS сохраняется в стеке №

xchg ВХ.ВР;ВХ и ВР обмениваются содержимым У

mov ES,AX;Содержимое АХ пересылается в ES ||

Непосредственная адресация. Операнд (байт или слово) указывается в команде и после трансляции поступает в код команды; он может иметь любой смысл (число, адрес, код ASCII), а также быть представлен в виде символического обозначения.

mov AH,40h;Число 40h загружается в АН

mov AL,'*";Код ASCII символа "*" загружается в AL

hit 21h;Команда прерывания с аргументом 2Ш

limit = 528;Число 528 получает обозначение limit

mov CX,limit;Число, обозначенное limit, загружается в СХ

Команда mov, использованная в последнем предложении, имеет два операнда; первый операнд определяется с помощью регистровой адреса­ции, второй — с помощью непосредственной.

Важным применением непосредственной адресации является пере­сылка относительных адресов (смещений). Чтобы указать, что речь идет об относительном адресе данной ячейки, а не об ее содержимом, исполь­зуется описатель onset (смещение):

;Сегмент данных mes db "Урок Г';Сегмент команд mov DX.oflset mes

;Строка символов

;Адрес строки засылается в DX

В приведенном примере относительный адрес строки mes, т.е. рассто­яние в байтах первого байта этой строки от начала сегмента, в котором она находится, заносится в регистр DX.

Прямая адресация памяти. Адресуется память; адрес ячейки памяти (слова или байта) указывается в команде (обычно в символической фор­ме) и поступает в код команды:

;Сегмент данных me ml dw О тет2 db 230;Сегменг команд inc meml mov mov

;Слово памяти содержит О;Байт памяти содержит 230

;Содержимое слова meml увеличивается на 1 DX,meml;Содержимое слова с именем meml загружается в DX AL,mem2;Содержимое байта с именем mem2 загружается в AL

Сравнивая этот пример с предыдущим, мы видим, что указание в команде имени ячейки памяти обозначает, что операндом является со-


держимое этой ячейки; указание имени ячейки с описателем onset — что операндом является адрес ячейки.

Прямая адресация памяти на первой взгляд кажется простой и на­глядной. Если мы хотим обратиться, например, к ячейке meml, мы про­сто указываем ее имя в программе. В действительности, однако, дело об­стоит сложнее. Вспомним, что адрес любой ячейки состоит из двух ком­понентов: сегментного адреса и смещения. Обозначения meml и mem2 в предыдущем примере, очевидно, являются смещениями. Сегментные же адреса хранятся в сегментных регистрах. Однако сегментных регистров че­тыре: DS, ES, CS и SS, Каким образом процессор узнает, из какого реги­стра взять сегментный адрес, и как сообщить ему об этом в программе'

Процессор различает группу кодов, носящих название префиксов. Имеется несколько групп префиксов: повторения, размера адреса, разме­ра операнда, замены сегмента. Здесь нас будут интересовать префиксы замены сегмента.

Команды процессора, обращающиеся к памяти, могут в качестве пер­вого байта своего кода содержать префикс замены сегмента, с помощью которого процессор определяет, из какого сегментного регистра взять сег­ментный адрес. Для сегментного регистра ES код префикса составляет 26h, для SS — 36U, для CS — 2Eh. Если префикс отсутствует, сегментный адрес берется из регистра DS (хотя для него тоже предусмотрен свой префикс).

Если в начале программы с помощью директивы assume указано со­ответствие сегменту данных сегментного регистра DS

assume DS:data

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

Если в директиве assume указано соответствие сегмента данных регистру ES assume ES:data

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

Однако в ряде случаев префикс замены сегмента должен указываться в программе в явной форме. Такая ситуация возникает, например, если Данные расположены в сегменте команд, что типично для резидентных обработчиков прерываний. Для обращения к таким данным можно, ко­нечно, использовать регистр DS, если предварительно настроить его на сегмент команд, но проще выполнить адресацию через регистр CS, кото­рый и так уже настроен должным образом. Если в сегменте команд содер­жится поле данных с именем mem, то команда чтения из этого поля будет выглядеть следующим образом:


Глава 2


Основы программирования



 


 


mov AX,CS:mem

В этом случае транслятор включит в код команды префикс замены для сег­мента CS. Другие примеры команд с заменой сегмента будут приведены ниже.

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

смещениям.

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

mov AX,OB800h mov ES,AX mov byte ptr ES:0,'!' mov byte ptr ES:2,T

;Сегментный адрес видеобуфера;Отправим его в ES

;Огправим символ на 1-е знакоместо экрана;Отправим символ на 2-е знакоместо экрана

Настроив регистр ES на сегментный адрес видеобуфера BSOOh, мы пересылаем код знака «!» сначала по относительному адресу 0 (в самое начало видеобуфера, в байт со смещением 0), а затем на следующее зна­коместо, имеющее смещение 2 (в нечетных байтах видеобуфера хранятся атрибуты символов, т.е. цвет символов и фона под ними). В обеих командах необходимо с помощью обозначения ES: указать сегментный регистр, который используется для адресации памяти. Встретившись с этим обо­значением, транслятор включит в код команды префикс замены сегмен­та, в данном случае код 26U.

В приведенном примере мы снова столкнулись с использованием ат­рибутивного оператора byte ptr, который позволяет в явной форме задать размер операнда. Однако если раньше этот оператор использовался, что­бы извлечь байт из данного, объявленного, как слово, то здесь его назна­чение иное. Транслятор, обрабатывая команду

mov byte ptr ES:0,T

не имеет возможности определить размер операнда-приемника. Разумеет­ся, видеобуфер, как и любая память, состоит из байтов, однако надо ли рассматривать эту память, как последовательность байтов или слов1 Ко­манда без явного задания размера операнда

mov ES:0,T

вызовет ошибку трансляции, так как ассемблер не сможет определить, надо ли транслировать это предложение, как команду пересылки в видео­буфер байта 2Ш, или как команду пересылки слова 00211г.


Между прочим, на первый взгляд может показаться, что в обсуждае-'мой команде достаточно ясно указан размер правого операнда, так как символ (в данном случае "!") всегда занимает один байт. Однако трансля­тор, встретив обозначение "!", сразу же преобразует его в код ASCII этого символа, т.е. в число 21h, и уже не знает, откуда это число произошло и какой размер оно имеет.

Стоит еще отметить, что указание в команде описателя word ptr

'f

{ mov word ptr ES:0,T

не вызовет ошибки трансляции, но приведет к неприятным результатам. В этом случае в видеобуфер будет записано слово 002 Ш, которое заполнит байт 0 видеобуфера кодом 2Ш, а байт 1 кодом ООН. Однако атрибут OOh обозначает черный цвет на черном фоне, и символ на экране виден не будет (хотя и будет записан в видеобуфер).

При желании можно избавиться от необходимости вводить описатель размера операнда. Для этого надо пересылать не непосредственное дан­ное, а содержимое регистра:

mov AL,'!' mov ES:0,AL

Здесь операндом-источником служит регистр AL, размер которого (1 байт) известен, и размер операнда-приемника определять не надо. Разу­меется, команда

mov ES:0,AX

заполнит в видеобуфере не байт, а слово.

Для адресации к видеобуферу в вышеприведенном примере использо­вался сегментный регистр дополнительных данных ES. Это вполне есте­ственно, так как обычно регистр DS служит для обращения к полям дан­ных программы, а регистр ES как раз и предназначен для адресации всего остального. Однако при необходимости можно было воспользоваться для записи в видеобуфер регистром DS:

mov AX,OB800h;Сегментный адрес
mov DS,AX видеобуфера в DS

mov byte ptr DS:0,T;Символ в видеобуфер

Любопытно, что хотя обознбачение DS: здесь необходимо, трансля­тор не включит в код команды префикс замены сегмента, так как коман­да без префикса выполняет адресацию по умолчанию через DS.

Если, однако, по умолчанию бвыполняется адресация через DS, то нельзя ли опустить в последней команде обозначение сегментного регистра1 Нельзя, так как обозначение О5:число указывает, что число является не непосред­ственным операндом, а адресом операнда. Команда (неправильная)

mov 6,10


 

 

Глава 2

должна была бы переслать число 10 в число 6, что, разумеется, лишено смысла и выполнено быть не может. Команда же

mov DS:6,10

пересылает число 10 по относительному адресу 6, что имеет смысл. Таким образом, обозначение сегментного регистра с двоеточием перед операн­дом говорит о том, что операнд является адресом. В дальнейшем мы еще столкнемся с этим важным правилом.

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

Регистровая косвенная (базовая и индексная). Адресуется память (байт или слово). Относительный адрес ячейки памяти находится в регистре, обозначение которого заключается в прямые скобки. В МП 86 косвенная адресация допустима только через регистры ВХ, ВР, SI и DI. При исполь­зовании регистров ВХ или ВР адресацию называют базовой, при исполь­зовании регистров SI или DI — индексной.

Преобразуем приведенный выше пример, чтобы продемонстрировать использование косвенной адресации через регистр.

t^fr

mov AX,OB800h mov ES,AX mov BX,2000 mov byte ptr ES:[BX],T

;Сегментный адрес видеобуфера в ES;Смещение к середине экрана;Символ на экран

Настроив ES, мы засылаем в регистр ВХ требуемое смещение (для разнообразия к середине видеобуфера, который имеет объем точно 4000 байт), и в последней команде засылаем код в видеобуфер с помощью косвенной базовой адресации через пару регистров ES:BX с указанием замены сегмента (ES:).

Если косвенная адресация осуществляется через один из регистров ВХ, SI или DI, то подразумевается сегмент, адресуемый через DS, поэто­му при адресации через этот регистр обозначение DS: можно опустить:

mov AX,OB800h mov DS,AX mov BX,2000 mov byte ptr [BX],T

;Сегментный адрес видеобуфера в DS;Смещение к середине экрана; Символ на экран

Кстати, этот фрагмент немного эффективнее предыдущего в смысле расходования памяти. Из-за отсутствия в коде последней команды пре­фикса замены сегмента он занимает на 1 байт меньше места.

Регистры ВХ, SI и DI в данном применении совершенно равнознач­ны, и с одинаковым.успехом можно воспользоваться любым из них:


 

ы программирования

69

mov DI.2000 mov byte ptr [DI],'!'

;Смещение к середине экрана;Символ на экран

Не так обстоит дело с регистром ВР. Этот регистр специально предназ-1чен для работы со стеком, и при адресации через этот регистр в режимах венной адресации подразумевается сегмент стека; другими словами, в качестве сегментного регистра по умолчанию используется регистр SS.

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

Сравнивая приведенные выше фрагменты программ, можно заметить, что использование базовой адресации, на первый взгляд, снижает'эф­фективность программы, так как требует дополнительной операции — загрузки в базовый регистр требуемого адреса. Действительно, базовая ад­ресация в нашем примере не оправдана — в случае прямого обращения к памяти вместо двух команд

mov mov

ВХ,2000;Смещение к середине экрана

byte ptr ES:[BX),T;Символ на экран

можно использовать одну

mov byte ptr ES:2000,T;Выведем символ в середину экрана

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

Регистровая косвенная адресация со смещением (базовая и индекс­ная). Адресуется память (байт или слово). Относительный адрес операнда определяется, как сумма содержимого регистра ВХ, ВР, SI или DI и ука­занной в команде константы, иногда называемой смещением. Смещение может быть числом или адресом. Так же, как и в случае базовой адреса­ции, при использовании регистров ВХ, SI и DI подразумевается сегмент, адресуемый через DS, а при использовании ВР подразумевается сегмент стека и, соответственно, регистр SS.

Рассмотрим применение косвенной адресации со смещением на при­мере прямого вывода в видеобуфер.

mov AX,OB800h mov ES,AX mov DI, 80*2*24

;Сегментный адрес

видеобуфера в ES

;Смещение к нижней строке экрана



Глава 2


Основы программирования



 


j mov byte ptr ES:[DI],'O*;Символ на экран

mov byte ptr ES:2[DI],'K';3апишем символ в следующую позицию mov byte ptr ES:4[DI],T;3апишем символ в следующую позицию

В этом примере в качестве базового выбран регистр DI; в него зано­сится базовый относительный адрес памяти, в данном случае смещение в видеобуфере к началу последней строки экрана. Модификация этого ад­реса с целью получить смещение по строке экрана осуществляется с по­мощью констант 2 и 4, которые при вычислении процессором исполни­тельного адреса прибавляются к содержимому базового регистра DI.

Иногда можно встретиться с альтернативными обозначениями того же способа адресации, которые допускает ассемблер. Вместо, например, 4[ВХ] можно с таким же успехом написать [ВХ+4], 4+[ВХ] или [ВХ]+4. Такая неоднозначность языка ничего, кроме путаницы, не приносит, однако ее надо иметь в виду, так как с этими обозначениями можно стол­кнуться, например, рассматривая текст деассемблированной программы.

Рассмотрим теперь пример использования базовой адресации со сме­щением при обращении к стеку:

;Основная программа

push DS;В стек загружаются значения

push ES;трех регистров,

push SI передаваемых подпрограмме

call mysub;Вызов подпрограммы mysub,

;использующей эти параметры

;Подпрограмма mysub

mov ВР,5Р;Поместим в ВР текущий адрес вершины стека mov АХ,2[ВР];Читаем в АХ последний параметр (SI) mov ВХ,4[ВР];Читасм в ВХ предыдущий параметр (ES) mov СХ,6[ВР];Читаем в СХ первый параметр (DS)

Здесь продемонстрирован классический прием чтения содержимого стека без извлечения из него этого содержимого. После того, как основ­ная программа сохранила в стеке три параметра, которые потребуются подпрограмме, командой call вызывается подпрограмма mysub. Эта ко­манда сохраняет в стеке адрес возврата (адрес следующего за call предло­жения основной программы) и осуществляет переход на подпрограмму-Состояние стека при входе в подпрограмму приведено на рис. 2.15.

Если бы подпрограмма просто сняла со стека находящиеся там пара­метры, она первым делом изъяла бы из стека адрес возврата, и лишила бы себя возможности вернуться в основную программу (подробнее воп­росы вызова подпрограммы и возврата из нее будут обсуждаться в после­дующих разделах). Поэтому в данном случае вместо команд pop удобнее воспользоваться командами mov. Подпрограмма копирует в ВР содержи­мое SP и использует затем этот адрес в качестве базового, модифицируя его с помощью базовой адресации со смещением.


 

Состояние SPпосле перехода на подпрограмму
Параметры, загруженные в стек основной программой
Исходное состояние SP

Смещения в стеке относительно текущего состояния SP

 

 

 

 

 

 

 

 

 

0 2 4 б .Адрес возврата < ч <
SI
ES
DS
 

Рис. 2.15. Состояние стека после загрузки в него трех параметров и перехода на подпрограмму.

Кстати, мы опять сталкиваемся здесь с той весьма обычной ситуаци­ей, когда программист не имеет возможности обращаться по наглядным символическим адресам, которьк в стеке, естественно, нет, а вынужден определять «вручную» смещения к интересующим его элементам стека. При этом необходимо учесть и алгоритм выполнения команды call, кото­рая, сохраняя в стеке адрес возврата в основную программу, смещает указатель стека еще на одно слово.

В нашем фрагментарном примере мы не рассматриваем вопрос воз­врата в основную программу. Вдумчивый читатель мог также усомниться в правильности или, лучше сказать, в разумности текста подпрограммы. Ведь перенося параметры из стека в регистры общего назначения, подпрог­рамма затирает их исходное содержимое. Если же они не содержали ниче­го нужного, то ими можно было воспользоваться для передачи парамет­ров в подпрограмму, а не связываться с мало наглядными операциями со стеком. Действительно, ради краткости мы опустили операции, практи­чески необходимые в любой подпрограмме — сохранение в стеке (опять в стеке!) тех регистров, которые будут использоваться в подпрограмме. Кста­ти, это относится и к регистру ВР. В реальной подпрограмме эти действия следовало выполнить, что привело бы к изменению смещений при реги­стре ВХ, которые приняли бы значения (с учетом сохранения 4 регист­ров) 10, 12 и 14.

Во всех приведенных выше примерах регистр использовался для хране­ния базового адреса, а смещение, если оно требовалось, указывалось в виде Константы. Возможна и обратная ситуация, когда в качестве смещения выс­тупает адрес массива, а в регистре находится индекс адресуемого элемента в этом массиве. Рассмотрим относительно решгьный пример такого рода

Пусть нам надо заполнить массив из 10000 слов натуральным рядом Чисел. Зарезервируем в сегменте данных место под этот массив, а в сег-



Глава 2


г


Основы программирования



 


 


менте команд организуем цикл занесения в последовательные слова мас­сива ряда нарастающих чисел. Нам придется воспользоваться нескольки­ми новым командами (inc, add и loop), которые в дальнейшем будут рас­смотрены более подробно.

;Сегмент данных array dw;Сегмент команд mov SI,0 mov AX,0 mov CX, 10000 fill: mov array[SIJ,AX inc AX add SI,2 loop fill

;Начальное значение индекса элемента в массиве;Первое число-заполнитель;Число шагов в цикле (всегда в СХ)

;3анесение числа в элемент массива '<•

;Инкремент числа-заполнителя $

;Смещение в массиве к следующему слову ^;

;Возврат на метку fill (CX раз) '•'-

Цикл начинается с команды, помеченной меткой fill (правила обра­зования имен меток такие же, как и для имен полей данных). В этой ко­манде содержимое АХ, поначату равное 0, переносится в ячейку памяти, адрес которой вычисляется, как сумма адреса массива array и содержимо­го индексного регистра SI, в котором в первом шаге цикла тоже 0. В ре­зультате в первое слово массива заносится 0. Далее содержимое регистра АХ увеличивается на 1, содержимое регистра SI — на 2 (из-за того, что массив состоит из слов), и командой loop осуществляется переход на метку fill, после чего тело цикла повторяется при новых значениях регис­тров АХ и SI. Число шагов в цикле, отсчитываемое командой loop, опре­деляется исходным содержимым регистра СХ.

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

[BX][SI] (подразумевается DS:[BX][SI]) [BX][DI] (подразумевается DS:[BX][DI]) [BP][SI] (подразумевается SS:[BP][SI]) [BP][DI] (подразумевается SS:[BP][DI])

Это чрезвычайно распространенный способ адресации, особенно, при работе с массивами. В нем используются два регистра, при этом одним из них должен быть базовый (ВХ или ВР), а другим — индексный (SI или DI). Как правило, в одном из регистров находится адрес массива, а в другом — индекс в нем, при этом совершенно безразлично, в каком что. Транс­формируем предыдущий пример, введя в него более эффективную базо-во-индексную адресацию.

;Сегмент данных array dw 10000


 

;Сегмент команд mov BX.offset array mov SI,0

;Базовый адрес массива в

;базовом регистре

;Начальное значение индекса

;элемента в массиве

mov mov mov inc add loop
AX,0 CX, 10000 [BX][SI],AX AX SI,2 fill

;Первое число-заполнитель



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2016-02-16 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: