Лекция №3 Основные определения данных, констант. Режимы адресации
Основные определения данных, констант.
Для заполнения последовательных байтов, слов или двойных слов памяти, а также для резервирования памяти служат директивы ассемблера (псевдооператоры) DB, DW и DD, а для резервирования массивов - директива DUP:
count dw 1000 ; В слово с именем count помещается число 1000
coeffs dw 5,12000,0,168 ; Указанными числами заполняются 4
; последовательные слова памяти.
; Первому слову дается имя coeffs
mask db OFFh ; В байт именем mask помещается 16-ричное
; число FFh
mes db --Внимание!--' ; Строка байтов с именем mes заполняется
; указанным текстом
addr dw mes ; В слово с именем addr помещается смещение
; первого байта строки mes
addrd dd myproc ; В двойное слово с именем addrd помещается
; двухсловный адрес процедуры myproc (в
; первое слово относительный адрес, во
; второе – сегментный адрес)
area dw 128 dup (?) ; Резервируется область памяти объемом 128
; слов
testmes db 100 dup ('#') ; Строка с именем testmes заполняется кодом
; символа #
array dw 1024 dup (256) ; Массив из 1024 слов заполняется числом 256
Для определения констант служат директива EQU и знак равенства:
kilo equ 1024 ; Числу 1024 присваивается символическое имя kilo offs=80*2*12+40*2 ; Константа offs получает значение, равное
; результату вычисления указанного выражения
length=OFFFFh ; Числу Ft-"FFh=65535 присваивается
; символическое имя length
Отличие директивы equ от знака равенства заключается в том, что директива equ присваивает символическим именам значения "раз и навсегда", а при использовании знака равенства значения констант можно изменять:
counter=0 ; Символическое имя counter принимает значение О counter=counter+l ; Символическое имя counter принимает значение 1
Для ссылок на текущую ячейку используется обозначение счетчика текущего
адреса $:
mes db 'Ждите'
mes_1en=$-mes
В этом примере константа mes—len получает значение длины строки mes (в данном случае 5 байтов), которая вычисляется как разность значения счетчика текущего адреса после определения строки и ее начального адреса mes.
Данные, описанные в программе, должны участвовать в операциях в соответствии со своими описаниями. Ассемблер фиксирует ошибку, если, например, данное, описанное как байт, участвует в операции со словом. Во многих случаях, однако, требуются как раз такие операции. Для их реализации предусмотрен атрибутивный оператор PTR:
bits dw OF5E9h ; Данное описано как слово
mov AX,bits ; Операция соответствует описанию
mov BH.byte ptr bits ; Из слова bits забирается младший
; байт (число E9h)
mov CL.byte ptr bits+1 ; Из слова bits забирается старший
; байт (число F5h)
addr dd myproc ; Данное описано как двойное слово
mov BX.word ptr addr ; Забираем младшее слово(относительный
; адрес myprog)
mov ES.word ptr addr+2 ; Забираем старшее слово(сегментный
; адрес myprog)
2. Режимы адресации
Режимом, или способом адресации называют процедуру нахождения операнда. Различают следующие режимы адресации.
2.1. Регистровый. Операнд (байт или слово) находится в регистре. Этот способ адресации применим ко всем программно- адресуемым регистрам процессора.
inc СХ ; Увеличение на 1 содержимого АХ
push OS ; Сегментный адрес сохраняется в стеке
xchg ВХ.ВР ; Регистры ВХ и ВР обмениваются содержимым
mov ES.AX ; Содержимое АХ пересылается в ES
2.2. Непосредственный. Операнд, (байт или слово) указывается в команде; он может иметь любой смысл (число, адрес, код ASCII), а также быть представлен в виде символического обозначения.
mov AH,40h ; Число 40h загружается в АН
mov AL,'*' ; Код ASCII символа * загружается в AL
int 21h ; Команда прерывания типа 21h
limit equ 523 ; Число 528 получает обозначение limit
mov CX,limit ; Число, обозначенное limit, загружается
; в CX
Важным применением непосредственной адресации является пересылка относительных адресов (смещений). Чтобы указать, что речь идет об относительном адресе данной ячейки, а не об ее содержимом, используется описатель OFFSET:
; Сегмент данных
mes db 'Ждите' ; Отрока символов
; Сегмент команд
mov DX,offset mes ; Адрес строки засылается в ОХ
В приведенном примере относительный адрес строки mes, т.е. расстояние в байтах первого байта этой строки от начала сегмента; в котором она находится, заносится в регистр DX.
2.3. Прямой. Адресуется память; адрес ячейки памяти (слова или байта) указывается в команде:
;Сегмент данных
mem dw 0 ; Резервируется слово памяти (и в него
; засылается 0)
;Сегмент команд
Inc mem ; Содержимое этого слова увеличивается на 1
mov DX.mem ; Содержимое слова с именем mem загружается
; в регистр DX
Строго говоря, процессору следует передать информацию о том, с помощью какого сегментного регистра определять адрес:
inc DS:mem
mov OX,DS:mem
Однако, как уже отмечалось, по умолчанию все смещения вычисляются относительно DS, поэтому в данном случае это указание сегментного регистра избыточно. В тех же случаях, когда рассматриваемая ячейка находится в сегменте, адресуемом через какой-либо другой сегментный регистр (ES, CS или SS), указание сегментного регистра является обязательным:
Inc ES:meml
Часто бывает нужно обращаться к памяти по известному абсолютному адресу. В этом случае указание сегментного регистра обязательно:
mov AL,DS:17h ; Загрузка AL из ячейки с адресом 17h
; относительно DS
mov BX,ES:2Ch ; Загрузка ВХ из ячейки с адресом 2Сh
; относительно ES
При обращении по абсолютным адресам константа, определяющая адрес, может быть заключена в квадратные скобки. Приведенные ниже команды эквивалентны предыдущим:
mov AL,DS:[17h]
mov BX,ES:[2Ch]
Следует подчеркнуть, что при любом обращении к памяти процессор обязательно использует один из сегментных регистров, Перед выполнением команды обращения к памяти в используемый сегментный регистр следует заслать требуемый сегментный адрес. Пусть, например, мы хотим прочитать код символа, изображаемого в настоящий в первой позиции экрана. Известно, что текстовый видеобуфер начинается с адреса B8OOOh. Для того, чтобы настроить на этот адрес сегментный регистр, в него следует загрузить число, характеризующее номер параграфа, с которого начинается видеобуфер, т.е. B8000h/16=B800h:
mov AX,OB800h ; Сегментный адрес видеобуфера
mov ES.AX ; отправим в ES
mov AL,ES:[0] ; Прочитаем первый байт видеобуфера
2.4. Регистровый косвенный (базовый или индексный). Адресуется память (байт или слово). Относительный адрес операнда находится в регистрах ВХ или ВР (базовая адресация) или в регистрах SI или DI (индексная адресация). При использовании регистров ВХ, SI и DI подразумевается сегмент, адресуемый через DS; при использовании ВР подразумевается сегмент стека и, соответственно, регистр SS. Допускается замена сегмента. Обозначение этого способа адресации:
[ВХ](подразумевается DS:[BX])
[ВР](подразумевается SS:[BP])
[Sl](подразумевается DS:[SI])
[DI](подразумевается DS:[DI])
Регистровый косвенный способ адресации удобно использовать в тех случаях, когда к некоторой ячейке памяти приходится обращаться многократно:
mov SI,offset celts ; Относительный адрес ячейки cells
; загружается в SI
mov AX,[SI] ; Содержимое ячейки cells ;
; загружается в AX
inc [SI] ; инкремент содержимого ячейки
; cells
mov BX,[SI] ; новое содержимое ячейки cells ;
; загружается в BX
2.5. Регистровый косвенный со смещением (базовый или индексный). Адресуется память (байт или слово). Относительный адрес операнда определяется как сумма содержимого регистра BX, BP, SI или DI и указанной в команде константы, называемой смещением. Смещение может быть числом или адресом. При использовании регистров BX, SI и DI подразумевается сегмент, адресуемый через DS; при использовании BP подразумевается сегмент стека – регистр SS. Допускается замена сегмента. Обозначение этого способа адресации:
смещение [BX] (подразумевается DS: смещение [BX])
смещение [BP] (подразумевается SS: смещение [BP])
смещение [SI] (подразумевается DS: смещение [SI])
смещение [DI] (подразумевается DS: смещение [DI])
Допустимы также обозначения (со всеми регистрами) вида:
[BX]+ смещение
[BX+ смещение]
Пусть в сегмента данных определен массив из 10 чисел:
array db 0,10,20,30,40,50,60,70,80,90