Шаг 37.
Передача аргументов через общую область памяти

    На этом шаге мы рассмотрим организацию передачи аргументов через общую область памяти.

    Этот вариант передачи аргументов предполагает, что вызывающая и вызываемая программы условились использовать некоторую область памяти как общую. Транслятор предоставляет специальное средство для организации такой области памяти. На шаге 18 мы разбирали директивы сегментации и их атрибуты. Один из них - атрибут комбинирования сегментов ("комбинация"). Наличие этого атрибута указывает компоновщику как нужно комбинировать сегменты, имеющие одно имя. Значение COMMON означает, что все сегменты, имеющие одинаковое имя в объединяемых модулях, будут располагаться компоновщиком, начиная с одного адреса оперативной памяти. Это значит, что они будут просто перекрываться в памяти и, следовательно, совместно использовать выделенную память.

    Недостатком этого способа в реальном режиме работы микропроцессора является отсутствие средств защиты данных от разрушения, так как нельзя проконтролировать соблюдение правил доступа к этим данным. В защищенном режиме ситуация выглядит лучше.

    Рассмотрим листинги 37.1 и 37.2 с примером использования общей области памяти для обмена данными между модулями. На этот раз программа состоит уже из двух независимых модулей, находящихся в разных файлах, и поэтому они представляют собой отдельные единицы трансляции. Функционально эти модули реализуют несложную задачу, которая заключается в том, что вызываемые процедуры формируют строку символов и передают ее через общую область, а вызывающая их процедура Begin выводит строку на экран.


    Листинг 37.1: основная программа, содержащая общий участок памяти и осуществляющая вывод сформированной строки на экран.
        TITLE   Передача аргументов через общую область памяти
        ;Программа сделана как EXE-файл.
        ;-------------------------------
        EXTRN PutChar: FAR, PutCharEnd: FAR ;Внешние процедуры.
        ;----- Сегмент стека
StackSg SEGMENT PARA STACK 'Stack'
DW      256  DUP(?)
StackSg ENDS
        ;----- Сегмент данных.
DataSg  SEGMENT PARA COMMON 'Data'
        ;----- Начало общей области памяти.
Buf     DB  15 DUP (" ") ;Буфер для хранения строки.
temp    DW  0  ;Длина текущей строки.
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 PutChar
        CALL PutCharEnd
        ;Вывод строки на экран:
        MOV AH,09H
        LEA DX,Buf
        INT 21H
        RET
Begin   ENDP
CodeSg  ENDS
        END Begin
Текст этой программы можно взять здесь.


    Листинг 37.2: библиотека, содержащая описание процедур и общую область памяти.
            TITLE   Передача аргументов через общую область памяти
            ;Модуль, где находится описание внешних процедур.
            ;-------------------------------
            PUBLIC PutChar, PutCharEnd ;Возвращаемые процедуры.
            ;----- Сегмент стека
StackSg     SEGMENT PARA STACK 'Stack'
DW          256  DUP(?)
StackSg     ENDS
            ;----- Сегмент данных.
DataSg      SEGMENT PARA COMMON 'Data'
            ;----- Начало общей области памяти.
Buffer      DB  15  DUP(" ") ;Буфер для хранения строки.
tmpSI       DW  0  ;Длина текущей строки.
DataSg      ENDS	
            ;----- Сегмент кодов.
CodeSg      SEGMENT  PARA 
            ASSUME CS: CodeSg, DS: DataSg, SS: StackSg
PutChar     PROC  FAR
            MOV SI,0
            MOV Buffer[SI],'Р'
            INC SI
            MOV Buffer[SI],'а'
            INC SI
            MOV Buffer[SI],'б'
            INC SI
            MOV Buffer[SI],'о'
            INC SI
            MOV Buffer[SI],'т'
            INC SI
            MOV Buffer[SI],'а'
            INC SI
            MOV Buffer[SI],'е'
            INC SI
            MOV Buffer[SI],'т'
            INC SI
            MOV Buffer[SI],'!'
            INC SI
            MOV tmpSI,SI
            RET
PutChar     ENDP

PutCharEnd  PROC  FAR
            MOV SI,tmpSI
            MOV Buffer[SI],'$'
            RET
PutCharEnd  ENDP		
CodeSg	ENDS
	END 
Текст этого модуля можно взять здесь.

    Обратите внимание, что совсем не обязательно, чтобы данные в сегментах COMMON имели одинаковые имена. Главное, и за этим нужно следить с особой тщательностью, - структура общих сегментов. Она должна быть абсолютно идентична во всех модулях данной программы, использующих обмен данными через общую память.

    Так как в данном примере программа состоит уже из двух модулей, то у читателя наверняка возник вопрос, как собрать ее в один исполняемый модуль. Можно предложить следующую последовательность шагов:

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




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