Шаг 45.
Инициализация EXE-программы

    На этом шаге мы рассмотрим структуру EXE-программы.

    Существует два основных типа выполняемых программ. Это EXE- и COM-файлы. Операционная система (DOS) требует выполнения четырех требований для инициализации ассемблерной EXE-программы:

    Первое из перечисленных требований реализуется директивой ASSUME.

    Второе требование вызвано тем, что загрузочному модулю в памяти непосредственно предшествует 256-байтовая область (100H), называемая префиксом программного сегмента (PSP), который содержит определенную служебную информацию. Для нас важно то, что первой командой, находящейся в PSP, является команда выхода в DOS. Поэтому после выполнения программы нужно передать управление на начало PSP и, таким образом, выйти в DOS.

    Выполняемую программу в памяти компьютера размещает специальная программа-загрузчик, которая использует регистр DS для установки адреса начальной точки PSP. Пользовательская программа должна сохранить этот адрес, поместив его в стек. Команда пересылки информации в стек начинается со служебного слова PUSH, например: PUSH AX. Команда извлечения данных из стека начинается со служебного слова POP. Таким образом, EXE-программа всегда должна содержать сегмент стека, в который обязательно помещается адрес начала PSP командой PUSH DS.

    Третье требование объясняется следующим образом. Извлечение из стека помещенного значения регистра DS будет осуществляться при выполнении команды RET главной процедуры (процедуры, с которой начинается выполнение программы). Это значение будет помещено в регистр CS. Однако в процессе вычисления адреса выполняемой команды участвует пара регистров CS:IP. После выполнения программы значение регистра IP будет отлично от нуля, но нам надо, чтобы там содержался нуль, так как регистр CS уже содержит адрес начала PSP. Поэтому нужно обнулить значение регистра IP, что осуществляется размещением нуля в стеке.

    Напомним, что параметр расстояние у директивы PROC основной программы должен быть установлен в FAR, что обеспечит при выполнении команды RET извлечение двух слов из стека. Если это расстояние не будет указано, то из стека будет извлечен только нуль, который помещается в регистр IP, что приведет к повторному выполнению программы (значение регистра CS не изменится и поэтому пара CS:0 адресует начало программы).

    Четвертое требование очевидно. Так как программа загрузчика использует регистр DS для своих нужд, то необходимо поместить в регистр DS адрес начала сегмента данных (если он присутствует в программе).

    Проиллюстрируем сказанное, рассмотрев общую структуру EXE-программы.

          TITLE   пример EXE-программы
;------------------ Сегмент стека -------------------------
          Stacksg   SEGMENT    PARA   STACK
             dw        128 DUP(?)
          Stacksg   ENDS
;--------------------- Сегмент данных---------------------
           Datasg    SEGMENT    PARA
             x        DB          00
             y        DB          00
             z        DB           ?
           Datasg    ENDS
;---------------------Кодовый сегмент --------------------
          Codesg    SEGMENT PARA
           begin    PROC     FAR
                    ;Пролог EXE-программы.
                    ;Выполнение первого требования.
                    ASSUME CS:Codesg, DS:Datasg, SS:Stacksg
                    ;Выполнение второго требования.
                    PUSH  DS         ; Записать DS в стек.
                    ;Выполнение третьего требования.
                    XOR  AX,AX       ; Установить в нуль AX.
                    PUSH  AX         ; Записать AX в стек.
                    ;Выполнение четвертого требования.
                    MOV   AX,Datasg  ; Занести адрес
                    MOV   DS,AX      ; Datasg в DS.
                    ;Завершение пролога EXE-программы. 
                       .  .  .
                    RET
           begin    ENDP
          Codesg    ENDS
                    END  begin

    На следующем шаге мы рассмотрим структуру COM-программы.




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