Программная модель МП
Выбери формат для чтения
Загружаем конспект в формате pdf
Это займет всего пару минут! А пока ты можешь прочитать работу в формате Word 👇
Программная модель МП
Microprocessor
Bus
Control
unit
Datapath
ALU
Reg.
Memory
Output
units
Input
units
What are microprocessors?
A microprocessor is a processor (or Central Processing Unit, CPU)
fabricated on a single integrated circuit.
Address bus
MAR
PC
IR
Control
unit
Control bus
X
Data bus
Y
ALU ACC
A simple microprocessor architecture
Other Commercial Microprocessors
PowerPC (IBM, Motorola)
Athlon, Dulon, Hammer (AMD)
Crusoe (Transmeta)
SPARC, UltraSPARC (Sun Microsystems)
TI’s TMS DSP chips (Texas Instruments)
StarCore (Motorola, Agere)
ARM cores (Advanced RISC Machines)
MIPS cores (MIPS Technologies)
Applications of Microprocessor-Based Systems
Computers
System performance is normally the most important design concern
...
Keyboard
Monitor
Disk
Other
peripherals
Bus
Microprocessor
Memory
Timing &
control
Block diagram of a computer
...
Interrupt
control
Applications of Microprocessor-Based Systems
Microcontrollers
A microcontroller is a simple
computer implemented in a
single VLSI chip.
In general, microcontrollers
are cheap and have low
performance
Microcontrollers are widely
used in industrial control,
automobile and home
applications
OSC.
RAM
ROM
CPU
I/O port
Timer
USART
Interrupt
A/D, D/A
Block diagram of a microcontroller
Applications of Microprocessor-Based Systems
ASICs
http://www.ti.com
Microprocessors are embedded
into ASIC chips to implement
complex functions
In general, it requires that
the microprocessors have
low power consumption and
take small silicon area
A TI baseband chip for cellular
phone applications
Class Objectives
Hardware architecture of microprocessor-based systems
Microprocessor architecture
Memory organization
I/O units of microprocessor-based systems
How to put them together
Programming of microprocessor-based systems
Intel 80x86 instruction set
Microprocessor Interrupt services
Assembly language programming
Topics
1.
Introduction of microprocessor-based systems
2.
Intel 8088 microprocessor architecture
3.
Memory organization in microprocessor-based systems
4.
Intel 80x86 instruction set
5.
Assembly language programming
6.
I/O systems
7.
Microprocessor interrupt and interrupt services
9.
Disk systems and file
10. Topics in advanced computer architecture
Принципы фон Неймана
•
•
•
•
•
Использование двоичной системы счисления в вычислительных
машинах.
Программное управление ЭВМ. Работа ЭВМ контролируется
программой, состоящей из набора команд. Команды выполняются
последовательно друг за другом. Созданием машины с хранимой в
памяти программой было положено начало тому, что мы сегодня
называем программированием.
Память компьютера используется не только для хранения данных, но
и программ.
Ячейки памяти ЭВМ имеют адреса, которые последовательно
пронумерованы. В любой момент можно обратиться к любой ячейке
памяти по ее адресу. Этот принцип открыл возможность использовать
переменные в программировании.
Возможность условного перехода в процессе выполнения программы.
Не смотря на то, что команды выполняются последовательно, в
программах можно реализовать возможность перехода к любому
участку кода.
Системы счисления
Десятичная
Двоичная
Шестнадцатеричная
Десятичная система счисления
Двоичная система счисления
Шестнадцатиричная система
счисления
INTEL 8086
General Purpose Registers
Представление положительных и
отрицательных чисел
Режимы адресации (начало)
Режимом адресации - способ определения
местонахождения операнда.
Различают семь основных режимов адресации данных,
которые можно разделить на две группы.
К первой относят режимы, в которых место, в котором
находится операнд, указывается непосредственно в
команде.
Это – непосредственный,
регистровый и
прямой режимы адресации.
Непосредственный режим
адресации
Операнд располагается в самой команде в виде
двоичного числа.
Операнд обычно представляет собой константу,
которую надо куда-то переслать, к чему-то прибавить,
с чем-то сравнить и т.д.
Прямой режим адресации
Прямая (или абсолютная) адресация предполагает,
что в команде после кода операции располагается
внутрисегментный адрес ячейки памяти. По этому
адресу хранится операнд.
Регистровый режим адресации
В команде указан один из регистров процессора, в
котором хранится операнд.
CPU
Сегментирование памяти
Для хранения кодов адресов памяти используются не отдельные
регистры, а пары регистров:
• сегментный регистр определяет адрес начала сегмента (то есть
положение сегмента в памяти);
• регистр смещения определяет положение рабочего адреса внутри
сегмента.
Формирование физического
адреса памяти из адреса
сегмента и смещения
Физический 20-разрядный адрес памяти,
выставляемый на внешнюю шину адреса, образуется
путем сложения смещения и адреса сегмента со
сдвигом на 4 бита. Положение этого адреса в памяти
показано на рисунке.
Например, сегмент в шестнадцатеричном виде равен
1200, а смещение — 3АВЕ.
Сегмент (1200) 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0
Смещение (3АВЕ)
0011110011011110
Адрес (15АВЕ)
00010101110011011110
Сегментация памяти
Память
00000
00010
+ FFFF
1000F
00010
00020
1 сегмент
2 сегмент
3 сегмент
1000F
10010
Чаще всего используемой командой процессора,
является команда
MOV Operand_1, Operand_2
Данная команда копирует содержимое правого операнда
в левый операнд.
Эта команда, равно как и практически все остальные
команды, оперирующие парой операндов, удовлетворяет
двум важным условиям:
Рассмотрим команду
mov
AH, 2h
B
Команда
MOV
MOV
MOV
MOV
MOV
MOV
MOV
MOV
4
2
Операнды
AL, imm8
CL, imm8
DL, imm8
BL, imm8
AH, imm8
CH, imm8
DH, imm8
BH, imm8
Код
B0
B1
B2
B3
B4
B5
B6
B7
Рассмотрим команду
mov
DL, 2Ah
B 2 2 A
Команда
MOV
MOV
MOV
MOV
MOV
MOV
MOV
MOV
Операнды
AL, imm8
CL, imm8
DL, imm8
BL, imm8
AH, imm8
CH, imm8
DH, imm8
BH, imm8
Код
B0
B1
B2
B3
B4
B5
B6
B7
Формат кодирования команд ассемблера
[метка] [префикс] команда [операнд(ы)] ; [комментарий]
Метка (если имеется), команда и операнд (если имеется) pазделяются по
крайней мере одним пробелом или символом табуляции.
Максимальная длина строки - 132 символа
Метка
count
Команда Операнд
db
mov
1
ax,
;Имя, команда, один операнд
;Команда, два операнда
Метки
Метка в языке ассемблера может содержать следующие
символы:
Буквы:
Цифры:
Спецсимволы:
знак вопроса
точка
знак
подчеркивание
доллар
от a до z и от a до z
от 0 до 9
(?)
(.) (только первый символ)
(@)
(_)
($)
Метки - ограничения
Первым символом в метке должна быть буква или спецсимвол.
Ассемблер не делает различия между заглавными и
строчными буквами.
Максимальная длина метки - 31 символ. Примеры меток:
count,
page25,
$e10, .cursor
Рекомендуется использовать описательные и смысловые
метки.
Имена регистров, например, AX, DI или AL и т.д. являются
зарезервированными и используются только для указания
соответствующих регистров.
Функции DOS
Код функции в рег-р AH
Заполнение других РОН в соответствии
с описанием функции
Вызов DOS int 21h
Инструкция int - interrupt – программное
прерывание
Вывод на экран символа
2h
AH – номер функции
41h DL – код символа
INT 21H – вызов функции DOS
mov
mov
INT
INT
AH,
DL,
21H
20H
02h
2Ah
; загружаем в AH число 02h
; загружаем в DL число 2Ah
; печать * на экране
; exit
Первая программа
code_seg
segment
assume cs:code_seg, ds:code_seg
org
100h
start:
mov
AH, 2h
mov
DL, 2Ah
; в DL ASCII код
int
21h
int
20h
; выход из программы
code_seg ends
end
start
Листинг трансляции
Файл PRIM1.LST
Turbo Assembler Version 3.1
PRIM1.ASM
1
0000
2
3
4
0100
5
0100 B4 02
6
0102 B2 2A
7
0104 CD 21
8
0106 CD 20
9
0108
10
21/02/05 01:42:50
Page 1
code_seg segment
assume CS:code_seg, DS:code_seg
org 100h
start:
mov AH, 2h
mov DL, 2Ah
int 21h
int 20h
code_seg ends
end start
Вывод на экран строки символов
Функция 02h – Выводит 1 символ
Функция 09Н – печатает целую строку,
пока не встретит символ ‘$’
mov
lea
Int 21H
AH,
DX,
09
mes
; 09h≡ 9H ≡ 9 ≡ 11O ≡ 1001B
; адрес сообщения
Пример 2
code_seg segment
assume cs:code_seg,ds:code_seg,ss:code_seg
org 100h
start:
jmp begin
mes
DB 13,10,’Привет',13,10,'$'
begin:
mov AH, 9h
lea DX, mes
int 21h
int 20h
code_seg ends
end start
Листинг трансляции (пример 2)
Turbo Assembler
Version 3.1
PRIM2.ASM
1
0000
2
cs:code_seg,ds:code_seg,ss:code_seg
3
4
0100
5
0100 EB 0C 90
6
0103 0D 0A AF E0 A8 A2 A5+
7
E2 0D 0A 24
8
010E
9
010E B4 09
10
0110 BA 0103r
11
0113 CD 21
12
0115 CD 20
13
0117
14
13 10
21/02/05 01:17:20
Page 1
code_seg segment
assume
org 100h
start:
jmp begin
mes DB 13,10,'привет',13,10,'$'
begin:
mov AH, 9h
lea DX, mes
int 21h
int 20h
code_seg ends
end start
Вывод на экран шестнадцатеричной цифры
Сhar
ASCII Code (HEX)
/
2F
30
1
31
2
32
3
33
4
34
5
35
6
36
7
37
8
38
9
39
:
3A
;
3B
3C
=
3D
3E
?
3F
@
40
mov
mov
цифры 0
int 21h
AH, 02h
DL, 30h ; вывод
+ 30h
mov AH, 02h
mov
DL, 39h ; вывод
цифры 9
int 21h
7
Вместо хранения таблицы
ASCII в программе, код цифры
можно сформировать
сложением цифры и константы
30h
Продолжение ASCII таблицы
@
40
A
41
B
42
C
43
D
44
E
45
F
46
G
47
mov AH, 02h
mov DL, 41h ; вывод цифры (буквы) A
int 21h
+037H
РОН = РОН+ 030h
if РОН 03Ah
then РОН=РОН+07h
Print РОН
Пример:
0A+30h=3Аh
3Ah+07h=41h
На ассемблере:
mov
AH,
02h
mov
DL,
BL
add
DL,
030h
cmp
DL,
3Ah
jl
print_letter
add
DL,
07h
print_letter:
int
21h
Вывод на экран содержимого младшей тетрады регистра BL
code_seg segment
assume CS:code_seg,DS:code_seg,SS:code_seg
org
100h
start:
mov
AH,
9h
; функция DOS для вывода стр.символов ( $ ; ограничитель стр.)
lea
DX,
mes
;≡ mov
DX, offset mes
int
21h
; print string
;
mov
BL,
0Fh
; загружаем в BL известное число, чтобы
; проверить правильность вывода
mov
AH,
02h
mov
DL,
BL
add
DL,
30h
cmp
DL,
3Ah
jl
print
add
DL,
07h
print:
int
21H
int
20h
mes
DB 13,10,'я печатаю HEX содержимое мл. тетрады регистра BL',13,10,'$‘
code_seg ends
end start
Процедура
Это список инструкций, который можно вызвать из различных мест
программы. Аналог функции в С и подпрограммы.
Процедуру можно вызвать с помощью
CALL имя процедуры
выход из процедуры ret. Адрес возврата запоминается в стеке.
Call
…
…
prim
prim
prim
proc [near], [far]
инструкция
...
инструкция
...
ret
endp
тело процедуры
Вывод на экран содержимого регистра BL
mov
rcr
call
mov
call
int
;
print_hex
mov
and
add
cmp
jl
add
print:
ret
print_hex
DL,
BL
DL,
4
print_hex
DL,
BL
print_hex
20h
proc near
AH,
02h
DL,
0Fh
DL,
030h
DL,
03Ah
print
DL,
07h
int
21h
endp
; сдвиг вправо на 4 бита
Команды циклического сдвига
CF
1
1
1
1
1
1
1
1
1
1
1
1
rcr
DL,
4
результат
rcl
DL,
результат
4
Поразрядное логическое AND
1
1
1
1
1
1
1
1
1
and
DL,
результат
0Fh
Cформировать байт из 2-х шестнадцатиричных цифр
code_seg segment
assume cs:code_seg,ds:code_seg,ss:code_seg
org 100h
start:
jmp
write_string
mes:
DB 13,10,'Я формирую байт из 2х вводимых HEX цифр',13,10,'$'
write_string
proc
near
mov
AH,
9h
; функция DOS для вывода строки символов
; $ - ограничитель строки
lea
DX,
mes
int
21h
; print string
write_string
endp
;
main
proc
near
; Ввод шестнадцатеричных цифр
call
inp_hex
mov
DL,AL
rol
DL,4
call
inp_hex
add
DL,AL
int
20h
main
endp
inp_hex proc
push
cycle:
mov
int
cmp
jb
cmp
ja
cmp
ja
mov
mov
int
sub
pop
ret
near
DX
AH,
21h
AL,
beep
AL,
beep
AL,
cont
AH,
DL,
21h
AL,
DX
08h
; function - input char without echo
030h
; if < beep (unsigned)
046h
; if > beep (unsigned)
039h
02h
AL
; print char
030h
; code ASCII-030h--> hex digit
beep:
mov
mov
int
jmp
AH,
DL,
21h
short
02h
07h
cycle
cont:
cmp
AL,
jb
beep
mov
AH,
mov
DL,
int
21h
sub
AL,
pop DX
ret
inp_hex endp
code_seg ends
end start
041h
02h
AL
037h
; code of beep
Домашнее задание
Вывод содержимого регистра BX
Ввод 4-х шестнадцатиричных цифр и
формирование из них содержимого
регистра BX
Вывод на экран двоичного числа
code_seg segment
assume cs:code_seg,ds:code_seg,ss:code_seg
org 100h
start:
jmp begin
mes: DB 13,10,'я печатаю двоичное содержимое регистра BX',13,10,'$'
begin:
mov
AH, 9h
; функция DOS для вывода строки символов
; $ - ограничитель строки
lea
DX, mes
int
21h
; print string
;
mov
BX,
0A3C5h
mov
CX,
16
mov
AH,
02
; функция- печать символа из DL
cycle:
rcl
BX,
1
; цикл. сдвиг BX на 1 разряд влево
xor
DL,
DL
; сложение с учетом значения флага переноса CF
adc
DL,
30h
int
21H
приемник=приемник+источник+CF
loop
cycle
int
20h
code_seg ends
end start
Если шестнадцатеричное число начинается с буквы, то в программе такое число
должно записываться с ведущим 0 (для того, чтобы отличить от меток или от
обозначения регистров), Например, число А – 0Ah, а не Ah – чтобы не спутать с
регистром AH.
Работа с файлами
В DOS доступны следующие функции работы с файлами:
39h – создать каталог файлов (аналогично функции MKDIR DOS)
3Аh – удалить каталог
3Вh – сменить текущий каталог
3Сh – создать файл (CREATE)
3Dh – открыть файл (OPEN)
3Eh – закрытие файла (CLOSE)
3Fh – читать данные из файла или устройства (READ)
40h – записать данные в файл или на устройство (WRITE)
41h – удалить файл (DELETE)
42h – переместить указатель текущей позиции в файле
43h – получить/установить аттрибуты файла
56h – переименовать файл
57h – получить/установить дату и время последнего изменения файла
5Ah – создать временный файл
5Bh – создать новый файл (В отличие от 3Сh, если файл уже
существует, то 5Bh сообщает об ошибке).
5Сh – блокировать/разблокировать доступ к файлу.
Работа с каталогом
39h – создать каталог файлов (аналогично функции MKDIR DOS)
перед использованием
DS:DX – адрес ASCIIZ – строки –имя пути для нового каталога.
Ошибки в АХ: 3 - путь не найден
5 – ошибка в доступе
3Аh – удалить каталог
DS:DX – адрес ASCIIZ – строки –имя пути для нового каталога.
Ошибки в АХ те же
3Вh – сменить текущий каталог
DS:DX – адрес ASCIIZ – строки –имя пути для нового каталога
Ошибки в АХ: 3 - путь не найден
АSCIIZ-строка
Функции DOS, работающие с файлами, требуют
задания имени и пути к файлу в виде ASCIIZ строки.
ASCIIZ строка состоит из обычных ASCII символов,
за которыми следует нулевой байт. Типичная строка
выглядит наподобие:
C:\DIRECTORY1\DIRECTORY2\FILENAME.EXT
В качестве разделителя может быть как прямая, так
и обратная косая черта. (имя дисковода может быть
опущено)
Функция - создать файл
3Сh – создать файл (CREATE)
открывает существующий или создает новый
файл.
DS:DX – адрес ASCIIZ строки.
СХ – атрибут файла
АХ – возвращается логический номер
файла.
Логический номер файла или дескриптор – это
16-битовое число, используемое DOS как
указатель на систему таблиц. Логический номер
освобождается после закрытия файла и может
быть использован повторно.
Особенности функции - CREATE
После выполнения всех необходимых
действий по созданию файла, функция 3Сh
возвращает в регистре АХ дескриптор
созданного файла, которым мы можем в
дальнейшем пользоваться для записи в файл
или чтения из него.
Если файл с заданным именем уже
существовал, функция 3Сh фактичеки
уничтожит имеющийся файл и создаст новый
с тем же именем.
Атрибут файла
В СХ, а точнее, в СL задается – атрибут файла
0 – отсутствие атрибутов
1 – только чтение
2 – скрытый файл
4 – системный
8 – метка тома
16 = 10h – подкаталог
32 = 20h – архив – этот разряд сброшен для всех
файлов, которые изменялись после последнего
копирования
Существует пять стандартных логических номеров 0 - 4, которые
автоматически предоставляются любой программе
Логически
й номер
Использование
Устройство по
умолчанию
Стандартный ввод (клавиатура)
CON:
1
Стандартный вывод (экран)
CON:
2
Стандартное устройство вывода при
ошибке
CON:
3
Стандартное вспомогательное
устройство
AUX:
4
Стандартное устройство печати
PRN:
Остальные номера с большими логическими номерами DOS
предоставляет по требованию
Проверка ошибок
Так как АХ используется для возврата как логического
номера, так и кода ошибки, то в качестве признака
ошибки используеся флаг CF (флаг переноса)
Возможны коды возврата:
3 – путь не найден
4 – нет свободного логического номера
5 – отказ в доступе – либо в каталоге нет места для
новой записи, либо уже существующий файл
защищен от записи и не может быть открыт для
вывода данных.
Файловая функция
mov AH, 3Ch ; AH 3Ch, 3D, ….
….
….
int 21h
нет
Произошла ошибка,
в AX – код ошибки
CF=0 ?
да
Ошибок нет – в AX - дескриптор
Анализ системных ошибок
MOV
AH, Function
; Номер функции
; Заполнение регистров параметрами,
; необходимыми для
; выполнения данной функции
INT
21h
JC
Error ; флаг СF установлен
; Нет, нормальное продолжение программы
…………
Error: …
; Да, анализ ошибок в АХ
CMP
AX, 1
JE
Error1
CMP
AX, 2
JE
Error2
…..
Функция 3Dh - открыть файл (OPEN)
DS:DX – адрес строки, содержащей путь и имя файла
AL - код режима открытия
Рассмотрим только разряды 02.
2
1
1
1
Только чтение
Только запись
Чтение/запись
Бит 7 – бит наследования
Биты 4-6 – режимы совместного использования.
Коды возврата в АХ:
2 – файл не найден
3 – путь не найден
4 – нет свободного логического номера файла
5 – отказ в доступе
12 – недопустимый код доступа
3Eh – закрыть файл (CLOSE)
Логический номер в ВХ
Номер функции 3Eh AH
int
21h
Код ошибки:
6 – ошибочный логический номер
3Fh – читать данные из файла (READ)
Логический номер
Число байт
Адрес буфера
ВХ
СХ
DS:DX
В АХ возвращается число действительно считанных байтов
Если в АХ 0, то программа пыталась считать данные за концом
файла
Код ошибки:
5 – отказ в доступе
6 – ошибочный логический номер
Процесс чтения из файла
память
устройство
Указатель
текущей
позиции
в файле
файл
Область
программы
DS:DX
Буфер
ввода
Размер число
байт в
CX
Дескриптор
в
BX
40h – записать данные в файл (WRITE)
Логический номер ВХ.
Число байт СХ
Адрес выводимых данных DS:DX
В АХ возвращается число действительно
выведенных байтов.
Проверка состоит их 2х шагов
СF=1?
AX = CX?
Если АХ<СХ – на диске не хватило места.
41h – удалить файл (DELETE)
DS:DX – адрес строки, определяющей
имя файла.
Заполнители ? и * в имени файла
использовать нельзя.
42h – переместить указатель текущей
позиции в файле
Логический номер – ВХ.
Новое положение указателя задается путем загрузки в регистр AL
исходного положения указателя, а в пару регистров СХ:DX – число
байтов, на которое необходимо переместить указатель. Загружаемое в
пару регистров СХ:DX смещение в байтах – это 32-битовое число без
знака. В СХ – старшая часть, в DX – младшая. Если смещение меньше
65535, то СХ = 0. Исходное положение в АL задается с помощью так
называемого кода метода:
АL = 0 – смещение берется от начала файла и указатель изменяется
на СХ:DX от этой точки
АL = 1 – смещение берется от текущей позиции
АL = 2 – смещение берется от конца файла.
В последнем случае в паре регистров СХ:DX обычно ноль, чтобы
определить текущий размер файла. Если задать смещение 0 и
запросить метод 0 – то возврат в начало файла.
Коды ошибок:
1 – ошибочный номер функции
6 – ошибочный логический номер
Пример 1
; создание файла
MOV
AH, 3Ch
; Функция CREATE
MOV
CX, 0
; Без атрибутов
MOV
DX, OFFSET Filename
; Адрес имени Файла
INT
21h
; Вызов DOS
Mov
Handler, AX
; сохранить дескриптор
; запись строки в файл
MOV
AH, 40h
; Функция записи
MOV
BX, Handler
; Дескриптор
MOV
CX, BufLen
; Число записываемых байтов
MOV
DX, OFFSET Buf
; Адрес буфера
INT
21h
; закрытие файла
MOV
AH, 3Eh
;
MOV
BX, Handler
INT 21h
; завершение программы
MOV
AX, 4C00h
; Функция завершения
INT
21h
; данные
Buf
DB
‘0123456789’ ; Данные, записываемые в файл
BufLen
EQU $ - Buf ; Длина данных. $ - текущее значение счетчика
Handler
DW
?
; Ячейка для дескриптора
Filename
DB
‘D:\test\myfile.txt’,0
; ASCIIZ строка спецификации файла
Пример 2
; Открыть файл
MOV
AH, 3Dh
; функция OPEN
MOV
AL, 2
; Доступ для чтения/записи
MOV
DX, OFFSET Filename ; Адрес имени файла
INT
21h
MOV
Handler, AX
; Сохранение дескриптора
; Пытаемся прочитать 80 байт
MOV
AH, 3Fh
; Функция READ
MOV
BX, Handler
; Дескриптор
MOV
CX, 80
; Сколько читать
MOV
DX, OFFSET BufIn
; Сюда читать
INT
21h
MOV
CX, AX
; сколько реально прочитано
; Вывод прочитанного на экран
MOV
AH, 40h
; функция WRITE
MOV
BX, 1
; Дескриптор стандартного вывода
MOV
DX, OFFSET BufIn
; отсюда выводить (СХ байт)
Int
21h
; Данные
BufIn
DB
80 dup (‘ ‘) ; буфер ввода
Handler
DW
?
Filename DB
‘D:\test\myf.txt’,0 ;спецификация файла
Функции для работы с файлами
43h – получить, установить аттрибуты файла
56h – переименовать файл
57h – получить/установить дату и время последнего изменения
файла
в DOS 3.00
5Ah – создать временный файл
CX - атрибут
DS:DX – имя пути, должно заканчиваться ‘\’
Строка должна иметь длину на 12 байт больше длины имени
пути, чтобы DOS могла бы дополнить уникальным именем
файла.
5Bh – создать новый файл. В отличие от 3Сh, если файл уже
существует, то 5Bh
сообщает об ошибке.
5Сh – блокировать/разблокировать доступ к файлу.
Программный загрузчик
Ц е л ь: Понять как DOS загружает
программу в память и управляет ее
исполнением
DOS состоит из четырех основных программ
1
Блок начальной загрузки находится на первом секторе нулевой
дорожки дискеты DOS, а также на любом диске, форматированном
командой FORMAT/S.
2
Программа IBMBIO.COM обеспечивает интерфейс низкого уровня
с программами BIOS в ROM. При инициализации программа
IBMBIO.COM определяет состояние всех устройств и оборудования, а
затем загружает программу COMMAND.COM
3
Программа IBMDOS.COM обеспечивает интерфейс высокого
уровня с программами. Эта программа управляет оглавлениями и
файлами на диске, блокированием и деблокированием дисковых
записей, функциями int 21h, а также содержит ряд других сервисных
функций.
4
Программа COMMAND.COM выполняет различные команды DOS,
такие как DIR или CHKDSK, а также выполняет com, exe и batпрограммы. Она состоит из трех частей: небольшая резидентная
часть, часть инициализации и транзитная часть. Программа
COMMAND.COM отвечает за загрузку выполняемых программ с
диска в память.
Распределение адресного пространства в DOS
Физический
адрес
Содержимое
Объем
(Кб)
00000h
таблица векторов прерываний
640
00400h
Область связи с ROM (ПЗУ)
00500h
Область связи с DOS
00600h
IBMBIO.COM
xxxx0h
IBMDOS.COM
Буфер каталога, Дисковый буфер,Таблица параметров дисковода
или таблица распределения файлов (FAT, по одной для каждого
дисковода)
xxxx0h
Резидентная часть COMMAND.COM
xxxx0h
Внешние команды или утилиты (com или exe-файлы)
xxxx0h
Пользовательский стек для com-файлов (256 байт)
xxxx0h
Транзитная часть COMMAND.COM, записывается в самые
старшие адреса памяти.
A0000h
Графический видеобуфер
64
B0000h
Свободные адреса
32
B8000h
Текстовый видеобуфер
32
C0000h
ПЗУ-расширения BIOS
64
D0000h
Свободные адреса
64
E0000h
ПЗУ BIOS
128
Командный процессор COMMAND.COM
Система загружает три части программы COMMAND.COM
в память во время сеанса работы постоянно или
временно. Ниже описано назначение каждой из трех
частей COMMAND.COM:
1. Резидентная часть непосредственно следует за программой
ibmdos.com. Резидентная часть обрабатывает все ошибки
дисковых операций ввода-вывода и управляет следующими
прерываниями:
int 22h
Адрес программы обработки завершения задачи.
int 23h
Адрес программы реакции на ctrl/break.
int 24h
Адрес программы реакции на ошибки дисковых
операций чтения/записи или сбойный участок
памяти в таблице распределения файлов (FAT).
int 27h
Завершение работы, после которого программа
остается резидентной.
Часть инициализации COMMAND.COM
2.
Часть инициализации непосредственно следует
за резидентной частью и содержит средства
поддержки autoexec-файлов. В начале работы
системы данная часть первой получает
управление. Она определяет сегментный адрес,
куда система должна загружать программы для
выполнения. Ни одна из этих программ
инициализации не потребуется больше во время
сеанса работы. Поэтому первая же команда
вводимая с клавиатуры и вызывающая загрузку
некоторой программы с диска перекрывают часть
инициализации в памяти.
3. Транзитная часть COMMAND.COM
Транзитная
часть загружается в самые старшие адреса памяти.
Выводит на экран приглашение C>, вводит и выполняет запросы.
Содержит настраивающий загрузчик и предназначена для загрузки
COM- или EXE-файлов с диска в память для выполнения.
Если поступил запрос на выполнение какой-либо программы, то
транзитная часть строит префикс программного сегмента (PSP)
непосредственно вслед за резидентной частью COMMAND.COM.
Затем она загружает запрошенную программу с диска в память по
смещению 100h от начала программного сегмента, устанавливает
адреса выхода и передает управление в загруженную программу.
Ниже приведена данная последовательность:
IBMBIO.COM
IBMDOS.COM
COMMAND.COM (резидент)
Префикс программного сегмента
Выполняемая программа
...
COMMAND.COM (транзитная часть, может быть перекрыта).
Выполнение команды RET или INT 20H в конце программы
приводит к возврату в резидентную часть COMMAND.COM.
Если транзитная часть была перекрыта, то резидентная
часть перезагружает транзитную часть с диска в память
Образ памяти программы типа .COM
После загрузки программы все четыре сегментных регистра
указывают на начало единственного сегмента. Указатель стека
автоматически инициализируется числом FFFEh. Таким
образом программе выделяется 64 Кб адресного
пространства, всю нижнюю часть которого занимает стек.
CS, DS, ES, SS
PSP
IP = 0100h
Программа и
данные
стек
SP = FFFEh
ПРЕФИКС СЕГМЕНТА ПРОГРАММЫ (PSP)
(program segment prefix)
PSP – это область размером 100h (25610),
которая содержит информацию,
необходимую DOS для обеспечения работы
программы.
Для СОМ-программы сегментные регистры
(CS, DS и ES) указывают на начало PSP, а
программа размещается сразу вслед за PSP,
то есть со смещением 100h от начала PSP.
Структура префикса программного сегмента
Поле
Смещение от
начала PSP
Размер поля
(десятичн)
Значение
1
00h
2 байт
Команда INT 20h
2
02h
2 байт
Размер памяти в параграфах
3
04h
1 байт
Резерв, обычно 0
4
05h
5 байт
Вызов диспетчера функций DOS
5
0Ah
4 байт
Вектор завершения работы (Адрес завершения CS:IP)
6
0Eh
4 байт
Вектор прерывания работы (Адрес выхода Ctrl-Break)
7
12h
4 байт
Вектор ошибки (Адрес выхода по ошибке)
8
16h
22 байт
Используется DOS
9
2Ch
2 байт
Указатель строки связи с окружающей средой
10
2Eh
34 байт
Рабочая область DOS
11
50h
3 байт
Коменды INT 21h, RETF
12
53h
2 байт
Зарезервировано
13
55h
7 байт
Расширение FCB #1
14
5Ch
9б айт
FCB #1
15
65h
7 байт
Расширение FCB #2
16
6Ch
20 байт
FCB #2
17
80h
1 байт
Длина параметров
18
81h
127 байт
Параметры
19
80h
128 байт
Область передачи информации
Поле 1
Прерывание INT 20h используется для завершения программы и
передачи управления DOS. Прерывание INT 20h эквивалентно AH=0
(функции 0) INT 21h. INT 20h не закрывает все открытые этой
программой файлы.
Более совершенная функция выхода из программы 4Сh - завершает
работу программы и передает тому, кто ее вызвал, код возврата. Если
программа была вызвана как подпрограмма, то вызвавшая ее
программа может получить код возврата с помощью функции 41h.
Если программа вызывалась командой DOS, то код возврата может
быть проверен в командном файле с помощью команды
ERRORLEVEL. Код возврата возвращается в AL. При выполнении этой
функции DOS автоматически закрывает все файлы, открытые с
помощью 3Dh и, возможно, 3Сh.
Итак, команда INT 20h находится в начале PSP . Таким образом,
можно выйти из программы, просто передав управление на эту ячейку
(при условии, что CS указывает на PSP).
Размещение в начале PSP команды INT 20h может быть объяснено
тем, что если LINK обнаруживает в программе неудовлетворенную
внешнюю ссылку, то он присваивает ее адресу смещения 0. при
передаче управления на эту ссылку выполнится команда, находящаяся
в начале PSP, то есть INT 20h, - что вызовет завершение программы.
Поле 2
сколько памяти доступно – содержит номер последнего блока
памяти, доступной DOS. Умножив это число на 16, получим
общий объем памяти в байтах. То же самое значение, что и в
поле 2, возвращает команда CHKDSK DOS. Если программе
необходима вся доступная память, то она должна использовать
это поле PSP для определения того, сколько памяти она может
использовать.
Программа также может получать и возвращать память с
помощью вызова функции 4Аh.
Поле 4
Это команда вызова с атрибутом дистанции FAR диспетчера
функций DOS. Следовательно, эта команда содержит полный
адрес диспетчера. Этот полный адрес не только указывает на
диспетчера, но при этом его смещение указывает, сколько
памяти в сегменте команд мы можем использовать (до FFF0, то
есть на 16 байт меньше, чем 64 КБайт). Это смещение
расположено в PSP со смещением 6, сразу за кодом команды,
имеющим смещение 5.
Это поле, в отличие от предыдущего, должно работать с
большинством многооконных и мультипрограммных систем.
Если DOS может предоставить более 64 Кбайт, то определить,
на сколько больше, мы можем по полю 2.
Поле 5, 6 и 7
Это полные адреса, для трех прерываний по завершению
работы, по Ctrl-Break (Ctrl-C) и по ошибке. Если мы хотим
использовать свои программы для обработки этих ситуаций, то
должны временно изменить эти слова. В конце работы вектора
должны быть восстановлены
Поле 9
Полный адрес набора строк описания окружающей среды. это
набор ASCIIZ строк. каждая строка имеет форму
ИМЯ = значение
Обычно эта среда содержит по крайней мере имя СОМSPEC
(используемое DOS для поиска на диске файла
COMMAND.COM).
Поле 11
Содержит команды INT 21h и команду возврата управления
вызвавшей программе RETF ( RET с дальним аттрибутом
дистанции FAR).
Таким образом, вместо INT 21h мы можем косвенно через
смещение в PSP вызвать эту команду.
Поле 13, 14, 15 и 16
Содержит команды INT 21h и команду возврата управления
вызвавшей программе RETF ( RET с дальним аттрибутом
дистанции FAR).
Таким образом, вместо INT 21h мы можем косвенно через
смещение в PSP вызвать эту команду.
Поле 17, 18
Обеспечивают нашим программам доступ к параметрам
командной строки. Поле 17 содержит полную длину строки
параметров (которая может быть от 0 до 127), а поле 18 – ее
содержимое.
Передаваемая строка не содержит имя вызванной программы.
Строка начинается с символа, следующего в команде вызова
сразу за именем программы; обычно это пробел. Разделители,
пробелы и запятые не отбрасываются и не снимаются. Любые
параметры переадресации ввода/вывода,
такие как
< ввод
> вывод
изымаются DOS и строка реконструируется таким образом, как
будто этих элементов не было вообще. В результате этих двух
операций программа не может узнать о переадресации
стандартного ввода-вывода и не может узнать свое
собственное имя.
Поле 19
Это область, которая по умолчанию используется DOS для
обмена данными с диском (DTA – Disk Transfer Area). Это
буфер длиной 128 байт, имеющий смещение 80h.
Используется всегда, когда мы пользуемся служебной
процедурой DOS для обмена с диском, не задавая в
качестве буфера свою собственную область.
Команды обработки строк
Для обработки строковых данных ассемблер имеет пять команд
обработки строк:
movs -
lods -
stos cmps -
scas -
переслать один байт или одно слово из одной
области памяти в другую;
загрузить из памяти один байт в регистр al или
одно слово в регистр ax;
записать содержимое регистра al или ax в память;
сравнить содержимое двух областей памяти,
размером в один байт или в одно слово;
сравнить содержимое регистра al или ax с
содержимым памяти.
Префикс rep позволяет этим командам обрабатывать строки
любой длины.
СВОЙСТВА ОПЕРАЦИЙ НАД СТРОКАМИ
Команда
Операнды
Байт
Слово
movs
es:di, ds:si
movsb
movsw
Lods
al,si или ax,si
lodsb
lodsw
Stos
di,al или di,ax
stosb
stosw
Cmps
si,di
cmpsb
cmpsw
Scas
di,al или di,ax
scasb
scasw
rep: ПРЕФИКС ПОВТОРЕНИЯ ЦЕПОЧЕЧНОЙ КОМАНДЫ
Несмотря на то, что цепочечные команды имеют отношение к одному
байту
или одному слову, префикс rep обеспечивает повторение команды
несколько
раз.
Префикс кодируется непосредственно перед цепочечной
командой, например, rep movsb.
Для использования префикса rep необходимо установить начальное
значение в регистре cx.
При выполнении цепочечной команды с префиксом rep происходит
уменьшение на 1 значения в регистре cx до нуля.
Таким образом, можно обрабатывать строки любой длины.
Флаг направления определяет направление повторяющейся операции:
для направления слева направо необходимо с помощью команды cld
установить флаг df в 0;
для направления справа налево необходимо с помощью команды std
установить флаг df в 1.
Пример: выполняется пересылка 20 байт из string1 в string2
Предположим, что оба регистра ds и es инициализированы адресом
сегмента данных
string1
string2
db
20 dup('*')
db
20 dup(' ')
...
cld
mov cx,20
lea di,string2
lea si,string1
rep movsb
;Сброс флага df
;Счетчик на 20 байт
;Адрес области "куда«
;Адрес области "откуда"
;Переслать данные
При выполнении команд cmps и scas возможна установка флагов
состояния, так чтобы операция могла прекратиться сразу после
обнаружения необходимого условия. Ниже приведены модификации
префикса rep для этих целей:
rep
-
повторять операцию, пока cx не равно 0;
repz
или repe повторять операцию, пока флаг zf показывает
"равно или ноль". Прекратить операцию при флаге zf, указывающему
на не равно или не ноль или при cx равном 0;
repne
или repnz повторять операцию, пока флаг zf показывает "не
равно или не ноль". Прекратить операцию при флаге zf,
указывающему на "равно или нуль" или при cx равным 0.
Пример проверки командной строки
repe
mov
cmp
je
xor
cld
mov
mov
mov
scasb
repe
dec
mov
cmpsb
CL,
ES:80h ; Длина хвоста в PSP
CL,
; Длина хвоста=0?
install_without_arg ; Да, прогр.запущена без пар.
CH,
CH
; CX=CL= длина хвоста
; DF=0 - флаг направления вперед
DI,
81h
; ES:DI-> начало хвоста в PSP
SI,
offset key
; DS:SI-> поле key
AL,
' '
; Уберем пробелы из начала хвоста
; Сканируем хвост пока пробелы
; AL - (ES:DI) -> флаги процессора
; повторять пока элементы равны
DI
; DI-> на первый символ после пробелов
CX,
4
; ожидаемая длина команды
; Сравниваем введенный хвост с ожидаемым
; (DS:SI)-(ES:DI) -> флаги процессора
print_mes_and_exit
; Неизвестная команда
flag
jne
inc
. . .
;----------------------------------------------------------------key
DB '/off‘
; команда
flag
DB 0
Домашнее задание
Написать программу, распечатывающую
содержимое PSP
ПРЕРЫВАНИЯ
Прерывание (interrupt) – это аппаратная функция,
вызывающая приостановку операций CPU, запоминание
его состояния и выполнение специальной программы,
которая называется программой обработки прерывания
(interrupt service routine - ISR) или обработчиком
прерывания (interrupt handler).
Существует три класса прерываний:
внутренние
внешние (аппаратные)
программные
Внутренние прерывания инициируются состоянием
самого процессора (например, деление на ноль)
Внешние – сигналом, подаваемым в CPU другими
компонентами вычислительной системы (например, при
любом нажатии на клавишу).
Программные прерывания – специальной командой
INT.
Независимо от источника прерывания,
последовательность действий,
выполняемых CPU по обслуживанию
прерывания всегда одинаковая, как для
аппаратного, так и для программного
прерывания.
Микропроцессоры семейства 8086 способны
обрабатывать 256 типов прерываний. Каждое
прерывание имеет номер от 0 до 255.
Начало оперативной памяти от адреса
0000h до 03FFh отводится под векторы
прерываний. Вектор прерывания – это 2
слова памяти (4 Байта), в которых
хранятся адреса программ обработки
прерываний (ISR). В старшее слово
записывается сегментный адрес ISR, в
младшее слово – смещение ISR, то есть
относительный адрес точки входа ISR в
сегменте. Вектор 0 располагается, начиная
с адреса 0, вектор 1 – с адреса 4, вектор 2
– с адреса 8 и т.д. Вектор с номером N
занимает, таким образом, байты с N*4 до
N*4+3.
Процедура прерывания
CPU
IP
CS
IP ISR0
2
CS ISR0
4
IP ISR1
6
CS ISR1
8
IP ISR2
A
CS ISR2
Nx4
IP ISRN
Nx4+2
CS ISRN
Flags
3FC
IP ISR255
3FE
CS ISR255
400
Old IP
New SP
Old CS
Flags
Вектор прерванного
процесса
Stack
Old SP
Программа обработки прерывания
Вход по
прерыванию,
например,
по команде
Сохранение
используемых
регистров в
стеке
int
Тело ISR
Восстановление
регистров из
стека
iret
Восстанавливает из
стека 3 регистра
IP
CS
Flags
Изменение содержимого
вектора прерывания
Рассмотрим как заполнить вектор
«вручную», т.е. без использования
функций DOS
Использование функций DOS для
изменения содержимого вектора
Сохранение
вектора
Заполнение вектора
Заполнение вектора
Вектор можно изменить непосредственно
засылая слова по адресу вектора.
При изменении вектора нужно соблюдать
определенные меры предосторожности. Например,
если мы изменили только одно слово вектора и
возникает прерывание по этому вектору, то это
приведет к зависанию программы. Для того, чтобы
исключить прерывания в процессе изменения
вектора, команды изменяющие вектор должны
выполняться при запрещенных прерываниях.
Команда CLI запрещает прерывания, все кроме
NMI-немаскируемых прерываний.
Пример заполнения вектора 65h
xor
ax,ax
mov
es,ax
cli
mov word ptr es:65h*4,
;переслать смещение
;запретить прерывания
offset new_65h
;точки входа в
;обработчик
mov word ptr es:65h*4+2,
часть
sti
...
...
new_65h
proc far
push
...
...
pop
iret
new_65h
endp
DS
;и сегментную
;разрешить прерывания
Функции DOS для сохранения/изменения
вектора прерывания
Получить вектор прерывания
Функция 35h
Применение:
35h
AH
Номер вектора AL
int 21h
Возврат ES:BX – содержимое вектора
(указатель на программу обработчика)
Изменить вектор прерывания
Функция 25h
Применение:
25h
AH
Номер вектора AL
int 21h
В DS:DX – новое содержимое вектора
(указатель на программу обработчика)
Пример изменения вектора прерывания
old_09h
...
...
DD
?
mov
int
mov
mov
mov
AX,
3509h
;
получить вектор
21h
;
прерывания 09h
word ptr old_09h,
BX
;
ES:BX - вектор
word ptr old_09h+2, ES
DX,offset new_09h
; получить смещение точки
; входа в новый обработчик на DX
mov AX,
2509h
; функция установки прерывания
; изменить вектор 09h
int 21h
; AL - номер прерыв.
; DS:DX - указатель программы обработки прер.
...
...
new_09h:
; точка входа в обработчик
Пример
code_seg segment
assume cs:code_seg, ds:code_seg, ss:code_seg
org
100h
start:
jmp
begin
line
db
2
column
db
10
sym
db
01h
begin:
mov
AH,25h
;ф-я заполнения вектора
прер.
mov
AL,65h
;номер вектора
mov
DX,offset new_65h ;смещение
обработчика
int
21h
gogo:
int
65h
mov
AH,02h
;функция позиционирования
mov
BH,0
;видеостраница
mov
DH,line
;строка
mov
DL,column
;столбец
int
10h
mov
AH,0Ah
;ф-я вывода символа без атрибута
mov
AL,sym
;символ
mov
BH,0
;видеостраница
mov
CX,60
;коэффициент повторения
int
10h
inc
sym
;следующий символ
inc
line
;следующая строка
mov
ah,08h ;ф-я выв без эха, чувствительная к Ctrl+C
int
21h
jmp
gogo
new_65h
proc
near
mov
AH,06h
;функция задания окна
mov
AL,0
;режим создания (нет прокрутки)
mov
BH,1bh ;атрибут всех символов в окне
;(светло-бирюзовые символы, синий фон)
mov
CX,0
;левый верхний угол 0,0
mov
DH,24
;нижняя Y-координата
mov
DL,79
;правая X-координата
int
10h
iret
new_65h
endp
code_seg
ends
end
start
Табличные вызовы подпрограмм
Для вызова функции DOS в AH заносится
номер функции и с помощью int 21h
вызывается диспетчер DOS. Диспетчер
извлекает из AH номер функции и активизирует
по этому номеру соответствующую программу
из числа функций DOS.
Рассмотрим упрощенную имитацию
диспетчера DOS. В нашей программе должен
быть диспетчер, вызываемый с помощью
прерывания и передающий управление
подпрограмме с заданным в AH номером.
Адрес диспетчера внесем в один из свободных
векторов прерывания.
Номер функции пересылается из
AH в регистр BX, который в
дальнейшем используется в
качестве индексного. Сдвиг BX
соответствует умножению на 2.
Теперь BX - индекс, в таблице
адресов addr_tbl, в которой
записаны смещения
(относительные адреса)
подпрограмм в порядке,
определяющем их номера.
jmp start
; Диспетчер прерывания 65h
new_65h: push bx
push dx
mov bl, ah
mov bh, 0
shl
bx,
1
; Лог. сдв. влево на
один разряд
call
add_tbl[bx];
pop dx
pop bx
iret
;Подпрограммы-функции
Продолжение
sub0: программы...
mov ah,
9
lea
dx,
mes0
int
21h
ret
...
...
...
sub4:
mov ah,
9
lea
dx,
mes4
int
21h
ret
start:
mov ax,
2565h ; ф-ия заполнения
вектора
; прер. int
65h
mov dx,
offset new_65h
int
21h
Продолжение программы...
;Последовательно вызываем подпрограммы
mov ah,
int
65h
mov ah,
1
int
65h
...
...
...
mov ah,
4
int
65h
mov ax,
4c00h ; exit
int
21h
Продолжение программы...
;Таблица адресов и подпрограмм
add_tbl
dw
sub0
dw
sub1
...
...
...
dw
sub4
;Сообщения
mes0
db
‘Отработала подпрограмма 0’,
13,10,’$’
...
...
...
mes4
db
‘Отработала подпрограмма 4’,
13,10,’$’
Резидентные программы
TSR
(Terminate and Stay Resident)
Любая TSR программа содержит один или несколько
взаимодействующих друг с другом обработчиков прерываний,
которые обеспечивают запуск программы и выполняют
служебные функции.
После прерывания регистры DS, ES, SS содержат прежние
значения (какими они были до прерывания), поэтому внутри
обработчика нужно использовать адресацию относительно CS.
Чаще всего резидентные программы не полностью заменяют
имеющиеся обработчики прерываний, а лишь дополняют их.
Формат TSR программы
entry:
;
;
;
;
;
;
boot:
jmp
org
boot
100h
Обработчик прерывания (резидентная часть)
вызов старого обработчика (с возвратом
или без возврата)
; часть инициализации
; изменение вектора прерывания
mov
dx, offset boot
int
27h
end
entry
Функция DOS - завершить программу и
оставить в памяти
int 27h CS DX -
завершить программу и оставить
резидентной
сегментный адрес PSP
смещение первого байта
освобождаемой памяти
Вызов старого обработчика
Передача управления без возврата.
Передать управление исходному обработчику можно:
jmp
Передача управления с возвратом. (Имитация прерывания по
старому вектору):
pushf
call
dword ptr [old_int_vect]
dword ptr [old_int_vect]
Это для iret, которая
извлекает из стека
три слова
Здесь old_int_vect - двойное слово, в котором сохранен
исходный вектор прерывания.
old_int_vect
DD
?
Защита резидентной программы от
повторной загрузки
Если в резидентной программе нет защиты от повторной
загрузки, то при повторном её запуске станет резидентной её
вторая копия.
И т.д. этот процесс может продолжаться до тех пор, пока не
будет исчерпана оперативная память
Наиболее распространенным методом защиты резидентной
программы от её повторной установки является использование
мультиплексного прерывания 2Fh, специально
предназначенного для взаимодействия с резидентными
программами
Мультиплексное прерывание 2Fh
Вызов:
AH
номер мультиплексного процесса (идентифицирует обработчик
прерывания)
00H-7FH
Резерв DOS
80h-B7h
доступны
B8h-8Fh
резерв для сетей
C0h-FFh
доступны для прикладных программ
В частности,
номера 00 и 01 закреплены за резидентной программой DOS print.com
02h рез. порция assign
10h рез порция share
Al
номер функции
Al
00h - дать статус установки процесса
Возвращает:
Al
статус установки
00h не установлен - можно устанавливать
01h не установлен - нельзя устанавливать
FFh установлен
Обработка прерывания 2Fh в резидентной
программе
Для того, чтобы резидентная программа могла отозваться на int 2Fh, в
ней должен иметься обработчик этого прерывания.
Через этот обработчик может быть осуществлена не только проверка
на повторную инициализацию, но и вообще связь с резидентной
программой - смена режима её работы или получения от нее каких-то
параметров. Задания действий осуществляются с помощью функции,
заданной в AL.
Таким образом обработчик должен прежде всего проверить номер
процесса в AH и при обнаружении своего номера проанализировать AL
и выполнить затребованные действия, после чего с помощью iret
передать управление вызвавшей программе.
Если обработчик обнаружил в AH - номер чужого процесса, он должен
командой jmp передать управление по цепочке тому обработчику,
адрес которого был ранее в векторе 2Fh. В результате вызов int 2fh из
любой программы будет проходить по цепочке через все загруженные
программы, пока не достигнет «своей» программы или не вернет
управление в вызвавшую программу через обработчик DOS, который,
очевидно, всегда будет самым последним в цепочке
Альтернативное мультиплексное
прерывание int 2Dh
int 2Dh
AH - мультиплексный номер
AL - функция
00h - проверка инсталляции
Возврат
al=0 -не установлен
al=ffh установлен
cx-версия
dx:di - строка сигнатуры
al=02h - выгрузка
Программа не должна использовать мультиплексный номер.
Программа должна сканировать мультиплексные номера с 00h по
FFh, запомнить первый свободный, т.е номер процесса, который не
инсталлирован.
Программа должна сравнивать 16 байт сигнатуры для всех
мультиплексных номеров, которые используются с целью определения
установлена ли программа на этом номере. Если не установлена, то
берется первый свободный номер.
Формат сигнатуры:
offset
size
00h
08h
10h
8 bytes
8bytes
64bytes
descriptor
имя произв
имя прогр.
asciz опсание продукта
Пример использования прерывания 2Fh
int_2Fh_vector
DD
?
...
int_2Fh
proc
far
cmp
AX,
0B700h
; или 0C700
jne
Pass_2Fh
mov
AL,
0FFh
iret
Pass_2Fh:
jmp
dword ptr CS:[int_2fh_vector]
int_2Fh
endp
;======================================
begin:
mov
AX,0B700h ; установить статус процесса
мультиплексного прер.
int
2Fh
cmp
AL,0
jz
not_installed
lea
DX,msg
call
print
int
20h
msg
DB
‘Программа уже инициализирована’, 13, 10, ‘$’
not_installed:
Выгрузка резидентной программы
В DOS отсутствуют средства выгрузки резидентных программ.
Единственный способ - перезагрузка компьютера. Правда есть
утилиты, которые позволяют удалять резидентные программы.
Резидентные программы должны иметь встроенные средства
выгрузки.
Рассмотрим пример. Пусть последовательно загружаются в память
три резидентные программы A,B,C. Перед изменением адреса
прерывания программа сохраняет адрес обработчика, а затем
вызывают его в процессе своей работы.
Программа A перехватывает прерывание 09h и 21h
Программа B перехватывает прерывание 16h и 21h
Программа C перехватывает прерывание 09h
После этого программа A удаляется из памяти
До удаления:
09h vect
Адр. обр прогр C
16h vect
Адр. обр прогр B
21h vect
Адр. обр прогр B
Int 09h vect
Адр. обр прер. 09h BIOS
Int 21h vect
Адр. обр прер. 21h DOS
Int 16h vect
Адр. обр прер. 16h BIOS
Int 21h vect
Адр. обр прер. 21h прогр. A
Int 09h vect
Адр. обр прер. 09h прогр. A
Программа A
Программа B
Программа C
После удаления:
09h vect
Адр. обр прер. 09h BIOS
16h vect
Адр. обр прер. 16h прогр. B
21h vect
Адр. обр прер. 21h DOS
Int 16h vect
Адр. обр прер. 16h BIOS
Int 21h vect
Адр. обр прер. 21h прогр. A (висячая ссылка)
Int 09h vect
Адр. обр прер. 09h прогр. A
Программа B
(висячая ссылка)
Программа C
Функция Освободить память
int 21h
AH=49h
ES сегментный адрес освобождаемого
блока памяти
возврат:
CF=0 ошибок нет
CF=1
AX=9
Пример процедуры выгрузки из памяти
remove
mov
mov
int
mov
cmp
jne
cmp
jne
mov
int
mov
cmp
jne
cmp
je
not_remove:
proc
CX,CS
AX,
3509h
21h
DX,
ES
CX,
DX
not_remove
BX,
offset
not_remove
AX,
3521h
21h
DX,
ES
CX,
DX
not_remove
BX,
offset
uninstall
ret
;проверить вектор 09h
int_09h
;проверить вектор 21h
inr_21h
uninstall:
push
lds
;
;
mov
mov
mov
int
lds
mov
int
pop
push
pop
mov
int
ret
remove
DS
DX, int_09h_vect
DX,
DS,
AX,
21h
DX,
AX,
21h
DS
CS
ES
AH,
21h
; восстановить 09h
; Эта команда эквивалентна
; следующим двум
word ptr int_09h_vect
word ptr int_09h_vect+2
2509h
int_21h_vect
2521h
49h
endp
Переключение стека в резидентной программе
При реализации процедуры прерывания (аппаратного или
программного) CPU сохраняет в стеке прерванной задачи регистр
флагов, сегментный регистр, регистр CS и IP и загружает из вектора
прерывания в регистры CS и IP двухсловный адрес обр-ка прер-ния.
Все остальные регистры хранят ту информацию, которая в них была на
момент прерывания.
Для того, чтобы не разрушать прерванную задачу, в самом начале
обработчика прерывания следует сохранить все используемые в
обработчике регистры, а перед командой iret - восстановить их. Это
относится и к сегментным регистрам и к РОН.
Все команды обращения к памяти используют по умолчанию в
качестве сегментного регистра - регистр DS. Если при переходе в
обработчик не выполнить настройку DS на сегмент обработчика, то
команды вида:
mov
AX,
mem
mov
BX,
[SI]
будут обращаться к случайным ячейкам прерванной задачи, что,
возможно, приведет к разрушению и этой задачи, и обработчика. Если
нежелательно перенастраивать регистр DS, то в командах работы с
памятью следует использовать замену регистра:
mov
AX,
CS:mem
mov
BX,
CS:[SI]
Особая ситуация возникает со стеком . При переходе в обработчик
регистры SS и SP настроены на стек прерванной задачи. Если этот
стек имеет достаточный объем, то обработчик его может использовать,
а если нет - переполнение стека может привести к разрушению
прерванной программы. Поэтому надежнее в обработчике прерывания
иметь собственный стек.
Если TSR программа «паразитирует» на чужом стеке, то в этом случае
использование стека должно быть минимальным.
Смена стека требует запоминания кадра стека (содержимого SS и SP)
в ячейках памяти отведенной обработчику, занесения в SS и SP новых
значений и восстановления старого кадра перед выходом из
обработчика. Естественно, что для стека должен быть выделен
свободный объем (необходимый для запоминания своих данных, а
может быть и чужих, от программ, «паразитирующих» на чужом стеке).
Если резидентная программа не допускает повторной активизации в
процессе своей работы, то можно не делать проверку переключения
стека, и смена стека может быть осуществлена следующим образом:
org
begin
100h
start:
jmp
ss_seg
dw
ss_offs
dw
mem
dw
.
.
new_handler
proc
far
mov
cs:ss_seg,ss ;сохр.кадра стека прерванной
задачи
mov
cs:ss_offs,sp
cli
;запрет прерываний
mov
cs:mem,cs
;настроим ss на наш сегмент
mov
ss,cs:mem
mov
sp,offset end_res
;настроим sp
sti
;разрешим прерывания
; теперь работаем на стеке резидентной программы
.
.
;в конце резидентной части:
stack_area
dw
256 dup (?)
new_handler
endp
end_res=$
Процедура обработчика прерывания начинается с сохранения кадра
стека прерванной задачи. Адресация ячеек выполняется через CS,
поскольку DS еще указывает на сегмент данных вызвавшей
программы.
Установка нового кадра стека всегда выполняется при запрещенных
прерываниях, т.к. если аппаратное прерывание произойдет между
командами заполнения SS и SP, вектор прерванного процесса будет
сохранен в случайной ячейке памяти.
Заполнить сегментный стека можно и так:
push
CS
pop
SS
Однако это выполняется на стеке прерванной программы,
приведенный же пример не затрагивает ни стека прерванной задачи,
ни регистр ax, ни других регистров. Т.к. команда
mov
SS,
CS
запрещена, то содержимое cs копируется в ss через ячейку памяти
mem. Команда
mov
SP,
offset end_res
заносит адрес для первого стека, место под которым выделено в
самом конце резидентной части обработчика. Под стек отведено 256
слов.
При запуске программы на выполнение DOS находит свободную
область памяти подходящего размера. В начале программы
создается префикс программного сегмента (PSP) размером в 256
байт. Сама программа загружается вслед за PSP. Кроме того, DOS
передает программе копию среды. Размер среды от 160 байт для
MS DOS 3.3 и выше. Сегментный адрес среды помещается в PSP
по смещению 2ch. Резидентные программы практически никогда не
используют среду DOS, занимаемую ею память можно освободить
с помощью функции 49h.
mov ES, word ptr DS:[2CH] ;загрузить сегментный адрес среды в es
mov AH, 49h
;и освободить память
int 21h
Резидентная программа не нуждается и в PSP. Младшая часть
PSP (до смещения 5ch) используется DOS и в последний раз
потребуется при выполнении функции 31h или прерывания 27h. В
дальнейшем DOS будет использовать PSP прерванной программы.
Некоторые TSR программы используют PSP программы,
например, пересылают резидентную часть программы в PSP c
помощью команды movsb, уменьшая тем самым размер
резидентной позиции. Однако, надежнее, проще и
целесообразнее найти применение PSP в резидентной
программе. Например, использовав его как буфер ввод-вывод
или разместив в нем собственный стек. Последнее выполняется
следующим образом:
вместо
mov
SP, offset end-res
mov
SP, offset start
При этом получаем стек глубиной 256 байт или 128 слов, т.е.
все PSP
Обработчик прерываний от таймера
Большому количеству TSR программ необходимы
постоянные по времени проверки ресурсов системы или
осуществление активизации некоторых процессов.
Подобные действия может обеспечить обработчик
прерываний от таймера.
Векторы прерываний.
Прер. 20
таймера
08h
1Сh
Заглушка
BIOS
iret
.
.
iret
.
.
.
Int 1Сh
.
iret
iret
Прикладная
обработка
Программа
BIOS отсчета
времени
Контроллер прерываний и его программирование
Если необходимо написать обработчик аппаратного
прерывания – то нужно выполнить все необходимые
действия:
аппаратура, от которой пришло прерывание;
микросхемы контроллера прерываний.
Сигналы прерываний поступают от ВУ через
контроллер прерываний (микросхема Intel 8259A)
Основное назначение контроллера – направление
сигналов запросов прерываний от восьми устройств
на единств.вход прерываний процессора
Контроллер передает в процессор номер вектора по
линиям данных.
Сигнал INT поступающий на одноименный вход СРU
инициирует процедуру прерывания.
Организация аппаратных прерываний в IBM РС/ХТ
IRQ0
IRQ1
IRQ2
IRQ3
КОНТР
ОЛЛЕР
ПРЕРЫ
ВАНИЙ
INT
СРU
vector
IRQ4
IRQ5
IRQ6
IRQ7
Баз. вектор – 8
Порты 20h, 21h
IRQ - Interrupt Request
Запрос прерывания
Формирование вектора прерывания
1
IRQ0
1
1
IRQ1
09h
клавиатура
1
1
IRQ2
0Ah
Резерв
1
1
1
IRQ3
0Bh
Сом2
1
1
IRQ4
0Ch
Сом1
1
1
1
IRQ5
0Dh
Жесткий диск
1
1
1
IRQ6
0Eh
Гибкий диск
1
1
1
1
IRQ7
0Fh
LPT1
Базовый вектор 08h
таймер
В IBM PC/AT 2 контроллера прерываний
IRQ8
IRQ9
IRQ10
IRQ11
IRQ12
IRQ13
КОНТР
ОЛЛЕР
ПРЕРЫ
ВАНИЙ
Ведо
мый
IRQ0
IRQ1
IRQ3
IRQ4
IRQ5
IRQ14
IRQ6
IRQ15
IRQ7
Баз.вектор – 70h
Порты А0h, А1h
КОНТР
ОЛЛЕР
ПРЕРЫ
ВАНИЙ
INT
СРU
vector
Веду
щий
Базовый вектор - 8
Порты 20h, 21h
Соответствие векторов прерываний устройствам
компьютера
Прерывание
IRQ
IRQ1
IRQ2
IRQ8
IRQ9
IRQ10
IRQ11
IRQ12
IRQ13
IRQ14
IRQ15
IRQ3
IRQ4
IRQ5
IRQ6
IRQ7
Вектор
8h
9h
Ah
70h
71h
72h
73h
74h
75h
76h
77h
Bh
Ch
Dh
Eh
Fh
Устройство
Таймер
Клавиатура
Вход от ведомого
Клапан микросхемы часы realtime
Программно перенапр. на IRQ2 (int OAh)
Резерв
-«Мышь (PS/2)
Сопроцессор
Жесткий диск
Резерв
Сом 2
Сом 1
Принтер LPT2
Гибкий диск
LPT1
Структура контроллера
CPU
INT
IF
INTA
IRQ0
IRQ1
1-0
IRQ2
1
x
IRQ3
x
IRQ4
1
x
IRQ5
x
IRQ6
x
IRQ7
x
Регистр
маски
IMR
Port 21h
Схема
анализа
приоритетов
Port 20h
Регистр
Запросов
IRR
Port 20h
x
1-0
Регистр
обслуживаемых
запросов
ISR
Port 20h
EOI
Структура программы обработки
аппаратного прерывания
IRQ1
Запрещены все вложенные прерывания,
независимо от их приоритетов
(IRQ - IRQ7)
sti
Разрешены только вложенные
прерывания
с более высокими приоритетами IRQ
EOI
Разрешены все вложенные прерывания,
независимо от их приоритетов
(IRQ0 - IRQ7)
iret
Обработчик прерываний, допускающий вложенность
прерываний
IRQi
STI
Возможны
прерывания
более высоких
уровней
IRQØ – IRQ(i-1)
Interrupt IRQ Ø,..,i,i+1,..
Возможны
прерывания
всех уровней
MOV AL, 20h
ОUT 20h, AL
IRET
EOI
Обработчик прерываний, не допускающий вложенности
прерываний
IRQi
STI
Возможны
прерывания
более высоких
уровней
IRQØ – IRQ(i-1)
Запрещены
все
прерывания
CLI
MOV AL, 20h
ОUT 20h, AL
IRET
EOI
Примеры программирования контроллера
прерывания
mov AL, 20h
out 20h, AL
out A0h, AL
AL, 21h
AL, 1
21h, AL
Запросы на прерывания, поступающие в ведущий контроллер IRQ - IRQ7 блокируют
только ведущий контроллер. Однако запросы на прерывание, поступающие в
ведомый контроллер - (IRQ8-IRQ15) , блокируют уровни низших приоритетов в
ведомом и IRQ2 - IRQ7 – в ведущем контроллере. Поэтому в программах обработки
прерываний уровней 8…15 следует предусматривать посылку команды конца
прерываний в оба контроллера
in
or
out
; прочитать текущую маску
; установить в 1 разряд рег-ра IMR
; вернуть в IMR
in
AL, 21h
; прочитать текущую маску
and AL, 0FEh ; сбросить бит в
out 21h, AL
; вернуть в IMR
Выполнение этих команд приведет к
остановке системного таймера.
Выполнение этих команд приведет к
восстановлениб работы системного
таймера.
Резидентный обработчик прерываний от клавиатуры
с подключением до системного
Аппарат.
прерывание
Отпускаие или нажатие
клавиши
Контроллер
прерываний
Контроллер
клавиатуры
CPU
Адрес системного
обработчика из
вектора 09h
8048
Порт 60h
Int 09h
Скен-код
Кольцевой буфер ввода
(16 слов)
Байт флагов клавиатуры
40h:17h
40h:1Eh
Адрес головного символа
40h:1Ah
Скен
Скен
ASCII
ASCII
Адрес хвостового символа
40h:1Ch
Программа пользователя
Программный запрос на ввод с
клавиатуры
40h:3Сh
(1E + 20) – 1 = 3E – 2 = 3C
Байт флагов клавиатуры
Статус
Ins
Caps Lock
Num Lock
Scroll Lock
Сост.Alt
Ctrl
Shift left
Shift right
КВ-FLAG
40h:17h
или можно определить КВ-FLAG
следующим образом:
RIGHT-SHIFT
EQU
клавиша правого шифта нажата
LEFT-SHIFT
EQU
клавиша левого шифта нажата
00000001B;
00000010B;
Клавиша SysRq нажата
-- // --Caps Lock -- // ---- // --Num Lock -- // ---- // --Scroll Lock -- // --Правая Alt нажата
Правая Ctrl нажата
Левая Alt нажата
Левая Ctrl нажата
Кольцевой буфер ввода
40h:1Аh BUFFER_HEAD
40h:1Сh BUFFER_TAIL
40h:1Eh КВ_BUFFER
DW
?
; указатель головного симв.
DW
?
; указатель хвостового симв.
; HEAD = TAIL - указывает, что буфер пустой
DW
16 DUP (?)
;кольцевой буфер
Пример обработчика прерывания 09h с подключением до системного
; поле данных резидентной секции
old_09h
DD
?
new_09h
proc
far
push
АХ
; Сохраним используемый регистр
in AL, 60h
; Введем скен-код
сmp AL, 44h
; Это скен-код (F10)?
je hotkey
; Да
роp АХ
; Восстановим АХ
jmp dword ptr CS:[old_09h]
; В системный обработчик без возврата
hotkey:
; Разрешим дальнейшую работу клавиатуры
in
AL, 61h
; Введем содержимое порта В
or
AL, 80h
; Установим старший бит
jmp
$+2
out
61h, AL
; И вернем в порт В
and
AL, 7Fh
; Снова разрешим работу клавиатуры
out
61h, AL
; Сбросив старший бит в порту В
;Пошлем приказ EOI
mov
AL, 20h
out
20h, AL
рор
АХ
iret
new_09h endp
Обработка горячей клавиши (Alt)/(F10)
new_09h
je
exit1:
gogo:
proc
push
in
сmp
gogo
роp
far
АХ
AL,
AL,
jmp dword
push
mov
mov
mov
рор
сmр
je
jmp
АХ
;
;
;
;
;
Сохраним используемый регистр
Введем скен-код
Это скен-код (F10)?
Да
Восстановим АХ
ptr CS:[old_09h]
ES
AХ, 40h
ES, АХ
AL, ES: 17h
ES
AL, 08h
hotkey
exit1
;
;
;
;
;
;
;
;
;
В системный обработчик без возврата
Сохраним ES
Настроим ES на начало
Данных BIOS
Получим байт флагов клавиатуры
Восстановим ES – он больше не нужен
(Alt) уже нажата?
Да
Нет, в системный обработчик
60h
44h
hotkey:
; Разрешим дальнейшую работу клавиатуры
in
AL,
61h
or
AL,
80h
jmp
$+2
out
61h,
AL
and
AL,
7Fh
out
61h,
AL
;Пошлем приказ EOI
mov
AL, 20h
out
20h, AL
рор
АХ
iret
new_09h
endp
; Введем содержимое порта В
; Установим старший бит
; И вернем в порт В
; Снова разрешим работу клавиатуры
; Сбросив старший бит в порту В
Резидентный обработчик прерывания от клавиатуры
с подключением после системного обработчика
CODE_SEG
ASSUME
SEGMENT
CS:CODE_SEG,DS:code_seg
ORG 100H
START:
JMP BEGIN
int_2Fh_vector
DD
?
old_09h
DD
?
;=============================================================================
;
;=============================================================================
new_09h
proc
far
pushf
; В системный обработчик
call
push
push
push
mov
mov
mov
dec
dec
cmp
jae
mov
dword ptr CS:[old_09h]
; с возвратом
AX
BX
ES
AX,40h
; Настроим ES на сегментный
ES,AX
; адрес области данных BIOS
BX,ES:[lCh] ; Адрес нового хвоста
BX
; Сместимся назад к последнему
BX
; введенному символу
BX,lEh
; Хвост не вышел за пределы буфера?
go
; Нет, значит он был где-то внутри буфера
BX,3Ch
; Хвост после вычитания 2 вышел за пределы буфера,
; сл-но он был в самом начале, а последний введенный
; символ находится в самом конце буфера
go:
mov
AX,ES:[BX]
; Получим последний символ из буфера
cmp
AX,1600h ; Был введен расширенный код ASCII сочетания Alt/U?
jne
go__out
; Нет
mov
word PTR ES:[BX],OODAh ; Да, заменим код в буфере на код уголка
go_out:
pop
ES
pop
BX
pop
AX
iret
new_09h endp
;=============================================================================
int_2Fh
proc
far
cmp
AX,0C700h
jne
pass_2Fh
mov
AL,OFFh
iret
pass_2Fh:
jmp
dword PTR CS:[int_2Fh_vector]
int_2Fh endp
;=============================================================================
begin:
mov
AX,0C700h ; AH=OC7h номер процесса C7h
; AL=OOh -дать статус установки процесса
int
2Fh
; мультиплексное прерывание
cmp
AL, 0
jz
not_installed
; возвращает AL=0 если не установлена
lea
DX,
msg
call
print
int
20h
msg
DB
'Уже установлена',13,10,'$'
not_instailed:
mov
AX,
352Fh
; получить вектор
int
21h
; прерывания 2Fh
mov
word ptr int_2Fh_vector,BX
; ES:BX - вектор
mov
word ptr int_2Fh_vector+2,ES
mov
DX,
offset int_2Fh
; получить смещение точки входа в новый
; обработчик на DX
mov
AX,
252Fh
; функция установки прерывания
; изменить вектор 2Fh
int
21h
; AL - номер прерыв. DS:DX - указатель программы обработки прер.
mov
AX,3509h
; получить вектор
int
21h
; прерывания 09h
mov
word ptr old_09h,
BX
; ES:BX - вектор
mov
word ptr old_09h+2, ES
;
mov
DX,
offset new_09h ; получить смещение точки входа в новый обработчик на DX
mov
AX,
2509h
; функция установки прерывания изменить вектор 09h
int
21h ; AL - номер прерыв. DS:DX - указатель программы обработки прер.
;-----------------------------------------------------------------------------mov
DX,offset begin
; оставить программу ...
int
27h
; ... резидентной и выйти
;=============================================================================
PRINT
PROC
NEAR
MOV АН,09H
INT
21H
RET
PRINT ENDP
;=============================================================================
CODE_SEG ENDS
END START
Состояние кольцевого буфера
Пусть перед вводом данного символа буфер был пуст
40h:1Еh
Голова 40h:1Аh
...
...
Мусор
Мусор
...
...
Хвост 40h:1Сh
40h:ЗСh
Это адрес
указателя, а не его
содержимое
Фактически в слове, на которое указывают
оба указателя, находится код символа,
введенного ранее и уже изъятого
программой из буфера
Состояние кольцевого буфера после ввода символа
40h:1Еh
Голова 40h:1Аh
...
...
scan
ASCII
...
...
Хвост 40h:1Сh
40h:ЗСh
40h:1Еh
Хвост 40h:1Сh
...
...
...
...
scan
ASCII
Голова 40h:1Аh
40h:ЗСh
В программе после вычитания 2 из адреса хвостового элемента, проверяется находится ли
полученное значение в пределах буфера. Если оно равно или больше 1Еh, команда jae выполняет переход на продолжение программы. Если полученное значение меньше 1Еh, то
это значит, что хвостовой указатель указывает на самое начало буфера, а занесенный только
что в буфер код находится в самом его конце
Резидентный обработчик прерываний от клавиатуры с подключением как до, так и после системного
CODE_SEG
SEGMENT
ASSUME
CS:CODE_SEG,DS:code_seg
ORG 100H
START:
JMP BEGIN
int_2Fh_vector
DD
?
old_09h
DD
?
tail
DW
new_09h
proc
far
push AX
push ES
mov
AX,
40h
; Настроим ES на сегментный
mov
ES,
AX
; адрес области данных BIOS
mov
AX,
ES:[1Ch]
; Сохраним адрес хвоста перед обработкой
mov
CS:tail, AX
pop ES
pop AX
pushf
; В системный обработчик
call
CS:old_09h
; с возвратом
push
AX
push
BX
push
ES
mov
AX,
40h
; Настроим ES на сегментный
mov
ES,
AX
; адрес области данных BIOS
mov
BX,
CS:tail
; Адрес нового хвоста
cmp
BX,
ES:[1Ch]
; Хвост сместился?
jne
go_out
; нет – на выход
mov
AX,
ES:[BX]
; Получим последний символ из буфера
cmp
AX,
1600h
; Был введен расширенный код ASCII
сочетания Alt/U?
jne
go_out
; Нет
mov
word PTR ES:[BX],OODAh
; Да, заменим код в буфере на код уголка
go_out:
pop
ES
pop
pop
iret
new_09h endp
int_2Fh
cmp
jne
mov
iret
pass_2Fh:
jmp
int_2Fh endp
begin:
mov
int
cmp
jz
BX
AX
proc
far
AX,0C700h
pass_2Fh
AL,OFFh
dword PTR CS:[int_2Fh_vector]
AX,
0C700h
2Fh
AL,
not_installed
; AH=OC7h номер процесса C7h
; AL=OOh -дать статус установки процесса
; мультиплексное прерывание
; возвращает AL=0 если не установлена
lea DX,msg
call
print
int 20h
msg DB
'Уже установлена',13,10,'$'
not_instailed:
mov
AX,
352Fh
; получить вектор
int 21h
; прерывания 2Fh
mov word ptr int_2Fh_vector,BX
; ES:BX - вектор
mov word ptr int_2Fh_vector+2,ES
mov DX,
offset int_2Fh
; получить смещение точки входа в новый
; обработчик на DX
mov AX,252Fh
; функция установки прерывания
; изменить вектор 2Fh
int 21h
; AL - номер прерыв. DS:DX - указатель программы обработки прер.
mov
int
mov
mov
mov
mov
AX,
3509h
21h
word ptr old_09h,
BX
word ptr old_09h+2 ,ES
DX,
offset new_09h
AX,
2509h
; получить вектор
; прерывания 09h
; ES:BX - вектор
;
; получить смещение точки входа в новый обработчик на DX
; функция установки прерывания
; изменить вектор 09h
int 21h
; AL - номер прерыв. DS:DX - указатель программы обработки прер.
;-----------------------------------------------------------------------------mov DX,
offset begin
; оставить программу ...
int 27h
; ... резидентной и выйти
;=============================================================================
;=============================================================================
PRINT
PROC
NEAR
MOV
АН,09H
INT 21H
RET
PRINT ENDP
;=============================================================================
CODE_SEG ENDS
END START
Использование памяти BIOS
Положение
Длина
Описание
40:10
Байт
Установленная аппаратура 1
40:11
Байт
Установленная аппаратура 2
40:12
Байт
Состояние после включения питания
40:13
Слово
Размер памяти
40:15
Слово
Резерв
40:17
Байт
Байт флагов клавиатуры 1
40:18
Байт
Байт флагов клавиатуры 2
40:1А
Слово
Адрес головного символа
40:1С
Слово
Адрес хвостового символа
40:1Е
32 байта
Кольцевой буфер клавиатуры
40:49
Байт
Режим дисплея
40:4А
Слово
Число колонок
40:4С
Слово
Длина буфера регенерации в байтах
40:4Е
Слово
Адрес буфера регенерации
Использование памяти BIOS (продолжение)
Положение
Длина
Описание
40:50
Слово
Позиция курсора на стр. 1
40:52
Слово
«
2
40:54
Слово
«
3
40:56
Слово
«
4
40:58
Слово
«
5
40:5А
Слово
«
6
40:5С
Слово
«
7
40:5Е
Слово
«
8
40:60
Слово
Тип курсора
40:62
Байт
Текущая строка изображения
40:63
Слово
Базовый адрес видеоконтроллера
.
.
.
40:6С
Слово
Счетчик таймера
40:70
Байт
40:71
Байт
Сост.клав.Break
Режимы дисплея
Номер
Тип
Макс. цветов
Формат текста
Макс. Страниц
Нач. адрес
Т
16
40х25
8
В8000
1
Т
16
40х25
8
В8000
2
Т
16
80х25
4
8
8
В8000
3
Т
16
80х25
4
8
8
В8000
4
Г
4
320х200 40х25
1
В8000
5
Г
4
320х200 40х25
1
В8000
6
Г
2
640х200 80х25
1
В8000
7
Т
Моно
80х25
8
Г
16
160х200 20х25
1
В0000
9
Г
16
320х200 40х25
1
В0000
А
Г
4
640х200 80х25
1
В0000
D
Г
16
320х100 40х25
8
А0000
Е
Г
16
640х200 80х25
4
“
F
Г
Моно
640х350 80х25
2
“
10
Г
16
640х350 80х25
2
“
1.
8
В0000
Функции int 10h
00h
установить видео режим
01h
установить размер и форму курсора
02h
установить позицию курсора
03h
читать позицию курсора
04h
читать световое перо
05h
выбрать активную страницу дисплея
06h
листать окно вверх (или очистить)
07h
листать окно вниз
08h
читать символ/атрибут
09h
писать символ/атрибут
0Ah
писать символ
0Bh
выбрать палитру/цвет бордюра
0Ch
писать графическую точку
0Dh
читать графическую точку
0Eh
писать символ в режиме TTY
0Fh
читать видео режим
10h
EGA уст ановить палитру
11h
EGA генератор символов
12h
EGA специальные функции
13h
писать строку (только AT + EGA )
Атрибут символа
7
6
5
4
Яркость фона или
мерцание символа
Цвет фона
Яркость символа
Цвет символа
3
2
1
Цвет символа
Биты 0-3
Цвет
черный
1
синий
2
зеленый
3
бирюзовый
4
красный
5
фиолетовый
6
коричневый
7
белый
8
серый
9
голубой
А
салатовый
В
светло-бирюзовый
С
розовый
D
светло-фиолетовый
E
желтый
F
ярко-белый
Биты 4-6 цвет фона под символом.
Бит 7 – в зависимости от режима видеоодаптера
определяет либо яркость фона под данным
символом
(тогда фон принимает 16 цветов), либо мерцание
символа.
Так, в режиме мерцания значения старшего
полубайта
атрибута 8h обозначает не серый фон, а черный
при
мерцающем символе. Сh- не розовый, а красный
Очистим экран, наложив на него черно-белое окно
mov
mov
AH,
Al,
06h
mov
BH,
07h
mov
mov
mov
mov
int
CH,
CL,
DH,
DL,
10h
24
79
;
;
;
;
;
;
;
;
;
;
функция задания окна
режим создания (не
прокрутка)
атрибут всех символов в
окне – ч/б
верхняя Y – коорд.
левая
Х – коорд.
нижняя
Y – коорд.
правая
X – коорд.
прер. BIOS.
0,0
24
y
79
x
Выведем на экран цветное окно
mov
mov
mov
mov
mov
mov
mov
int
AH,
AL,
BH,
CH,
CL,
DH,
DL,
10h
06h
1Eh
5
40
9
75
; функция задания окна
; режим создания (не прокрутки)
; атрибут желтый по синему
; верхняя Y – коорд.
; левая X – коорд.
; нижняя Y – коорд.
; правая X – коорд.
; прер. BIOS
Позиционируем курсор
mov
mov
mov
mov
Int
AH,
BH,
DH,
DL,
10h
02h
7
45
; функция позиционирования
; видеостраница
; строка
; столбец
Вывод строки символов в окно без задания
атрибутов (т.е. с атрибутами окна)
metka:
mov
mov
mov
mov
inc
Int
Loop
CX,
BX,
AH,
AL,
BX
10h
metka
len1
offset
0Eh
[Bx]
; длина строки
mes1
; адрес строки символа
; вывод одного символа в реж. телетайпа
; символ в AL
; сдвиг по строке
; Строка вне окна, с указанием атрибутов символов
mov
AH,
13h
; функция вывода строки
mov
AL,
; режим (атрибут в BL)
mov
BH,
; видеостраница
mov
BL,
04h
; атрибут всех символов
mov
CX,
len2
; длина строки
mov
DH,
16
; начало позиции - строка
mov
DL,
25
; начало позиции - столбец
push
DS
; настройка ЕS на наш сегм.
pop
ES
; данные
mov
BP, offset mes2
; ES:BP – выв. стр.
Int
10h
; Позицируем курсор в начало посл. строки экрана
mov
AH,
02h
; функция позиционирования
mov
BH,
; видеострока
mov
DH,
24
; строка
mov
DL,
; столбец
Int
10h
mes1
DB
16,’Cтрока, выведенная в окно’,17
len1 = $-mes1
mes2
DB
22,22,22,’Строка, выведенная вне окна’,22,22,22
len2 =$-mes2
Работа с видеобуфером
См. Слайд «Распределение адресного пространства в DOS»
Текстовый видеобуфер адаптера EGA включает 8 видеостраниц и
занимает 32Кб от сегментного адреса B800h. Начинается он с
видеостраницы 0, адрес которой B8000h. Объем видеостраниц 4Кб.
Видеостраница
Начальный адрес
В8000
1
В9000
2
ВА000
3
ВВ000
4
BC000
5
BD000
6
BE000
7
BF000 До BFFFF, следующий адрес C0000h
Логическая организация текстового видеобуфера
B800h:00
Символ
B800h:01
Атрибут
знакоместо 0
B800h:02
Символ
B800h:03
Атрибут
знакоместо 1
B800h:04…
Символ …
знаком...
Принципы работы с видеобуфером
2-х байтовые коды символов записываются в видеобуфер в том
порядке, в каком они должны появляться на экране, т.е. первые
80 двухбайтовых полей - соответствуют первой строке, вторые
80 - второй строке и т. д.
Таким образом, переход на следующую строку осуществляется
не с помощью управляющих кодов возврата каретки или
перевода строки, а с размещением кодов символа в другом
месте буфера, в полях, соответствующих следующей строке.
Вообще при формировании изображения непосредственно в
видеобуфере, в обход программ DOS и BIOS, все управляющие
коды ASCII теряют свои управляющие функции и
отображаются в виде соответствующих им символов.
Трактовка же кодов 10,13 - ПС и ВК- выполняется программами
DOS или BIOS, которые в данном случае не активизируются.
Пример программы непосредственной работы с
видеобуфером
mov
mov
mov
mov
mov
mov
mov
AX,
ES,
BX,
AL,
0B800h
AX
80*2*5
’*’
; сегментный адрес видеобуфера
; загрузка в ES
; смещение в видеобуфере(в байтах)
; код ASCII символа в AL
; соответствует первому (четному)
; байту знакоместа
AH,
0Eh
; атрибут- желтый на черном
; соответствует второму (нечетному)
; байту знакоместа - код атрибута
ES:[BX], AX
; запись в видеобуфер
ES:[BX+162],0B0Fh
; цвет светлобирюзовый по черному,
; символ с кодом ASCII Fh
Выражение 80*2*5 –
смещение от начала
видеобуфера первого
байта строки 5
Запишем строку в видеобуфер
push
CS
pop
DS
mov
AX,
mov
ES,
mov
SI,
Mov
DI,
mov
CX,
cld
rep
movsb
;Данные
msg
DB
msglen=$-msg
;DS на наш сегмент
; команд
0B800h
;
AX
;ES-> на видеобуфер
offset msg
;SI= адрес источника
80*2*12+37*2 ;DI= адрес приёмника
msglen
;CX-число пересылаемых битов
; сброс DF - вперед
; пересылка в цикле
‘П’,1Eh,’р’,1Eh,’и’,1Eh,’в’,1Eh,’е’,1Eh,’т’,1Eh
Сдвиг от начала видеобуфера составляет 12 строк по 80 символов
+ 37 символов
Если для всех символов атрибут одинаковый, то программа может
быть организована следующим образом
; DS на наш сегмент
; ES на строку 0 видеобуфера
mov DI,
80*2*5
; начальное смещение на экране
; Будем переносить байт за байтом
; на экран, вставляя между
; кодами ASCII биты атрибута
mov CX,
str_len
; длина строки
mov
SI,
offset str
; смещение исходной строки
cld
; DF=0 вперед
mov AH,
attr
; атрибут в AH
next: lodsb
; загрузим в AL очередной символ
stosw
; выгрузим символ = атрибут из AX в
; видеобуфер
loop next
; повторять str_len раз
;Данные
str DB ’Пример вывода в видеобуфер’
str_len=$-str
attr DB 1Eh
; атрибут всех символов строк
Программы с несколькими сегментами команд
Рассмотрим программы с расширением ЕХЕ. Любая программа, загружаемая в
память, включает три компонента:
окружение ENVIRONMENT
префикс программы PSP
собственно программу, в случае ЕХЕ может состоять из нескольких сегментов.
CS,SS,IP и SP инициализируются заголовками из ЕХЕ-файла.
Поскольку окружение и сама программа ( включая PSP) рассматриваются DOS ,
как отдельные блоки памяти, и та, и другая структура предваряются блоками
управления памяти МСВ, размером 16 байт. С помощью этих блоков DOS ведёт
учёт свободной и занятой памяти.
MCB
DS:[2Сh], ES:[2Ch]
Окружение
MCB
PSP
программа
DS,ES
CS
СОМ программы
В этом случае единственный сегмент содержит все компоненты
программы.
PSP
коды команд
данные
стек
В терминах языков высокого уровня это соответствует минимальной
или крошечной модели памяти. Преимущество .СОМ прогр. перед ЕХЕкомпакность. Как правило резидентная программа пишется в формате .СОМ.
В терминах языков высокого уровня это соответствует минимальной
или крошечной модели памяти
PSP
Программ
ас
данными
стек
IP = 0100h
SP = 0FFFEh
Формат MCB блока
смещение
длина
Содержимое
1
Тип ‘M’ (2Dh) – за этим блоком есть еще блоки MCB
Тип ‘Z’ (5Ah) – данный блок последний
1
2
Владелец (сегм. Адрес)
3
2
Размер (число параграфов в памяти)
5
11
Зарезервировано
Пример программы с двумя сегментами команд
text1 segment ‘code’
assume CS:text1, DS:data
main proc
mov AX,data
mov DS,AX
.
.
call far ptr subr1
.
.
call far ptr subr2
.
.
main endp
text1 ends
text2 segment ‘code’
assume CS:text2, DS:data
subr1 proc far
.
.
subr1 endp
;
subr2 proc far
.
.
subr2 endp
text2 ends
data segment
… DB
… DW
.
.
data ends
stack segment stack ‘stack’
DW 128 dup(0)
stack ends
end main
Модели памяти
В терминах языков высокого уровня
• COM - программа соответствует минимальной или крошечной
модели памяти
• Если команда помещается в один сегмент команд и данные в
одном сегменте данных, то такая .ЕХЕ программа
принадлежит к малой модели памяти.
• Если требуется увеличить объём команд, то необходимо
организовать несколько сегментов команд. Программа с
несколькими сегментами команд и одним сегментом
данных относится к средней модели памяти.
В программе, содержащей несколько сегментов команд, должны быть
команды либо перехода из одного сегмента в другой, либо вызов
процедуры из другого сегмента. Любое обращение к другому сегменту
команд носит название межсегментного или дальнего.
Сегмент команд с главной процедурой получил название
text1. Процедуры subr1 и subr2 объявлены с описанием far, а её вызовы
в главной процедуре сопровождаются описаниями far ptr (far pointerдальний указатель). Вызов не call, а call far ptr.
Смещение код команды адрес проц. subr1
000A
9A
0009 4451
call far ptr subr1
1)CS=444D->в стек
2)IP=000F->в стек
код операции дальнего
3)4451-> в CS
вызова
4)0009-> в IP
ret- работает в зависимости от того, как объявлена процедура
ret-в дальней проц. снимает со стека два слова.
ret-в ближней процедуре снимает со стека одно слово.
Т.о. ближние процедуры следует вызывать только из того же
сегмента командой ближнего вызова call, в то время, как процедуры,
объявленные, как дальние следует вызывать только с помощью команды
дальнего вызова call far ptr. Лишь в этом случае завершающие эти
процедуры команды ret будут работать правильно.
Передача параметров из С программы в
функцию на Ассемблере
i = 25;
J =4;
Test (i, j, 1);
_Test
_Test
.MODEL small
.CODE
PUBLIC _Test
Proc
push
BP
mov
BP,
mov
AX,
add
AX,
sub
AX,
pop
BP
ret
ENDP
END
SP
[BP+4]
[BP+6]
[BP+8]
SP
Return Address
SP+2
25 (i)
SP+4
4 (j)
SP+6
1
Интерфейс с программами на С
extern caps(char);
main()
{
char c;
for(c='a'; c <= 'z'; c++) caps (c);
}
func
segment
public caps
caps
proc near
push
BP
mov
BP,
SP
mov
DL,
[BP]+4
sub
DL,
32
push
DX
mov
AH,
2
int 21h
pop
AX
pop
BP
ret 2
caps
endp
func
ends
end