Описание некоторых команд Ассемблера
Команда пересылки данных - MOV
Основная команда общего назначения MOV (move – переслать) может пересылать байт или слово между регистром и ячейкой памяти или между двумя регистрами. Она может также пересылать непосредственно адресуемое значение в регистр или в ячейку памяти. При пересылке она замещает первый операнд (приемник) вторым (источником), соответственно исходное значение первого операнда теряется. Тип пересылаемых операндов должен быть одинаков.
Команда имеет следующий формат: MOV приемник, источник
В этой команде допустимо большинство из возможных сочетаний операндов. Приведем несколько примеров:
MOV AX,TABLE; Пересылка из памяти в регистр.
MOV TABLE,АХ; Пересылка из регистра в память.
MOV ES:[BX],AX; Можно заменить используемый регистр сегмента.
MOV DS,AX; Пересылка между 16-битовыми регистрами.
MOV BL,AL; Пересылка между 8- битовыми регистрами.
MOV CL,-ЗО; Пересылка константы в регистр.
MOV DEST,25H; Пересылка константы в ячейку памяти по адресу DEST.
В команде МОV исключаются следующие сочетания операндов:
1) память, память – запрещается непосредственная пересылка данных из одной ячейки памяти в другую. Чтобы выполнить такую операцию, необходимо использовать промежуточное звено, которым может быть регистр общего назначения. Например, если per1 и per2 – переменные, находящиеся в памяти, то для пересылки значения из одной переменной в другую можно воспользоваться следующими командами:
MOV AX, per1; Копировать содержимое ячейки по адресу per1 в АХ.
MOV per2,AX; Копировать содержимое АХ в ячейку по адресу per2.
2) регистр сегмента, непосредственный операнд – нельзя пересылать непосредственно адресуемый операнд в регистр сегмента. Как и в случае 1, сначала надо загрузить его в регистр общего назначения. Например, для загрузки адреса сегмента данных (DATA_SEG) в регистр DS используют следующие команды:
MOV AX,@DATA; Копировать адрес сегмента данных в АХ.
MOV DS,AX; Копировать адрес сегмента данных из АХ в DS.
Эти команды инициализируют сегментный регистр DS;
3) регистр сегмента, регистр сегмента – нельзя непосредственно пересылать значение одного регистра сегмента в другой. Делайте подобные пересылки через регистр общего назначения. Например, чтобы регистр DS указывал на тот же сегмент, что и регистр ES, воспользуйтесь командами:
MOV AX,@DATA; Копировать адрес сегмента данных в АХ.
MOV DS,AX; Копировать адрес сегмента данных из АХ в DS.
MOV ЕS, АХ; Копировать адрес сегмента данных из АХ в ES.
4) запрещено использовать регистр CS в качестве приемника в команде пересылки непосредственных данных.
Команды обращения в стэк – PUSH и POP
Как уже упоминалось, во время исполнения процедуры стек содержит адрес возврата. Команда вызова процедуры CALL (call - вызвать) помещает адрес следующей команды в стек, а команда возврата RET (return - возвратить) извлекает его по окончании исполнения процедуры. Это один из случаев, когда микропроцессор 8086 использует стек автоматически, без указания.
Таким образом, стек удобен для временного сохранения данных (содержимого регистров и ячеек памяти) при работе программы. Например, сохранить содержимое регистра СХ на то время, пока он требуется для выполнения каких-либо действий. Для этого имеются две команды для работы со стеком – PUSH (поместить слово в стек) и POP (извлечь слово из стека). Команда PUSH помещает содержимое регистра или ячейки памяти размером в 16-битовое слово на вершину стека. А команда POP, наоборот, снимает слово с вершины стека и помещает его в ячейку памяти или регистр.
Команды PUSH и POP имеют следующие форматы:
PUSH источник
POP приемник
Приведем несколько примеров:
PUSH SI; В стэк копируется содержимое регистра SI.
PUSH DS; В стэк копируется содержимое регистра DS.
PUSH CS; В стэк копируется содержимое регистра CS.
PUSH COUNTER; В стэк копируетсяc одержимое константы,
PUSH TABLE [BX][DI]; или ячейки памяти из указанного адреса.
Будучи взаимно обратными командами, PUSH и POP обычно используются парами, т.е. каждой команде PUSH в программе должна соответствовать своя команда POP. Например, при сохранении содержимого регистра АХ в стеке и последующем его восстановлении программа будет иметь вид:
PUSH AX; Сохранить АХ на вершине стека.
. . . ; Другие команды программы,
. . . ; изменяющие содержимое АХ.
. . . ;
POP AX; Восстановить значение АХ, сняв его с вершины стека.
Под вершиной стека понимается ячейка в сегменте стека, адрес которой содержится в указателе стека SP. Так как стек "растет" по направлению к младшим адресам памяти (к ячейке 0), то первое помещаемое в стек слово запоминается в ячейке стека с наибольшим адресом, следующее на два байта ниже, и т.д.
Регистр SP всегда указывает на адрес последнего слова, помещенного в стек. Следовательно, команда PUSH вычитает 2 из значения указателя стека, а затем пересылает операнд-источник (слово) в стек. Действуя обратным образом, команда POP пересылает в операнд-приемник слово, адрес которого содержится в регистре SP, a затем добавляет 2 к содержимому этого регистра. Адреса ячеек стека вычисляются по следующему известному алгоритму:
SS × 10H + SP ± 2.
Значение SP в результате исполнения команды PUSH указатель стека передвинется на два байта памяти ниже, и в этих байтах (ранее не используемых) будет содержаться значение регистра АХ. В результате исполнения команды POP содержимое регистра SP вернется в исходное состояние. Слово, считанное из стека по команде РОР, может быть помещено в любой регистр, кроме сегментного регистра CS. С помощью серии команд PUSH в стеке можно сохранить 32768 слов, причем каждая команда PUSH помещает свой операнд на вершину стека, и поэтому с помощью команды POP слова извлекаются из стека в порядке, обратном их записи. В приведенном ниже примере последовательность команд помещает значения четырех регистров в стек, а затем восстанавливает их, но уже в обратном порядке.
Mov AX,33; Занесем в АХ десятичное число 33.
Mov BX,55; Занесем в ВХ десятичное число 55.
Mov CX,66; Занесем в СХ десятичное число 66.
Mov dx,77; Занесем в DХ десятичное число 77.
PUSH AX; Сохраним содержимое АХ в стеке.
PUSH ВХ; Сохраним содержимое ВХ в стеке.
PUSH СХ; Сохраним содержимое СХ в стеке.
PUSH DX; Сохраним содержимое DХ в стеке.
POP AX; Восстановить АХ. Теперь в АХ число 77.
POP BX; Восстановить ВХ. Теперь в ВХ число 66.
POP CX; Восстановить СХ. Теперь в СХ число 55.
POP DX; Восстановить DХ. Теперь в DХ число 33.
Команды PUSH и POP удобны также для копирования содержимого одного регистра сегмента в другой. Например, с помощью команд
PUSH ES
POP DS; Можно скопировать значение регистра ES в регистр DS.
Разновидность стековых команд дает возможность сохранять в стеке содержимое регистра флагов.
PUSHF; Запись регистра флагов в стек.
POPF; Чтение регистра флагов из стека.
По первой команде в стеке сохраняется содержимое регистра флагов, а по второй из стека считывается слово и заносится в Flags. При этом команда PUSHF не меняет флаги, а команда POPF, естественно, меняет все флаги. Эти команды можно также использовать для определения или изменения состояния любого флага.
Команда обмена операндами - XCHG
Команда обмена XCHG (exchange - обменять) меняет между собой значения двух регистров или регистра и ячейки памяти. Операнды должны иметь одинаковый тип данных (байт−байт, слово−слово и т.д.). Несколько примеров:
XCHG АХ,ВХ; Обменять значения двух словных регистров.
XCHG AL,BL; Обменять значения двух байтовых регистров.
XCHG WORD_MEM,DX; Поменять значения словной ячейки памяти и словного регистра.
XCHG DL,BYTE_ MEM; Поменять значения байтового регистра и байтовой ячейки памяти.
Команда инвертирования операндов
Команда инвертирования NOT выполняет логическую функцию НЕ над операндом и оставляет результат в операнде. Операндом может служить регистр или ячейка памяти. Тип операндов – байт, слово, двойное слово.
Пример применения команды:
Mov АХ,579BH; Загрузим данные в регистр АХ.
Not АХ; Получим в АХ 0А864Н.
Mov WORD_MEM,1111H; Загрузим в ячейку памяти число 1111Н.
Not WORD_MEM; Инвертируем его и получим число ЕЕЕЕН.
Mov BYTE_ MEM, 0000H; Загрузим в ячейку памяти число 0000Н.
Not BYTE_ MEM; Инвертируем его и получим число FFFFH.
Команда программного прерывания – INT
Команда INT инициирует в процессоре процедуру прерывания, в результате которой управление передается программе обработки прерывания с номером n. Этот номер указан в качестве операнда команды.
Прерывания подразделяются на аппаратные и программные, но процедуры обработки прерываний выполняются по одному алгоритму.
Команда INT (interrupt – прерывать) имеет следующий формат:
INT тип_прерывания,
где тип_прерывания −это номер, идентифицирующий один из 256 различных векторов, находящихся в памяти (вектор-это четырехбайтная область памяти).
Таким образом, каждому из 256 прерываний соответствует один вектор, где хранятся IP и CS программы обработки прерывания.
При исполнении команды INT микропроцессор выполняет следующие действия:
1) помещает в стек содержимое регистра флагов;
2) помещает в стек значение регистра CS;
3) помещает в стек значение регистра IP;
4) обнуляет флаг трассировки TF и флаг включения-выключения прерываний IF для исключения пошагового режима исполнения команд и блокировки других маскируемых прерываний;
5) умножая тип_ прерыванияна 4, вычисляя тем самым адрес вектора прерывания;
6) загружает из памяти второе слово вектора прерывания в регистр CS;
7) загружает из памяти первое слово вектора прерывания в регистр IP;
8) устанавливает флаги IF и TF.
Итак, после исполнения команды INT в стеке окажутся значения регистра флагов и регистров CS и IP, флаги TF и IF будут равны 0, а в регистрах CS:IP начальный адрес программы обработки прерывания. Адреса имеют длину 4 байта и они занимают первые 1К байтов.
Например, команда INT 21Н заставит микропроцессор 8086 вычислить адрес вектора 54Н (4×21Н). Следовательно, он получит 16-битовые значения регистров IP и CS, отвечающие программе обработки прерывания, из ячеек 54Н и 56Н соответственно.
Вызванная программа анализирует содержимое регистров Al, AH, DX, определяет вид вызываемой функции и осуществляет передачу управления этой функции.