Шаг 38.
Использование директив EXTRN и PUBLIC

    На этом шаге мы рассмотрим передачу параметров с посощью директив EXTRN и PUBLIC.

    Эти директивы мы уже упоминали выше, когда рассматривали варианты взаимного расположения вызывающей программы и вызываемой процедуры, Ко всему сказанному добавим, что директивы EXTRN и PUBLIC также можно использовать для обмена информацией между модулями. Назначение и форматы этих директив уже были рассмотрены, поэтому сейчас опишем только порядок их использования для обмена данными. Можно выделить несколько вариантов их применения:

    Рассмотрим эти варианты на примере программы, которая определяет в сегменте данных две символьные строки и вызывает процедуру, выводящую эти символы на экран.

    Вариант 1. Два модуля используют только сегмент данных вызывающей программы (листинги 38.1 и 38.2). В этом случае не требуется переопределения сегмента данных в вызываемой процедуре. В листинге 38.1 в вызывающей программе определены две переменные, вывод на экран которых осуществляет вызываемая программа (листинг 38.2).


    Листинг 38.1:
        TITLE Первый вариант использования директив EXTRN и PUBLIC
        ;Программа сделана как EXE-файл.
        ;-------------------------------
        EXTRN My_Proc2: FAR ;Внешняя процедура.
        PUBLIC Per1, Per2   ;Экспортируемые переменные.
        ;----- Сегмент стека
StackSg SEGMENT PARA STACK 'Stack'
DW      256  DUP(?)
StackSg ENDS
        ;----- Сегмент данных.
DataSg  SEGMENT PARA
Per1    DB  "1$" ;Первая переменная.
Per2    DB  "2$" ;Вторая переменная.
DataSg  ENDS	
        ;----- Сегмент кодов.
CodeSg  SEGMENT  PARA 
        ASSUME CS: CodeSg, DS: DataSg, SS: StackSg
Begin   PROC  FAR
        ;Пролог EXE-файла.
        PUSH DS
        XOR AX,AX
        PUSH AX
        MOV AX, DataSg
        MOV DS,AX
        ;Конец пролога
        ;Вызов внешней процедуры:
        CALL My_Proc2
        RET
Begin	ENDP
CodeSg	ENDS
	END Begin
Текст этой программы можно взять здесь.


    Листинг 38.2:
         TITLE   Вызываемый модуль
         ;Он подключается на этапе компоновки.
         ;-------------------------------
         EXTRN Per1: BYTE, Per2: BYTE ;Внешние переменные.
         PUBLIC My_Proc2              ;Экспортируемая процедура.
CodeSg   SEGMENT  PARA 
         ASSUME CS: CodeSg
My_Proc2 PROC  FAR
         MOV AH,09H 
         LEA DX, Per1
         INT 21H
         MOV AH,09H 
         LEA DX, Per2
         INT 21H
         RET
My_Proc2 ENDP
CodeSg   ENDS
         END
Текст этого модуля можно взять здесь.

    Вариант 2. У каждого из модулей есть свой собственный сегмент данных. В этом случае для доступа к переменным из своего модуля требуется переопределение сегмента данных в вызываемой процедуре.


    Листинг 38.3:
         TITLE   Вызываемый модуль
         ;Он подключается на этапе компоновки.
         ;Вызывающий модуль - тот же.
         ;-------------------------------
         EXTRN Per1: BYTE, Per2: BYTE ;Внешние переменные.
         PUBLIC My_Proc2              ;Экспортируемая процедура.
         ;----- Сегмент данных.
DataSg   SEGMENT PARA 
Per0     DB  "0$" ;Еще одна переменная.
DataSg   ENDS	
         ;----- Сегмент кодов.
CodeSg   SEGMENT  PARA 
         ASSUME CS: CodeSg, DS: DataSg
My_Proc2 PROC  FAR
         ;=======================
         ;На момент начала процедуры DS
         ;содержит адрес сегмента данных вызываемого модуля.
         ;Поэтому выводим значения переменных Per1 и Per2
         ;======================= 
         MOV AH,09H 
         LEA DX, Per1
         INT 21H
         MOV AH,09H 
         LEA DX, Per2
         INT 21H
         ;---------Переопределяем сегмент данных.
         PUSH DS          ;Сохранили DS.
         MOV AX, SEG Per0 ;Сегментный адрес Per0 в DS.
         MOV DS,AX
         MOV AH,09H 
         LEA DX, Per0
         INT 21H
         POP  DS          ;Восстановили DS.
         ;---------- Еще раз вывели Per1 и Per2.        
         MOV AH,09H 
         LEA DX, Per1
         INT 21H
         MOV AH,09H 
         LEA DX, Per2
         INT 21H
         RET
My_Proc2 ENDP
CodeSg   ENDS
         END
Текст этого модуля можно взять здесь.

    Вариант З. Использование атрибута комбинирования (объединения) сегментов PUBLIC в директиве сегментации SEGMENT для сегментов данных модулей (листинги 38.4 и 38.5). Данное значение атрибута комбинирования заставляет компоновщик объединить последовательно сегменты с одинаковыми именами. Все адреса и смещения будут вычисляться относительно начала этого нового сегмента. В этом случае не понадобится производить дополнительной настройки сегментных регистров (как было в предыдущих случаях).


    Листинг 38.4:
        TITLE Третий вариант использования директив EXTRN и PUBLIC
        ;Программа сделана как EXE-файл.
        ;-------------------------------
        EXTRN My_Proc2: FAR, Per0: BYTE ;Внешняя процедура и переменная.
        PUBLIC Per1, Per2   ;Экспортируемые переменные.
        ;----- Сегмент стека
StackSg SEGMENT PARA STACK 'Stack'
DW      256  DUP(?)
StackSg ENDS
        ;----- Сегмент данных.
DataSg  SEGMENT PARA PUBLIC 'Data'
Per1    DB  "1$" ;Первая переменная.
Per2    DB  "2$" ;Вторая переменная.
DataSg  ENDS	
        ;----- Сегмент кодов.
CodeSg  SEGMENT  PARA 
        ASSUME CS: CodeSg, DS: DataSg, SS: StackSg
Begin   PROC  FAR
        ;Пролог EXE-файла.
        PUSH DS
        XOR AX,AX
        PUSH AX
        MOV AX, DataSg
        MOV DS,AX
        ;Конец пролога.
        ;Вывод значения внешней переменной.
        MOV AH,09H
        LEA DX,Per0
        INT 21H
        ;Вызов внешней процедуры:
        CALL My_Proc2
        RET
Begin	ENDP
CodeSg	ENDS
	END Begin
Текст этой программы можно взять здесь.


    Листинг 38.5:
         TITLE   Вызываемый модуль
         ;Он подключается на этапе компоновки.
         ;-------------------------------
         EXTRN Per1: BYTE, Per2: BYTE ;Внешние переменные.
         PUBLIC My_Proc2, Per0        ;Экспортируемая процедура и переменная.
         ;----- Сегмент данных.
DataSg   SEGMENT PARA PUBLIC 'Data'
Per0     DB  "0$" ;Еще одна переменная.
DataSg   ENDS	
         ;----- Сегмент кодов.
CodeSg   SEGMENT  PARA 
         ASSUME CS: CodeSg, DS: DataSg
My_Proc2 PROC  FAR
         ;-------- Вывод переменных.
         MOV AH,09H 
         LEA DX, Per0
         INT 21H
         MOV AH,09H 
         LEA DX, Per1
         INT 21H
         MOV AH,09H 
         LEA DX, Per2
         INT 21H
         RET
My_Proc2 ENDP
CodeSg   ENDS
         END
Текст этого модуля можно взять здесь.

    Мы разобрали способы передачи параметров в процедуру. Рассмотрим теперь механизм возврата результатов из процедуры.

    На следующем шаге мы рассмотрим организацию возврата данных из процедуры.




Предыдущий шаг Содержание Следующий шаг