|
Для реализации этого способа
начинайте подпрограмму со следующей инструкции:
mov cs:new_stk_seg,cs ; получение нового стекового сегмента
Если необходимо, то для переключения стеков в программе мож-
- 3-59 -
но разработать два макроса, содержащих требуемые программные ко-
ды. Первый макрос включает программный код из входа в тело
программы, а второй макрос программный код из выхода из тела
программы. |
panda |
|
{img2} |
программа резервного копирования |
|
Оба макроса должны соответствовать именам переменных
стека в области данных, а второй макрос, кроме того, должен при-
нимать метку вершины стека top_of_stack как параметр для включе-
ния в предложение dw для указателя нового стека new_stk_ptr. В
эти макросы не должна входить инструкция RET. |
asplinux |
|
|
Это позволит ис-
пользовать эти макросы для выхода как с помощью инструкций JMP и
IRET, так и с помощью инструкции RET.
Для файлов типа .EXE второй макрос должен также принимать
как параметр имя стекового сегмента. Пример описанных выше мак-
росов для файлов типа .COM содержится в листинге 3-12 (INIT28),
приводимом позднее в этой главе.
Дополнительные соображения по переключению стеков
При переключении стеков, или, наоборот, при манипуляции сте-
ковым сегментом программа уязвима для прерываний. |
текстовые редакторы |
|
|
отказоустойчивые вычислительные системы, файловый менеджер, nod32, panda 2007, kaspersky, .
Архиваторы
|
Пример, приведенный в листинге 3-9, несколько неудачен
тем, что не сохраняет контекст предыдущей программы, а просто пе-
резаписывает его.
При получении управления, если необходимо сохранить целый
набор регистров, наиболее легким способом выполнения этого явля-
ется способ, заключающийся в том, чтобы сначала установить новый
стек программы и затем записать в него эти регистры. Поскольку
значения стекового сегмента и указателя стека не могут быть сох-
ранены в стеке вызывающей программы (в связи с отсутствием спо-
соба получения их обратно) и поскольку они не могут быть сохра-
нены в новом стеке (который еще не установлен), параметры стека
должны сохраняться в памяти. Если в виде исключения поместить в
один и тот же сегмент программные коды и данные, то для сохране-
ния старых стекового сегмента и указателя стека и установке
новых стекового сегмента и указателя стека может быть использо-
вана последовательность программных кодов, показанная в листин-
ге 3-11.
- 3-58 -
Листинг 3-11. Переключение стека для программы типа .EXE
----------------------------------------------------------------
enter: mov cs:old_stk_seg,ss ; Сохранение значений старого
mov cs:old_stk_ptr,sp ; стека
mov ss,cs:new_stk_seg ; загрузка значений нового
mov sp,cs:new_stk_ptr ; стека
push ds ; регистры стекового сегмента
push es
push ax ; начало записи в стек общих регистров
...
push bp
push si
push di
...
body:<тело программы> ; здесь начинается тело программы
...
pop di ; начало восстановления общих регистров
pop si
pop bp
...
pop ax
pop es ; восстановление регистров сегмента
mov ss,cs:old_stk_seg ; восстановление старых зна-
mov sp,cs:old_stk_ptr ; чений стека
jmp exit ; обход памяти данных
old_stk_seg dw ? ; стековый сегмент вызывающей программы
old_str_ptr dw ? ; указатель стека вызывающей программы
; стековый сегмент подпрограммы
new_stk_seg dw segment stack
; указатель стека подпрограммы
new_stk_ptr dw top_of_stack
exit: ; позиция выхода
ret ; возврат в вызывающую программу
----------------------------------------------------------------
Программные коды в листинге 3-11 зависят от имеющихся значе-
ний для стекового сегмента и указателя стека, уже размещенных в
памяти. Для резидентных подпрограмм и подпрограмм RTL это должно
быть выполнено с помощью процесса инициализации. Надлежащие зна-
чения в память для программ типа .EXE операционная система
MS-DOS помещает в процессе настройки.
В связи с тем, что подпрограммы типа .COM не могут содержать
значения сегмента, эти подпрограммы требуют другого способа пе-
реключения стеков. Запоминание значений для вершины стека в па-
мяти не вызывает проблем, за исключением адреса начала сегмента.
Т.к. подпрограммы типа .COM для своих целей совместно используют
один и тот же сегмент, то значение стекового сегмента может быть
получено из регистра программного сегмента. К несчастью, семей-
ство микропроцессоров 8086 не поддерживает пересылку из регистра
сегмента в регистр сегмента, поэтому значение может быть пере-
дано косвенным путем. В связи с отсутствием регистра, в котором
можно было бы сохранить значение, значение передается через па-
мять, используя кодовый сегмент.
|
|
|