восстановить содержимое сохраненных регистров. Сразу после того как в С5 и IP будет помещена необходимая информация, работа программы продолжится с нужного места.

Сохранение регистров SP и С5 не вызывает особых сложностей — в Турбо Паскале для доступа к ним предусмотрены стандартные функции SPtr и CSeg. Однако в стандартных библиотеках нет аналогичных функций для чтения регистров ВР и IP. Во всех случаях восстановление сохраненных значений регистров возможно только с помощью ассемблера (в дальнейшем д^я краткости я буду писать ассемблер вместо язык ассемблера).

Особые сложности связаны с сохранением текущего значения регистра IP, в котором содержится адрес (точнее, смещение) очередной машинной команды. Дело в том, что с адресом любого исполняемого оператора Турбо Паскаля может быть связана только метка, однако в Турбо Паскале не предусмотрено никаких операций над метками. В частности, невозможно получить связанный с меткой адрес. Таким образом, для определения адреса нужного оператора придется использовать единственно возможный путь: разместить ассемблерный фрагмент непосредственно перед этим оператором и вычислить расстояние в байтах от некоторого места внутри ассемблерной части до начала этого оператора.

Размещение ассемблерного фрагмента в теле программы не вызывает особых проблем — для этого в Вашем распоряжении имеются средства встроенного ассемблера и InLine— операторов. Отмечу, что в силу тривиальности ассемблерных частей их можно реализовать в виде макросов. Макрос представляет собой процедуру, тело которого заменяет один InL me— оператор. Такая конструкция рассматривается компилятором как готовая программная заготовка, снабженная собственным именем. Всюду, где в тексте программы встречается вызов макроса, компилятор автоматически вставляет нужные программные коды. Макросы могут иметь параметры, которые перед передачей управления помещаются в стек в соответствии с соглашениями Турбо Паскаля. Однако для вызова макроса не используется машинная инструкция CALL, как это обычно бывает при вызове подпрограммы, ведь тело макроса располагается сразу за предыдущим оператором Турбо Паскаля. По этой причине в конце макроса не следует указывать инструкцию RET. Во всем остальном макросы ничем не отличаются от других InLine— процедур.

2.2.1. Текст модуля F_Jump

Ниже приводится текст модуля F_Jump, в котором объявляется тип JumpRec и два макроса SetJump и LongJump. Макрос Setiump осуществляет необходимые действия по сохранению регистров, поэтому его необходимо размещать непосредственно перед тем оператором, на который требуется передать управление в случае возникновения исключительной ситуации. Макрос LongJump осуществляет обратные действия — восстанавливает сохраненные ранее регистры. В результате его работы управление будет передано в нужную точку программы, поэтому этот макрос следует размещать внутри процедуры выхода, непосредственно перед ее завершением.