4.7. Выполнение загрузочного модуля

Сборщик tlink.exe формирует из объектных модулей файл, готовый для выполнения. Этот файл называется загрузочным модулем. Он может быть построен двумя способами. В зависимости от способа построения он имеет расширение EXE или COM.

Размещение программы в памяти. Для выполнения программы пользователя операционная система (точнее загрузчик COMMAND.COM) размещает коды программы в свободной оперативной памяти и добавляет перед программой состоящий из 256 байт блок, который называется префиксом программного сегмента (PSP). После размещения операционная система передаёт управление в точку входа этой программы (определенную как операнд директивы end). Операционная система при этом производит следующие действия:

1) определяет сегментный адрес префикса программного сегмента (PSP);

2) создает два блока памяти – блок памяти для переменных среды и блок памяти для PSP и программы;

3) в блок памяти переменных среды помещает путь, откуда была загружена программа;

4) заполняет поля PSP.

Загрузочный модуль размещается в памяти следующим образом:

Сначала идет PSP (256 байт). Затем коды программы. Затем — данные программы, после которых идут неинициализируемые данные. Стек размещается в конце сегмента стека (который в случае COM совпадает с сегментом кодов).

Регистры DS и ES после размещения программы пользователя указывают на PSP.

Загрузочный модуль, как файл, может существовать в одном из двух форматов: EXE и COM. Формат EXE отличается от COM тем, что он содержит специальный начальный блок, который называется заголовком и занимает не менее 512 байт.

При загрузке программы DS и ES указывают на PSP и запоминаются поля PSP, но дальнейшие действия зависят от формата файла.

Файл EXE загружается, начиная с адреса PSP:100h. В момент загрузки файла EXE регистры CS, IP, SS и SP инициализируются значениями, указанными в заголовке.

Регистры DS и ES указывают на PSP. CS устанавливается на начало сегмента кодов.

Файл COM состоит из единственного сегмента. Образ файла COM помещается, начиная с адреса PSP:100h. Регистры CS и SS указывают на PSP, регистр SP – на конец сегмента PSP (т.е. SP=0FFFEh), регистр IP равен 100h.

В первых байтах PSP записывается команда int 20h (выход в операционную систему). Стало быть, если выполнить в начале программы EXE команды

push   es

mov    ax,0

push   ax

то, в случае, если встретится команда ret, произойдет переход по адресу ES:0 на команду int 20h. Если же вместо ret использовать для возврата в операционную систему к

оманду int 20h непосредственно в программе, то, поскольку сегмент вызывающей программы будет отличаться от PSP, адрес возврата будет вычисляться некорректно.

В программе COM эти шаги инициализации регистра DS и записи нулевого слова в стек не нужны. Эти действия производит загрузчик. Выход можно осуществлять с помощью команды RET. Так как адресация начинается со смещения 100h от начала PSP, то программа COM должна содержать директиву ORG 100h (после оператора SEGMENT).

Основное отличие формата COM от EXE заключается в том, что размер программы COM не больше 64 Кбайт и все данные, коды команд и область стека в ней размещаются в одном сегменте.

Пример. Рассмотрим программу, которая все символы строки превращает в соответствующие этим символам большие буквы

<1>        TITLE UEX.COM

<2> codesg segment

<3>        assume cs:codesg, ds:codesg, ss:codesg

<4>        org 100h

<5> begin: jmp   main

<6> text   db    ‘abcdefghijABCDEFGHIJ0123456789 $’

<7> main   proc  near

<8>        lea  bx,text

<9>        mov  cx,31       ;число символов

<10> b20:   mov   ah,[bx]     ;если символ

<11>        cmp  ah,’a’      ;не принадлежит диапазону

<12>        jb   b30         ;от ‘a’ до ‘z’

<13>        cmp  ah,’z’      ;то переходим к

<14>        ja   b30         ;следующему символу

<15>        and  ah,11011111b;очищаем бит 5

<16>        mov  [bx],ah     ;записываем новый символ

<17> b30:   inc   bx          ;bx указывает на

<18>        loop b20         ;следующий символ

<19>        lea  dx,text

<20>        mov  al,0

<21>        mov  ah,9        ;вывод строки

<22>        int  21h         ;на экран

<23>        ret

<24> main   endp

<25> codesg ends

<26>   end  begin