Существует два основных типа загрузочных программ: EXE и COM. Рассмотрим требования к EXE-программам.
DOS имеет четыре требования для инициализации ассемблерной EXE-программы:
- указать ассемблеру, какие сегментные регистры должны соответствовать сегментам,
- сохранить в стеке адрес, находящийся в регистре DS, когда программа начнет выполнение,
- записать в стек нулевой адрес,
- загрузить в регистр DS
data segment
адрес сегмента данных.
Существуют определенные различия между программой, выполняемой как EXE-файл и программой, выполняемой как COM-файл.
Параметр | EXE | COM |
---|---|---|
Размер программы | EXE-программа может иметь любой размер | COM-файл ограничен размером одного сегмента и не превышает 64К. COM-файл всегда меньше, чем соответствующий EXE-файл; одна из причин этого - отсутствие в COM-файле 512-байтового начального блока EXE-файла. |
Сегмент стэка | В EXE-программе определяется сегмент стека | COM-программа генерирует стек автоматически. Таким образом при создании ассемблерной программы, которая будет преобразована в COM-файл, стек должен быть опущен. |
Сегмент данных | В EXE программе обычно определяется сегмент данных, а регистр DS инициализируется адресом этого сегмента. | В COM-программе все данные должны быть определены в сегменте кода. |
Инициализация | EXE-программа записывает нулевое слово в стек и инициализирует регистр DS ("Data Segment") | COM-программа не имеет ни стека, ни сегмента данных, то эти шаги отсутствуют. |
Когда COM-программа начинает работать, все сегментные регистры содержат адрес префикса программного сегмента (PSP) 256-байтового (или 0x100) блока, который резервируется операционной системой DOS непосредственно перед COM или EXE программой в памяти. Так как адресация начинается со смещения 0x100 от начала PSP ("Program Segment's Prefix"), то в программе после оператора SEGMENT кодируется директива ORG 100H
data segment para public “data”;сегмент данных
message db “Введите две 16-теричные цифры, $”
data ends
stk segment stack
db 256 dup (“?”);сегмент стека
stk ends
code segment para public “code”;начало сегмента кода
main proc. ;начало процедуры main
assume cs:code,ds:data,ss:stk
mov ax,data. ;адрес сегмента данных в регистр ах
mov ds,ax
mov ah,9
mov dx,offset message
int 0x21
xor ax, ax ;очистить регистр ах
mov ah, 0x1 ;1h в регистр ah
int 0x21 ;генерация прерывания с номером 21h
mov dl,al ;содержимое регистра al в регистр dl
sub dl,0x30 ;вычитание: (dl)=(dl)-30h
cmp dl,0x9 ;сравнить (dl) с 9h
jle M1 ;перейти на метку М1, если dl<9h или dl=9h
sub dl,0x7 ;вычитание: (dl)=(dl)-7h
M1: ;определение метки М1
mov cl,0x4 ;пересылка 4h в регистр сl
shl dl,cl ;сдвиг содержимого dl на 4 разряда влево
int 0x21 ;вызов прерывания с номером 21h
sub al,0x30 ;вычитание: (dl)=(dl)-30h
cmp al,0x9 ;сравнить (al) c 9h
jle M2 ;перейти на метку М2, если al<9h или al=9h
sub al,0x7 ;вычитание: (al)=(al)-7h
M2: ;определение метки М2
add dl,al ;сложение: (dl)=(dl)+(al)
mov ax,0x4c00 ;пересылка 4с00h в регистр ax
int 0x21 ;вызов прерывания с номером 21h
main endp ;конец процедуры main
code ends ;конец сегмента кода