Команды процессора, используемые в лабораторной работе
· MOV– команда передачи данных. Пересылает один элемент данных из регистра в регистр, из регистра в память, из памяти в регистр, выполняет загрузку данных в регистр или память.
Оба операнда должны быть одного и того же размера - байт, слово или двойное слово.
Нельзя выполнять пересылку данных с помощью MOV из одной переменной в другую, из одного сегментного регистра в другой. Кроме того, нельзя помещать в сегментный регистр непосредственный операнд - эти операции выполняются двумя командами MOV (из сегментного регистра в обычный и уже из него в другой сегментный).
· ADD –складывает содержимого операнда-источника и операнда приемника и помещает результат в операнд-приемник.
· SUB – вычитает содержимое операнда-источника из содержимого операнда-приемника и возвращает результат в операнд-приемник.
· INC –добавляет 1 к содержимому регистра или ячейки памяти, указанных в качестве операнда.
· DEC –вычитает 1 из содержимого регистра или ячейки памяти.
· MUL –производит перемножение без знака содержимого регистра АХ или АL с содержимым указанного операнда. При перемножении байтов 16-тиразрядный результат помещается в регистры AH (старший байт) и AL (младший байт), при перемножении слов в регистры DX (старшее слово) и AX (младшее слово). Команда не позволяет использовать в качестве операнда непосредственное значение.
· IMUL –выполняет перемножение чисел со знаком. Работает аналогично команде MUL.
· DIV –делит без знака содержимое регистра AX (при делении на байт) или регистров DX и AX (при делении на 16-разрядное слово) на указанный в команде операнд. В первом случае частное помещается в регистр AL, остаток – в регистр АН. Во втором случае частное помещается в регистр АХ, а остаток – в регистр DX.
· IDIV – предназначена для деления чисел со знаком. Работает аналогично команде DIV.
Директивы определения данных:
Псевдокоманда – директива ассемблера, которая приводит к включению данных или кода в программу, хотя сама она никакой команде процессора не соответствует.
Директивы определения переменных
– указывают ассемблеру, что в соответствующем месте программы располагается переменная;
– определяют тип переменной (байт, слово, вещественное число и т.д.);
– задают начальное значение переменной и ставят в соответствие переменной метку, которая будет использоваться для обращения к этим данным.
Ассемблер обеспечивает два способа резервирования данных: через указание длины данных и по их содержимому. Формат определения данных:
[имя] Dn выражение,
где n – задает тип данных. Так DB – определить байт, DW – определить слово (2байта), DD – определить двойное слово (4 байта), DF – определить 6 байт, DQ – определить учетверенное слово (8 байт), DT– определить 10 байт.
Примеры определения данных:
А1 DB ? – байт с именем А1 принимает неопределенное значение,
COUNT DW 970 – слово с именем COUNT принимает значение 970,
MASKA DB 0FFH – байт с именем MASKA принимает значение FF в шестнадцатеричном коде,
MESSG DB ‘message’ – строка байт, заполненная текстом,
ADDR DW MESSG – в слово с именем ADDR помещается смещение первого байта строки MESSG,
ADDR1 DD MYPROC – в двойное слово с именем ADDR1 помещается адрес процедуры MYPROC,
TABL DW 128 DUP(?) – под переменную TABL резервируется128 неопределенных слов,
KILO EQU 10 – KILO резервируется как значение 10
TABL1 DB KILO DUP(’’) – под переменную TABL1 резервируется 10 байт, содержащих символ’’,
DESB DT ? – под переменную DESB, резервируется10 байт,
OFFS EQU 67+8 – OFFS резервируется как значение 67+8
MASN EQU $- MESSG – MASN определяется значением разности текущего адреса и смещения первого байта строки MESSG
ARRAY DB 6,2,4,1,3 – определение массива символов с именем ARRAY,
BITS DW 0F5E9H – слово с именем BITS принимает значение BITS 0F5E9H в шестнадцатеричном коде,
MEM=9 – значение 9 обозначается как MEM
EXE и COM программы. Программы, выполняемые под управлением MS–DOS, могут принадлежать к одному из двух типов, которым соответствуют расширения имен программных файлов .COM и .EXE. Основное различие этих типов программ заключается в том, что программы типа .COM состоят из единственного сегмента, в котором размещаются и программа, и данные, и стек, а программы типа .EXE состоят из отдельных сегментов для программы, данных и стека. Размер программы типа COM не может превышать максимального размера сегмента, а именно 64 Кбайт, размер же программы типа EXE ограничен только размером памяти.
Структура типичной EXE-программы на ассемблере, подготовленной для ассемблера MASM, выглядит следующим образом.
title ; Программа типа .EXE
data segment ; Сегмент данных
string db «строка данных»,»$»
…
data ends ; Конец сегмента данных
cseg segment ‘code’; Сегмент программы.
assume CS :cseg, DS:data, SS:stack; ES:data
myproc proc
mov AX,data ; Указание на начало сегмента данных
Mov DS,AX
… ; Текст программы.
mov AH,4Ch ; Выход из программы
int 21h; в DOS.
myproc endp;
cseg ends; Конец сегмента программы.
Stacksegment stack ‘stack’; Организация
dw 128 dup (0); сегмента
stack ends; стека.
end myproc ; Конец программы
Следует заметить, что транслятор MASM различает прописные и строчные буквы только при использовании специальных опций при вызове ассемблера. В приведенном тексте выделены ключевые слова и обязательные команды или фрагменты команд.
Рассмотрим структуру программы. Оператор title позволяет следующий за ним текст вывести во все страницы листинга программы в качестве заголовка. Комментарии указываются после знака «;».
Программа состоит из трех сегментов: программного cseg, сегмента данных data и сегмента стека stack. Имена сегментам даются произвольно. Каждый сегмент открывается оператором segment и закрывается оператором ends. Перед обоими операторами должно стоять имя сегмента. Порядок описания сегментов в большинстве случаев значения не имеет, но предпочтительнее данные, используемые в программе, располагать перед текстом программы.
Слова ‘code’ и ‘stack’ указывают на класс сегментов. Сегменты, принадлежащие одному классу, загружаются в память рядом. Когда в памяти используется один сегмент данного класса, этот указатель не обязателен, но для программы – компоновщика LINK необходимо указать класс ‘code’.
Текст сегмента данных в этом примере начинается с одной из типичных команд работы с данными. Команда
String db “строка данных”,”$”
определяет строку, значение которой приведено в кавычках, знак доллара необходим для указания конца строки. По этой команде в памяти выделяется место и в эту область заносится текст «строка данных».
Текст программного сегмента начинается с обязательного оператора assume, который позволяет транслятору сопоставить сегментные регистры и символические имена сегментов.
Собственно программа обычно состоит из процедур. Деление программы на процедуры не обязательно, но повышает ее наглядность и облегчает передачу управления подпрограммам и другим программным модулям. В примере программа содержит единственную процедуру myproc, открываемую оператором proc и закрываемую оператором endp c обязательным указанием имени процедуры. Последние две команды программного сегмента
mov ah,4Ch
int 21h
используются для организации возврата в DOS после выполнения программы. При этом вызывается процедура DOS с номером 21h (здесь h указывает на то, что код 21 представлен в 16-тиричном виде) и используется функция 4C, шестнадцатеричный номер которой помещается в регистр АН. Процедура завершает текущий процесс, возвращая указанный код завершения родительскому процессу. В процессе завершения освобождает всю выделенную процессу память, сбрасывает на диск буферы, закрывает все открытые дескрипторы и передает управление обработчику завершения процесса.
В сегментный регистр данных DS данные загружаются через регистр общего назначения AX. В в регистры CS и SS данные загружаются автоматически.
Для правильности выделения стека и автоматической инициализации регистра сегмента стека СS в строке описания сегмента стека необходимо указать параметр stack и класс ‘stack’. Для сегмента стека в программе зарезервировано 128 слов памяти с помощью оператора dw. Для программ, не осуществляющих операций со стеком, определение регистра SS и выделение сегмента стека необязательны. Текст программы заканчивается обязательной директивой end.
Пример программы (. ехе-файл), реализующей вычисление функции у=(a+d)*c/d:
; Вычисление функции у=(а+b)*c/d
; Формат данных – слово.
; ************************************************************
stseg segment para stack 'stack' ;задание сегмента стека
dw 16 dup(?) ; резервирование 16 слов памяти под стек
stseg ends
;–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
dseg segment para ;задание сегмента данных
a dw 10
b dw 20
c dw 30
d dw 30
y dw ? ;результат (2 байта)
ostd dw ? ;остаток от деления
dseg ends
;––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
cseg segment para ;начало сегмента кода
lab1 proc far ; вызов процедуры
assume cs: cseg, ds: dseg,ss: stseg
push ds
mov ax,0
push ax
mov ax,dseg
mov ds,ax
;––––––––––––––––––––––– текст программы ––––––––––––––––––––––––
mov ax,a ; (a)
add ax,b ; (a+b)
imul c ; (a+b)*c
idiv d ;(a+b)*c
mov y,ax ; запись результата в память
mov ost,dx ; запись остатка в память
ret ;возврат изпроцедуры
lab1 endp; конец описания процедуры
cseg ends ; конец сегмента кода
;–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
end lab1 ; конец программы
;************************************************************