Exe dos

Глава 7 – Загрузка и выполнение программ в DOS, структура EXE и COM программ

Exe dos

Загрузка и выполнение программ

При загрузке программ в оперативную память DOS (дисковая операционная система) инициализирует как минимум три сегментных регистра: CS, DS и SS.

При этом совокупности байтов, представляющих команды процессора (код программы), и данные помещаются из файла на диске в оперативную память, а адреса этих сегментов записываются в CS и DS соответственно.

Сегмент стека либо выделяется в области, указанной в программе, либо совпадает (если он явно в программе не описан) с самым первым сегментом программы. Адрес сегмента стека помещается в регистр SS.

Программа может иметь несколько кодовых с егментов и сегментов данных и в процессе выполнения специальными командами выполнять переключения между ними.

Для того чтобы адресовать одновременно два сегмента данных, например, при выполнении операции пересылки из одной области памяти в другую, можно использовать регистр дополнительного сегмента ES.

Кодовый сегмент и сегмент стека всегда определяются содержимым своих регистров (CS и SS), и поэтому в каждый момент выполнения программы всегда используется какой-то один кодовый сегмент и один сегмент стека.

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

Все сегменты могут использовать различные области памяти, а могут частично или полностью перекрываться. Кодовый сегмент должен обязательно описываться в программе, все остальные сегменты могут отсутствовать.

В этом случае DOS при загрузке программы в оперативную память инициирует регистры DS и ES значением адреса префикса программного сегмента PSP (Program Segment Prefics) – специальной области оперативной памяти размером 256 (100h) байт.

PSP может использоваться в программе для определения имен файлов и параметров из командной строки, введенной при запуске программы на выполнение, объема доступной памяти, переменных окружения системы и т.д. Регистр SS при этом инициализируется значением сегмента, находящегося сразу за PSP, т.е.

первого сегмента программы. При этом необходимо учитывать, что стек «растет вниз» (при помещении в стек содержимое регистра SP, указывающего на вершину стека, уменьшается, а при считывании из стека – увеличивается).

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

Вот пример размещения сегментов в памяти:

Рассмотрим распределение памяти на примере простейшей структуры программы:
;Данные программы
DATA SEGMENT
MSG DB ‘Текст$’
DATA ENDS
;Код программы
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START:
;команды установки сегмента данных
MOV AX,DATA
MOV DS,AX
…………….
;команды
CODE ENDS
END START

В этой программе явно описаны два сегмента – кода с именем CODE и данных с именем DATA. Директива ASSUME связывает имена этих сегментов, которые в общем случае могут быть произвольными, с сегментными регистрами CS и DS соответственно. 
Распределение памяти при загрузке программы на исполнение показано на рисунке:

Как видно из рисунка, сегмент стека в данном случае установлен на PSP, что при его интенсивном использовании может привести к неожиданным результатам. После инициализации в регистре IP находится смещение первой команды программы относительно начала кодового сегмента, адрес которого помещен в регистр CS.

Процессор, считывая эту команду, начинает выполнение программы, постоянно изменяя содержимое регистра IP и при необходимости CS для получения кодов очередных команд до тех пор, пока не встретит команду завершения программы. DS после загрузки программы установлен на начало PSP, поэтому для его использования в первых двух командах программы выполняется загрузка DS значением сегмента данных.

Вообще говоря структура приведена здесь для примера, а более подробно мы рассмотрим её позднее.

Различия EXE и COM программ

DOS может загружать и выполнять программные файлы двух типов – COM и EXE.

Ввиду сегментации адресного пространства процессора 8086 и того факта, что переходы (JMP) и вызовы (CALL) используют относительную адресацию, оба типа программ могут выполняться в любом месте памяти.

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

Файл COM-формата – это двоичный образ кода и данных программы. Такой файл должен занимать менее 64K и не содержать перемещаемых адресов сегментов.

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

Перед загрузкой COM- или EXE-программы DOS определяет сегментный адрес, называемый префиксом программного сегмента (PSP), как базовый для программы.

Затем DOS выполняет следующие шаги: 1) создает копию текущего окружения DOS (область памяти, содержащая ряд строк в формате ASCIIZ, которые могут использоваться приложениями для получения некоторой системной информации и для передачи данных между программами) для программы; 2) помещает путь, откуда загружена программа, в конец окружения;

3) заполняет поля PSP информацией, полезной для загружаемой программы (количество памяти, доступное программе; сегментный адрес окружения DOS; текущие векторы прерываний INT 22H INT 23H и INT 24H и т.д).

EXE-программы. 

EXE-программы содержат несколько программных сегментов, включая сегмент кода, данных и стека. EXE-файл загружается, начиная с адреса PSP:0100h.

В процессе загрузки считывается информация заголовка EXE в начале файла и выполняется перемещение адресов сегментов.

Это означает, что ссылки типа mov ax,data_seg mov ds,ax и call my_far_proc должны быть приведены (пересчитаны), чтобы учесть тот факт, что программа была загружена в произвольно выбранный сегмент. 

После перемещения управление передается загрузочному модулю посредством инструкции далекого перехода (FAR JMP) к адресу CS:IP, извлеченному из заголовка EXE.

В момент получения управления программой EXE -формата: 1) DS и ES указывают на начало PSP 2) CS, IP, SS и SP инициализированы значениями, указанными в заголовке EXE

3) поле PSP MemTop (вершина доступной памяти системы в параграфах) содержит значение, указанное в заголовке EXE. Обычно вся доступная память распределена программе.

COM-программы. 

COM-программы содержат единственный сегмент (или, во всяком случае, не содержат явных ссылок на другие сегменты). Образ COM-файла считывается с диска и помещается в память, начиная с PSP:0100h. В общем случае, COM-программа может использовать множественные сегменты, но она должна сама вычислять сегментные адреса, используя PSP как базу.

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

После загрузки двоичного образа COM-программы: 1) CS, DS, ES и SS указывают на PSP; 2) SP указывает на конец сегмента PSP (обычно 0FFFEH, но может быть и меньше, если полный 64K сегмент недоступен);  3) слово по смещению 06H в PSP (доступные байты в программном сегменте) указывает, какая часть программного сегмента доступна; 4) вся память системы за программным сегментом распределена программе; 5) слово 00H помещено (PUSH) в стек.

6) IP содержит 100H (первый байт модуля) в результате команды JMP PSP:100H.

Структура программ на ассемблере

Следует отметить, что какой-либо фиксированной структуры программы на языке Ассемблера нет, но для небольших EXE-программ с трехсегментной структурой типична следующая структура:
;Определение сегмента стека
STAK SEGMENT STACK
DB 256 DUP (?)
STAK ENDS
;Определение сегмента данных
DATA SEGMENT
SYMB DB '#' ;Описание переменной с именем SYMB
;типа Byte и со значением «#»
. . . ;Определение других переменных
DATA ENDS
;Определение сегмента кода
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,SS:STAK
;Определение подпрограммы
PROC1 PROC 
. . . ;Текст подпрограммы
PROC1 ENDP
START: ;Точка входа в программу START
XOR AX,AX 
MOV BX,data ;Обязательная инициализация
MOV DS,BX ;регистра DS в начале программы
CALL PROC1 ;Пример вызова подпрограммы
. . . ;Текст программы
MOV AH,4CH ;Операторы завершения программы
INT 21H
CODE ENDS
END START

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

Сегмент стека в приведенной структуре описан с параметром STACK, поэтому в самой программе нет необходимости загружать сегментный регистр SS. Сегментный регистр CS тоже нет необходимости загружать, как уже отмечалось ранее. В связи с этим в начале программы загружается лишь регистр DS. 

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

Необходимо также заметить, что все предложения, по которым ассемблер заносит что-либо в формируемую программу (инструкции, директивы определения данных и т.д.) обязательно должны входить в какой-либо программный сегмент, размещать их вне программных сегментов нельзя.

Исключение составляют директивы информационного характера, например, директивы EQU, директивы описания типов структур и записей. Кроме того, не рекомендуется размещать в сегменте данных инструкции, а в сегменте кода – описание переменных из-за возникающих в этом случае проблем с сегментированием.

Типичная структура COM-программы аналогична структуре EXE-программы, с той лишь разницей, что, как уже отмечалось выше, COM-программа содержит лишь один сегмент – сегмент кода, который включает в себя инструкции процессора, директивы и описания переменных.

;Определение сегмента кода
CODE SEGMENT
ASSUME CS:CODE,DS:CODE,SS:CODE
ORG 100H ;Начало необходимое для COM-программы
;Определение подпрограммы
PROC1 PROC 
. . .

;Текст подпрограммы
PROC1 ENDP
START:
. . . ;Текст программы
MOV AH,4CH ;Операторы завершения программы
INT 21H
;===== Data =====
BUF DB 6 ;Определение переменной типа Byte 
.

. . ;Определение других переменных
CODE ENDS
END START

Ну вообще говоря надо отметить что кроме структуры различие между этими форматами программ состоит еще и в режимах компиляции, то есть в том какие параметры указывать в командной строке! Это мы разберём на практике!

А теперь теже самые структуры программ но с упрощенными директивами!

Вот как компактнее можно описать EXE программу
.model small
.code ;начали сегмент кода
start:
;текст программы
.data ;начали сегмент данных
message db 'This symbol is out:',0Ah,0Dh,'$'
end start

Видите те самы директивы распределения сегментов? В начале просто задали модель памяти, а затем где какие сегменты! 🙂 так гораздо проще! Именно этот подход я и буду демонстрировать при разборе конкретных задач.

А вот и COM программа

.model tiny
.

code
org 100h
start:
;текст программы
ret;так можно завершать COM программу!!!

message db 'This string is out!!!!!!',0Ah,0Dh,'$'
end start

Здесь еще проще! Всё в одном сегменте! и код и данные! Только модель памяти задали tiny да добавили директиву изменения программного счётчика – ведь COM программа грузится после PSP размеров в 100h.

Источник: http://iamalone.ru/index.php/blog/dokumentatsiya/samouchitel-po-assembleru/item/244-glava-7-zagruzka-i-vypolnenie-programm-v-dos-struktura-exe-i-com-programm

DOS на флэшке

Exe dos

Сервер 2012 и технический прогресс вообще это хорошо. Но иногда приходится возвращаться к истокам – DOS. И дело не в ностальгических воспоминаниях о первых игрушках. Для этого есть DOSBox.

Просто, определенное ПО невозможно запустить под XP или 7. Не помогают ни помянутый DOSBox, ни VirtualPC. Обычно это различные обновления для BIOS. Или программы напрямую работающие с контроллером COM порта – самописанное ПО для самоспаянных программаторов, часто использующихся в автомастерских и сервисных центрах печатной техники.

Обычно для этих целей в углу, с незапамятных времен, стоит Pentium 200 с ЭЛТ монитором. Но всему приходит конец.

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

Быстрым выходом может стать загрузка DOS с флэшки. На все про все у вас уйдет 5 минут и подготовленная к выбросу флэшка малой емкости.

Скачиваем DOSUSB.ZIP содержащий файлы DOS и HPUSBFW.ZIP с утилитой HP USB disk storage format tool.

Разворачиваем архивы на жесткий диск, вставляем подопытную флэшку и запускаем HPUSBFW.EXE с правами администратора. Выбираем тип файловой системы FAT32 и ставим галочку Create a DOS startup disk using system files located at

Указываем путь к каталогу с файлами DOS и нажимаем кнопку Start

По окончании процесса у нас готова загрузочная флэшка с DOS, утилита записывает загрузчик и копирует три файла: IO.SYS, MSDOS.SYS и COMMAND.COM В дополнение можно на нее скопировать оставшиеся файлы из DOSUSB.ZIP

Пробежимся по настройкам и внешним DOS командам присутвующим на нашей флэшке.

CONFIG.SYS

dos=high,umb указывает DOS загружать часть кода в HMA
files=60 количество файлов которые ОС сможет открывать одновременно
buffers=20 количество первичных дисковых буферов (если есть dos=high буфера загружаются в HMA)
stacks=9,256 количество (8-64) и размер стеков в байтах (32-512), начиная с MSDOS 3.2 ОС может выполнять переключение между стеками при возникновении аппаратного прерывания (по умолчанию переключение запрещено stack=0,0)
lastdrive=z указывает максимальную разрешенную букву для устройств (по умолчанию, следующая за последним устройством, которое нашла DOS при загрузке)
device=himem.sys /testmem:off загрузка драйвера extended memory и HMA
devicehigh=display.sys con=(ega,,1) загрузка драйвера поддерживающего вывод на экран русских символов
country=007,866,country.sys поддержка файлов и папок имена которых содержат русские символы

AUTOEXEC.BAT

@ECHO OFF
SET DIRCMD=/O:N устанавливаем параметры для команды DIR, в данном случае сортировку по имени
cls очищаем экран
set temp=c:\ устанавливаем переменные временных каталогов
set tmp=c:\
mode.com con cp prepare=((866) ega3.

cpi) указываем экранный шрифт ega3.cpi для display.sys
mode.com con cp select=866 выбираем режим отображения через display.sys и ega3.cpi
keyb.com ru,,keybrd3.sys настраиваем клавиатуру на использование русского языка с файлом определения keybrd3.

sys, русский CTRL+RIGHT_SHIFT, английский CTRL+LEFT_SHIFT

Внешние команды присутствующие на флэшке:

ATTRIB.EXE отображение и изменение атрибутов файлов

CHKDSK.EXE используйте если SCANDISK не может проверить диск

DEBUG.EXE отладчик, несмотря на простоту может многое

EDIT.COM текстовый редактор

EXT.EXE интерактивное создание командной строки для EXTRACT

EXTRACT.EXE экстрактор для CAB файлов

FDISK.EXE управление разделами на дисках

FORMAT.COM форматирование разделов созданных FDISK

MSCDEXT.EXE перенаправитель для CDROM, работает по принципу сетевого перенаправителя, получает запросы от ОС первым и обрабатывает касающиеся CDROM, для ОС CDROM представляется сетевым диском

RESTART.COM перезагрузка компьютера без предупреждения

SCANDISK.EXE программа для проверки файловой системы и диска на ошибки

SYS.COM перенос системных файлов с одного диска на другой

Источник: http://adminland.ru/blog/dos-na-fleshke

Поделиться:
Нет комментариев

    Добавить комментарий

    Ваш e-mail не будет опубликован. Все поля обязательны для заполнения.