Как уже упоминалось, во время исполнения процедуры стек содержит адрес возврата. Команда вызова процедуры CALL (call - вызвать) помещает адрес следующей команды в стек, а команда возврата RET (return - возвратить) извлекает его по окончании исполнения процедуры. Это один из случаев, когда микропроцессор 8086 использует стек автоматически, без указания.
Таким образом, стек удобен для временного сохранения данных (содержимого регистров и ячеек памяти) при работе программы. Например, сохранить содержимое регистра СХ на то время, пока он требуется для выполнения каких-либо действий. Для этого имеются две команды для работы со стеком – PUSH (поместить слово в стек) и POP (извлечь слово из стека). Команда PUSH помещает содержимое регистра или ячейки памяти размером в 16-битовое слово на вершину стека. А команда POP, наоборот, снимает слово с вершины стека и помещает его в ячейку памяти или регистр.
Команды PUSH и POP имеют следующие форматы:
PUSH источник;
POP приемник;
Приведем несколько примеров:
PUSH SI; Можно сохранить регистр общего назначения.
PUSH DS; Можно сохранить регистр сегмента,
PUSH CS; включая регистр CS.
PUSH COUNTER; Можно также сохранить содержимое
PUSH TABLE [BX][DI]; ячейки памяти.
Будучи взаимно обратными командами, PUSH и POP обычно используются парами, т.е. каждой команде PUSH в программе должна соответствовать своя команда POP. Например, при сохранении содержимого регистра АХ в стеке и последующем его восстановлении программа будет иметь вид:
PUSH AX; Сохранить АХ на вершине стека.
. . . ;Другие команды программы,
. . .; изменяющие содержимое АХ.
. . .;
POP AX; Восстановить значение АХ, сняв его с вершины стека.
Под вершиной стека понимается ячейка в сегменте стека, адрес которой содержится в указателе стека SP. На рисунке 3.1 показаны состояния стека и его указателя до и после использования команд PUSH и POP. Так как стек "растет" по направлению к младшим адресам памяти (к ячейке 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, естественно, меняет все флаги. Эти команды можно также использовать для определения или изменения состояния любого флага.
3.1.16 Команды вычитания - SUB, и вычитания с заемом SBB
Команды SUB (substract - вычесть) и
SBB (substract with borrow - вычесть с заемом)
аналогичны соответственно командам сложения ADD и ADC, только при вычитании флаг переноса CF действует как признак заема. Формат команды: SUB приемник,источник;
Команда SUB вычитает операнд-источник из операнда-приемника и помещает результат в приемник, т.е. приемник:= приемник – источник.
Команда SBB делает то же самое, но дополнительно вычитает из приемника значение флага переноса CF:
SUB приемник,источник – С F ; приемник:= приемник - источник -
содержимое флага переноса.
Как и в случае сложения, команды SUB и SBB выполняют две отдельные функции. Первая команда вычитает числа размером в байт или слово, а также младшие биты чисел повышенной точности. Втрорая команда вычитает старшие биты чисел повышенной точности. Например, команда SUB AX,CX; вычитает содержимое регистра СХ из содержимого регистра АХ и возвращает результат в регистр АХ.
Если размеры операндов превышают 16 бит, то необходимо применить следующую последовательность команд:
SUB АХ,ВХ; Вычесть младшие 16 бит,
SBB BX,DX; а затем старшие 16 бит.
Здесь мы вычитаем 32-битовое число, находящееся в регистрах СХ и DX, из 32-битового числа, помещенного в регистры АХ и ВХ. При вычитании содержимого регистра DX из содержимого регистра ВХ команда SBB учитывает возможность заема при выполнении первого вычитания. Можно вычитать из содержимого регистра содержимое ячейки памяти (и наоборот) или вычитать из содержимого регистра либо ячейки памяти непосредственное значение. Примеры допустимых команд:
SUB АХ, MEM; Вычесть из регистра содержимое ячейки памяти.
SUB MEM [BX],AX; Вычесть из ячейки памяти регистр.
SUB AL,1O; Вычесть константу из регистра.
SUB MEM_BYTE,OFh; Вычесть константу из ячейки памяти.
Нельзя непосредственно вычесть содержимое одной ячейки памяти из другой или использовать непосредственное значение как приемник.
Команды SUB и SBB могут воздействовать на шесть флагов следующим образом:
- устанавливают флаг переноса CF в 1, если требуется заем, в противном случае он равен 0;
- устанавливают флаг четности PF в 1, если результат вычитания имеет четное число битов со значением 1, в противном случае он равен 0;
- устанавливают вспомогательный флаг переноса AF в 1, если результат вычитания десятичных чисел требует коррекции, в противном случае он равен 0;
- устанавливают флаг нуля ZF в 1, если результат равен 0, в противном случае он равен 0;
- устанавливают флаг знака SF в 1, если результат отрицателен (старший бит равен 1), в противном случае флаг равен 0;
- устанавливают флаг переполнения OF в 1, если при вычитании результат превышает диапазон значений приемника в обратном коде, а сам приемник изменяет знак.
Флаги SF и OF имеют смысл только при вычитании чисел со знаком, а флаг AF- только при вычитании десятичных чисел.
Дата: 2018-11-18, просмотров: 553.