Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Lab6.DOC
Скачиваний:
1
Добавлен:
01.05.2025
Размер:
186 Кб
Скачать
☆

Завантаження і виконання програм

При завантаженні програми на початку блоку пам'яті, що відводиться для неї, (для СОМ-програм це уся вільна на даний момент пам'ять) створюється структура даних PSP (префікс програмного сегмента) розміром 256 байт (100h). Потім DOS створює копію поточного оточення для програми, що завантажується, поміщає повний шлях і ім'я програми в кінець оточення, заповнює поля PSP таким чином:

+00h: слово - 0CDh 20h - команда INT 20h. Якщо СОМ-програма завершується командою RETN, керування передається на цю команду.

+02h: слово - сегментна адреса першого байта після області пам'яті, виділеної для програми

+04h: байт - не використовується DOS

+05h: 5 байт - 9Ah 0F0h 0FEh 01Dh 0F0h - команда CALL FAR на абсолютну адресу 000C0h, записана так, щоб другий і третій байти складали слово, рівне розміру першого сегмента для СОМ-файлів.

+OAh: 4 байти - адреса оброблювача INT 22h (вихід із програми)

+OEh: 4 байти - адреса оброблювача INT 23h (оброблювач натискання Ctrl-Break)

+12h: 4 байти - адреса оброблювача INT 24h (оброблювач критичних помилок)

+16h: слово - сегментна адреса PSP процесу, з якого був запущений поточний

+18h: 20 байт - JFT - список відкритих ідентифікаторів, один байт на ідентифікатор, 0FFh - кінець списку

+2Ch: слово - сегментна адреса копії оточення для процесу

+2Eh: 2 слова - SS:SP процесу при останньому виклику INT 21h

+32h: слово - число елементів JFT (за замовчуванням 20)

+34h: 4 байти - далека адреса JFT (за замовчуванням PSP:0018)

+38h: 4 байти - далека адреса попереднього PSP

+3Ch: байт - флаг, що вказує, що консоль знаходиться в стані введення 2-байтного символу

+3Dh: байт - флаг, що встановлюється функцією 0В711h переривання 2Fh (при наступному виклику INT 21h для роботи з файлом ім'я файлу буде замінено повним)

+3Eh: слово - не використовується в DOS

+40h: слово - версія DOS, що поверне функція DOS 30h (DOS 5.0+)

+42h: 12 байт - не використовується в DOS

+50h: 2 байти - 0CDh 21h - команда INT 21 h

+52h: байт - 0CBh - команда RETF

+53h: 2 байти - не використовується в DOS

+55h: 7 байт - область для розширення першого FCB

+5Ch: 16 байт - перший FCB, заповнюваний з першого аргументу командного рядка

+6Сh: 16 байт - другий FCB, заповнюваний із другого аргументу командного рядка

+7Ch: 4 байти - не використовується в DOS

+80h: 128 байт - командний рядок і область DTA за замовчуванням.

і записує програму в пам'ять, починаючи з адреси PSP:0100h. Якщо завантажується ЕХЕ-программа, що використовує далекі процедури чи сегменти даних, DOS модифікує ці команди так, щоб використовувані в них сегментні адреси відповідали сегментним адресам, що одержали зазначені процедури і сегменти даних при завантаженні програми в пам'ять.

Під час запуску СОМ-програми регістри встановлюються таким чином:

AL = 0FFh, якщо перший параметр командного рядка містить неправильне ім'я диска , інакше - 00h

АН = 0FFh, якщо другий параметр містить неправильне ім'я диска, інакше - 00h

CS = DS = ES = SS = сегментна адреса PSP

SP = адреса останнього слова в сегменті (звичайно 0FFFEh; менше, якщо не вистачає пам'яті)

При запуску ЕХЕ-програми регістри SS:SP установлюються відповідно до сегмента стека, визначеного у програмі, потім у стек розміщується слово 0000h і виконується перехід на початок програми (PSP:0100h для СОМ, власна точка входу для ЕХЕ).

Усі ці дії виконує одна функція DOS - завантажити і виконати програму.

Функція DOS 4Bh: Завантажити і виконати програму

Вхід: АН = 4Bh

AL = 00h - завантажити і виконати;

AL = 01h - завантажити і не виконувати

DS:DX - адреса ASCIZ-рядка з повним ім'ям програми

ES:BX - адреса блоку параметрів ЕРВ:

+00h: слово - сегментна адреса оточення, що буде скопійовано для нового процесу (чи 0, якщо використовується поточне оточення)

+02h: 4 байти - адреса командного рядка для нового процесу

+06h: 4 байти - адреса першого FCB для нового процесу

+0Аh: 4 байти - адреса другого FCB для нового процесу

+0Eh: 4 байти - тут буде записаний SS:SP нового процесу після

його завершення (тільки для AL =01)

+12h: 4 байти - тут буде записана CS:IP (точка входу) нового процесу після його завершення (тільки для AL =01)

AL = 03h - завантажити як оверлей

DS:DX - адреса ASCIZ-рядка з повним ім'ям програми

ES:BX - адреса блоку параметрів:

+00h: слово - сегментна адреса для завантаження оверлея

+02h: слово - число, що буде використано в командах, що застосовують безпосередні сегментні адреси, -звичайно теж саме, що й у попереднім полі,0 - для СОМ-файлів

AL = 05h - підготуватися до виконання (DOS 5.0+)

DS:DX = адреса наступної структури:

+00h: слово - 00h

+02h: слово - біт 0 - програма - ЕХЕ

біт 1 - програма - оверлей

+04h: 4 байти - адреса ASCIZ-рядка з ім'ям нової програми

+08h: слово - сегментна адреса PSP нової програми

+OAh: 4 байти - точка входу нової програми

+OEh: 4 байти - розмір програми, включаючи PSP

Вихід:

CF= 0, якщо операція виконана, ВХ і DX модифікуються,

CF = 1, якщо відбулася помилка, АХ = код помилки (2 - файл не знайдений,5 - доступ до файлу заборонений, 8 - не вистачає пам'яті. 0Ah - неправильне оточення, 0Bh - неправильний формат)

Підфункціям 00 і 01 потрібно, щоб вільна пам'ять для завантаження програми була в потрібній кількості, так що СОМ-програми повинні скористатися функцією DOS 4Ah з метою зменшення відведеного їм блоку пам'яті до мінімально необхідного. При виклику підфункції 03 DOS завантажує оверлей у пам'ять, виділену поточним процесом, тому ЕХЕ-программы повинні переконатися, що її досить.

Ця функція ігнорує розширення файлу і розрізняє ЕХЕ- і СОМ-файли по першим двом байтам заголовка (MZ для ЕХЕ-файлів).

Підфункція 05 повинна викликатися після завантаження і перед передачею керування на програму, причому ніякі переривання DOS і BIOS не можна викликати після повернення з цієї підфункції і до переходу на точку входу нової програми.

Завантаженії і викликаний у такий спосіб програмі надається кілька способів завершення роботи. Спосіб, що найчастіше застосовується для СОМ-файлів, — команда RETN. При цьому керування передається на адресу PSP:0000, де розташовується код команди INT 20h. Відповідно програму можна завершити відразу, викликавши INT 20h, але обидва способи вимагають, щоб CS містив сегментну адресу PSP поточного процесу. Крім того, вони не дозволяють повернути код повернення, що може передати попередньому процесу інформацію про те, як завершилася запущена програма. Рекомендований спосіб завершення програми - функція DOS 4Ch.

Функція DOS 4Ch: Завершити програму

Вхід: АН = 4Ch

AL = код повернення

Значення коду повернення можна використовувати в пакетних файлах DOS як змінну ERRORLEVEL і визначати з програми за допомогою функції DOS 4Dh.

Функція DOS 4Dh: Визначити код повернення останнього процесу, що завершився

Вхід: АН = 4Dh

Вихід: АН = спосіб завершення:

00h - нормальний

01h - Ctrl-Break

02h - критична помилка

03h - програма залишилася в пам'яті як резидентна

AL = код повернення

CF=0

Завдання 3. ( 2 рівень, 3 рівень)

1. Наберіть наведену нище програму.

; shell.asm

; програма, що виконує функції командного інтерпретатора

; (визиваюча command.com для всіх команд, крім exit).

.model tiny

.code

.186

org 100h ; COM-програма

prompt_end equ '$' ; останній символ у запрошенні до введення

start:

mov sp,length_of_program+100h+200h ; переміщення стека на 200h

; після кінця програми (додаткові 100h - для PSP)

mov ah,4Ah

stack_shift=length_of_program+100h+200h

mov bx,stack_shift shr 4+1

int 21h ; звільнимо всю пам'ять після кінця програми і стека

; заповнимо поля EPB, що містять сегментні адреси

mov ax,cs

mov word ptr EPB+4,ax ; сегментна адреса командного рядка

mov word ptr EPB+8,ax ; сегментна адреса першого FCB

mov word ptr EPB+0Ch,ax ; сегментна адреса другого FCB

main_loop:

; побудова і виведення запрошення для введення

mov ah,19h ; Функція DOS 19h

int 21h ; визначити поточний диск

add al,'A' ; тепер AL = ASCII-код диска (A, B, C...)

mov byte ptr drive_letter,al ; помістити його в рядок

mov ah,47h ; Функція DOS 47h

mov dl,00

mov si,offset pwd_buffer

int 21h ; визначити поточну директорію

mov al,0 ; знайти нуль (кінець поточної директорії)

mov di,offset prompt_start ; у рядку з запрошенням

mov cx,prompt_l

repne scasb

dec di ; DI - адреса байта з нулем

mov dx,offset prompt_start ; DS:DX - рядок запрошення

sub di,dx ; DI - довжина рядка запрошення

mov cx,di

mov bx,1 ; stdout

mov ah,40h

int 21h ; виведення рядка в файл чи пристрій

mov al,prompt_end

int 29h ; виведення останнього символу в запрошенні

; одержати команду від користувача

mov ah,0Ah ; Функція DOS 0Ah

mov dx,offset command_buffer

int 21h ; введення

mov al,0Dh ; виведення символу CR

int 29h

mov al,0Ah ; виведення символу LF

int 29h ; (CR і LF разом - переведення рядка)

cmp byte ptr command_buffer+1,0 ; якщо введено порожній рядок,

je main_loop ; продовжити основний цикл

; перевірити, чи є введена команда командою 'exit'

mov di,offset command_buffer+2 ; адреса введеного рядка

mov si,offset cmd_exit ; адреса еталонного рядка 'exit',0Dh

mov cx,cmd_exit_l ; довжина еталонного рядка

repe cmpsb ; порівняти рядки

jcxz got_exit ; якщо рядки ідентичні - виконати exit

; передати інші команди інтерпретатору DOS (COMMAND.COM)

xor cx,cx

mov si,offset command_buffer+2 ; адреса введеного рядка

mov di,offset command_text ; параметри для command.com

mov cl,byte ptr command_buffer+1 ; розмір введеного рядка

inc cl ; врахувати 0Dh наприкінці

rep movsb ; скопіювати рядок

mov ax,4B00h ; функція DOS 4Bh

mov dx,offset command_com ; адреса ASCIZ-рядка з адресою

mov bx,offset EPB

int 21h ; виконати програму

jmp short main_loop ; продовжити основний цикл

got_exit:

int 20h ; вихід із програми (ret не можна, тому

; що переміщали стек)

cmd_exit db 'exit',0Dh ; команда 'exit'

cmd_exit_l equ $-cmd_exit ; її довжина

prompt_start db 'tinyshell:' ; підказка для введення

drive_letter db 'C:'

pwd_buffer db 64 dup (?) ; буфер для поточної директорії

prompt_l equ $-prompt_start ; максимальна довжина підказки

command_com db 'C:\COMMAND.COM',0 ; ім'я файлу

EPB dw 0000 ; використовувати поточне оточення

dw offset commandline,0 ; адреса командного рядка

dw 005Ch,0,006Ch,0 ; адреси FCB, переданих DOS

; нашій програмі при запуску (насправді

; вони не використовуються)

commandline db 125 ; максимальна довжина командного рядка

db ' /C ' ; ключ /C для COMMAND.COM

command_text db 122 dup (?) ; буфер для командного рядка

command_buffer db 122 ; тут починається буфер для введення

length_of_program equ 124+$-start ; довжина програми + довжина

; буфера для введення

end start

2. Проаналізувати программу за допомогою TD.

3. Разібрати логіку работи програми

4. Модифікуйте програму так, щоб вона коректно відображала довгі імена директорій в запрошенні для введення.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]