Примеры команд с различной адресацией операндов
В командах на Ассемблере результат всегда пересылается по адресу первого операнда.
1) Регистровая
MOV AX, BX ; (BX) ® AX (содержимое ВХ по адресу АХ переносится)
Машинный формат: 1001 0011 1100 0011
“код операции” 100100
“d” = 1
“w” = 1
“mod” = 11
“reg” = 000
“r/m” = 011
2) Непосредственная
MOV AX, 25; 25 ® AX
CONST EQU 34h; именованная константа CONST
MOV AX, CONST; 34h ® AX
С помощью EQUопределяются 16-тиричные константы.
3) Прямая
Если известен адрес памяти, начиная с которого размещается операнд, то в команде можно непосредственно указать этот адрес.
MOV AX, ES : 0001;
ES – регистр сегмента данных (дополнительный сегмент данных), 0001 – смещение внутри сегмента.
!Содержимое двух байтов, начиная с адреса (ES) + 0001 пересылаются в AX - ((ES) + 0001) ®AX.
Прямая адресация может быть записана с помощью символического имени, которое предварительно поставлено в соответствие некоторому адресу памяти, с помощью специальной директивы определения памяти, например: DB – байт,
DW – слово,
DD – двойное слово.
Если в сегменте ES содержится директива Var_p DW, тогда по команде
MOV AX, ES : Var_p; ((ES) + Var_p) ®AX.
Например, если команда имеет вид (данные в DS):
MOV AX, Var_p;((DS) + Var_p) ®AX.
4) Косвенно-регистровая
Данный вид адресации отличается от регистровой адресации тем, что в регистре содержится не сам операнд, а адрес области памяти, в которой операнд содержится.
MOV AX, [SI];
Предварительно в SI должен быть записан адрес некоторой команды.
Могут использоваться регистры:
SI, DI, BX, BP, EAX. EBX, ECX, EDX, EBP, ESI, EDI.
Не могут использоваться: AX, CX, DX, SP, ESP.
Физический адрес будет получаться ((DS)+(SI))->AX. _ - смещ. на 4 разряда влево
5) По базе со смещением
MOV AX, [BX]+2; ((DS) + (BX) + 2) ®AX.
º MOV AX, [BX + 2];
º MOV AX, 2[BX];
MOV AX, [BP + 4]; ((SS) + (BP) + 4) ®AX.
6) Прямая с индексированием
MOV AX, MAS[SI] ; ((DS) + (SI) + MAS) ®AX
MAS – адрес в области памяти. С помощью этой адресации можно работать с одномерными
Массивами (и со структурами). Символическое имя определяет начало массива, а переход от одного элемента к другому осуществляется с помощью содержимого индексного регистра. Если работаем с байтами, то содержимое отличается на 1, со словами – на 2, с дв. словами – на 4.
7) По базе с индексированием
MOV AX, Arr[BX][DI] ; ((DS) + (BX) + (DI) + Arr) ®AX.
Эта адресация используется для работы с двумерными массивами.
Символическое имя определяет начало массива, с помощью базового регистра осуществляется переход от одной строки матрицы к другой, а с помощью индексного регистра - переход от
одного элемента к другому внутри строки. Также для работы с массивами структур.
29) Команды пересылки, особенности их использования.
Особенности использования команд пересылки
1. Нельзя пересылать информацию из одной области памяти в другую;
2. Нельзя пересылать информацию из одного сегментного регистра в другой. Если необходимо это сделать, надо воспользоваться в качестве промежуточного регистр общего назначения или стек.
3. Нельзя пересылать непосредственный операнд в сегментный регистр, но если такая необходимость возникает, то нужно использовать в качестве промежуточного один из регистров общего назначения.
MOV DX, 100h
MOV DS, DX
4. Нельзя изменять командой MOV содержимое регистра CS.
5. Данные в памяти хранятся в «перевернутом» виде, а в регистрах
в «нормальном» виде, и команда пересылки учитывает это,
например,R DW 1234h
В байте с адресом R будет 34h, в байте с адресом R+1 будет 12h.
MOV AX, R ;12h ® AH, 34h ® AL.
6. Размер передаваемых данных определяется типом операндов в команде.
X DB ?; Х - адрес одного байта в памяти.
Y DW ?; Y определяет поле в 2 байта в памяти.
MOV X, 0; очищение одного байта в памяти.
MOV Y, 0; очищение двух байтов в памяти.
MOV AX, 0 ; очищение двух байтов регистра
MOV [SI], 0; сообщение об ошибке.
В последнем случае необходимо использовать специальный оператор PTR.
<тип> PTR <выражение (адресное, константное)>
Выражение может быть константным или адресным, а тип это:
BYTE, WORD, DWORD и т.д.
byte PTR 0 ;0 воспринимается как байт
word PTR 0 ;0 воспринимается как слово
byte PTR op1 ;один байт в памяти начиная с этого адреса
MOV byte PTR [SI], 0;
º MOV [SI], byte PTR 0;
ºMOV [SI], word PTR 0; 0® ((DS) +(SI))
7. Если тип обоих операндов в команде определяется, то эти типы должны соответствовать друг другу.
MOV AH, 500; сообщение об ошибке, 500 в байт не вмещается.
MOV AX, X; ошибка, Х – 1байт, АХ – 2 байта.
MOV AL, R; ошибка, R – 2 байта, AL – 1 байт
MOV AL, byte PTR R; (AL) = 34h
MOV AL, byte PTR R+1; (AL) = 12h
К командам пересылки относят команду обмена значений операндов.
XCHG OP1, OP2; r«r Ú r«m
MOV AX, 10h;
MOV BX, 20h;
XCHG AX, BX; (AX) = 20h, (BX) = 10h
Для перестановки значений байтов внутри регистра используют BSWOP.
(EAX) = 12345678h
BSWOP EAX; (EAX) = 78563412h
К командам пересылки относят:
Команды конвертирования:
CBW ; безадресная команда, (AL) ® AX : конвертирует байт в слово.
CWD ;( AX) ® DX:AX; конвертирует слово в дв. слово
CWE ; ( AX) ® EAX (для i386 и выше)
CDF ; (EAX) ® EDX:EAX (для i386 и выше)
Команды условной пересылки CMOVxx
CMOVL AL, BL; если (AL) < (BL), то (BL) ® (AL)
Загрузка адреса.
LEA OP1, OP2; вычисляет адрес OP2 и пересылает первому операнду, который может быть только регистром.
LEA BX, M[DX][DI]
13) Понятие команды и директивы в Ассемблере, формат команды и директивы.
Команды преобразуются в машинные коды, реализующие алгоритм решения задачи. Директивы описывают, каким образом необходимо выполнять ассемблирование и объединение модулей. Они описывают форматы данных, выделяемые области памяти для программ и т.д.
Команда на Ассемблере состоит из четырех полей (п. имени, п. операции, п. операнда, п. комментария):
[<имя>[:]] <код операции> [<операнды>] [;комментарии]
Поля отделяют друг от друга хотя бы одним пробелом. В квадратных скобках указаны необязательные поля, все поля, кроме <код операции>, могут отсутствовать. <имя> - символическое имя Ассемблера. Имя используется в качестве метки для обращения к этой команде, передачи управления на данную команду. [:] после имени означает, что метка является внутренней, т.е. управление на нее можно передать только из сегмента внутри которого она находится. Код операции определяет какое действие должен выполнить процессор. Поле <операнды> содержит адреса данных, или данные, участвующие в операции, а также место расположения результатов операции. Операндов может быть от 1 до 3, они отделяются друг от друга запятой.
Комментарии отделяются кроме пробела еще и ";" и могут занимать всю строку или часть строки.
Например:
JMP M1
;команда безусловной передачи управления на команду с меткой M1.
------------/-------/------------
M1: MOV AX, BX
;пересылка содержимого регистраBXв регистрAX.
В комментарии будем записывать в виде (BX) AX
-----------/--------/------------
Директива, как и команда, состоит из четырех полей:
[<имя>] <код псевдооперации> <операнды> [;комментарии]
Здесь <имя> - символическое имя Ассемблера,
<код псевдооперации> - определяет назначение директивы.
Операндов может быть различное количество и для одной директивы.
Например:
M1 DB 1, 0, 1, 0, 1 ;директива DB определяет 5 байтов памяти и заполняет их 0 или 1 соответственно, адрес первого байта – М1.
M2 DB ?,?,?; директива DBопределяет три байта памяти ничем их не заполняя, адрес первого – M2.
Proc ; директива начала процедуры,
endp; директива конца процедуры,
Segment ; директива начала сегмента,
ends ; директива конца сегмента.
18) Организация сегмента кодов, директивы SEGMENT и ASSUME.
Обычно программа на Ассемблере состоит из трех сегментов: сегмент стека, сегмент данных, сегмент кода.
; сегмент стека
Sseg Segment…
-----/-------
Sseg ends
; сегмент данных
Dseg Segment…
-----/-------
Dseg end
; сегмент кода
Cseg Segment…
-----/-------
Cseg end
end start
start определяет точку входа в программу, т.е. команду, с которой начинается выполнение.
Каждый сегмент начинается директивой начала сегмента - Segment и заканчивается директивой конца сегмента - Ends, в операндах директивы Segment содержится информация о назначении сегмента.
В кодовом сегменте специальная директива….
ASSUME SS:SSeg, DS:DSeg, CS:CSeg, ES:DSeg;
на DSeg ссылаются и DS, и ES.
Кодовый сегмент оформляется как процедура, это может быть одна процедура или несколько оследовательных процедур, или несколько вложенных процедур. Директива ASSUME сразу после директивы кодового сегмента.
Структура кодового сегмента с использованием двух вложенных процедур выглядит следующим образом:
Cseg Segment…
ASSUME SS:SSeg, DS:DSeg, CS:CSeg, CS:DSeg
pr1 Proc
--------/--------
pr2 Proc
-------/-----
pr2 endp
-------/-----
pr1 endp
Cseg ends
В сегменте стека выделяется место под стек.
В сегменте данных описываются данные, используемые в программе, выделяется место под промежуточные и окончательные результаты.
Кодовый сегмент содержит программу решения поставленной задачи.
Директива сегмента:
Общий вид
<имя> Segment <ReadOnly> <выравнивание> <тип> <размер> <’класс’>
Любой из операндов может отсутствовать.
1) Если есть <ReadOnly>, то будет выведено сообщение об ошибке при попытке записи в сегмент.
2) Операнд <выравнивание> определяет адрес начала сегмента.
• BYTE - адрес начала сегмента может быть любым,
• WORD - адрес начала сегмента кратен 2,
• DWORD - адрес начала сегмента кратен 4,
• Para - адрес начала сегмента кратен 16 – (по умолчанию),
Page - адрес начала сегмента кратен 256.
3) <тип> определяет тип объединения сегментов.
Значение stack указывается в сегменте стека, для остальных сегментов – public. Если такой параметр присутствует, то все сегменты с одним именем и различными классами объединяются в один последовательно в порядке их записи.
Значение ‘Common’ говорит, что сегменты с одним именем объединены, но не последовательно, а с одного и того же адреса так, что общий размер сегмента будет равен не сумме, а максимуму из них.
Значение IT <выражение> - указывает на то, что сегмент должен располагаться по фиксированному абсолютному адресу, определенному операндом <выражение>,
Значение ‘Private’ означает, что этот сегмент ни с каким другим объединяться не должен.
4) <разрядность> use 16 – сегмент до 64 Кб,
use 32 – сегмент до 4 ГБ
5) ‘<класс>’ – с одинаковым классом сегменты располагаются в исполняемом файле последовательно друг за другом.
9) Структура программы на ассемблере с использованием стандартных директив сегментации.
Ассемблер – это язык программирования низкого уровня и программа, написанная на Ассемблере, должна пройти три этапа обработки на компьютере, как и программа, написанная на любом другом языке программирования.
I этап - преобразование исходного модуля в объектный – ассемблирование. Исходных модулей может быть 1 или несколько.
II этап - с помощью программы редактора связей объектные модули объединяются в загрузочный, исполняемый модуль.
III этап – выполнение программы.
Исходный файл на Ассемблере состоит из команд и директив. Команды преобразуются в машинные коды, реализующие алгоритм решения задачи. Директивы описывают, каким образом необходимо выполнять ассемблирование и объединение модулей. Они описывают форматы данных, выделяемые области памяти для программ и т.д.
Исходный модуль на Ассемблере (.asm) – последовательность строк, команд, директив и комментариев.
Программа, оформленная с помощью стандартных директив сегментации , обычно состоит из трех сегментов: сегмент стека, сегмент данных, сегмент кода.
; сегмент стека
Sseg Segment…
-----/-------
Sseg ends
; сегмент данных
Dseg Segment…
-----/-------
Dseg end
; сегмент кода
Cseg Segment…
-----/-------
Cseg end
end start
start определяет точку входа в программу, т.е. команду, с которой начинается выполнение.
Каждый сегмент начинается директивой начала сегмента - Segment и заканчивается директивой конца сегмента - Ends, в операндах директивы Segment содержится информация о назначении сегмента.
В кодовом сегменте специальная директива….
ASSUME SS:SSeg, DS:DSeg, CS:CSeg, ES:DSeg;
на DSeg ссылаются и DS, и ES.
Кодовый сегмент оформляется как процедура, это может быть одна процедура или несколько оследовательных процедур, или несколько вложенных процедур. Директива ASSUME сразу после директивы кодового сегмента.
В сегменте стека выделяется место под сегмент стека, определяется его размер. В сегменте данных описываются исходные данные, выделяется место для конечных и промежуточных результатов. Кодовый сегмент содержит программу, оформяется в виде одной процедуры, нескольких последовательных или вложенных процедур.
Структура кодового сегмента с использованием двух вложенных процедур выглядит следующим образом:
Cseg Segment…
ASSUME SS:SSeg, DS:DSeg, CS:CSeg, CS:DSeg
pr1 Proc
--------/--------
pr2 Proc
-------/-----
pr2 endp
-------/-----
pr1 endp
Cseg ends
В сегменте стека выделяется место под стек.
В сегменте данных описываются данные, используемые в программе, выделяется место под промежуточные и окончательные результаты.
Кодовый сегмент содержит программу решения поставленной задачи.
; Prim1.ASM
; сегмент стека
Sseg Segment…
DB 256 DUP(?)
Sseg ends
; сегмент даннх
Dseg Segment…
X DB ‘A’
Y DB ‘B’
Z DB ‘C’
Dseg ends
;
Cseg Segment…
ASSUME SS:SSeg, DS:DSeg, CS:CSeg
Start Proc FAR
Push DS
Push AX
MOV DX, DSeg
MOV DS, DX
CALL Main
Ret
Start endp
Main Proc NEAR
ADD AL, X
MOV AX, Y
--------/------
Ret
Main endp
Cseg ends
end Start
• Строки 1, 5, 11 – это комментарии.
• Кодовый сегмент содержит две последовательные процедуры. Первая процедура – внешняя, о б этом говорит параметр FAR.
• Строки 15 -18 – реализуют связь с операционной системой и определяют адрес начала сегмента данных.
• Строка 19 – это обращение к внутренней процедуре Main, строка 20, команда Ret – возврат в ОС.
• Main – внутренняя процедура, о чем говорит параметр NEAR в директиве начала процедуры Proc.
• Директива end имеет параметр Start, определяющий точку входа в программу, т.е. команду, с которой должно начинаться выполнение программы.
• Внутренняя процедура – это процедура, к которой можно обратиться только из того сегмента, в котором она содержится. К внешней процедуре можно обратиться из любого сегмента. По умолчанию (если в директиве начала процедуры параметр отсутствует) процедура является внутренней.
17) Сегмент стека, организация работы со стеком, команды для работы со стеком, команды прерывания.
В сегменте стека выделяется место под сегмент стека, определяется его размер.
Адрес начала сегмента стека определяется автоматически ОС с помощью регистра SS, а указатель на вершину стека – это регистр указателей SP (ESP). Cтек организован таким образом, что при добавлении элементов в стек, содержимое указателя стека уменьшается. Стек растет вниз от максимального значения, хранящегося в SS (растет вниз головой). При добавлении в стек адреса уменьшаются. Такая организация необходима при использовании модели памяти flat. В этом случае программа размещается, начиная с младших адресов, а стек размещается в старших адресах
Стек используется для временного хранения данных, для организации работы с подпрограммами, в том числе и рекурсивными, для передачи параметров подпрограммам, размещения локальных параметров и т.д.
Для того, чтобы стек можно было использовать для хранения и фактических и локальных параметров, после передачи фактических параметров значение указателя на вершину стека можно сохранить в регистре BP и тогда к глобальным параметрам можно обращаться, используя конструкцию
BP - k, а к локальным - BP + n, где k, и n - определяются количеством параметров и их длиной.