Архитектура и основы ассемблера Н.Кащеев НИИТ Обзор курса
Архитектура и основы ассемблера Н.Кащеев НИИТ
Обзор курса Цель курса: Курс дает знания в следующих областях Архитектура процессора Архитектура микропроцессорной системы Основы языка ассемблер Представление о связи между программированием на языке С и на языке ассемблер Связь с другими курсами: Курс дает необходимую базу для изучения курсов: UNIX Программирование на языке С
Evolution of Computers First generation (1939-1954) - vacuum tube Second generation (1954-1959) - transistor Third generation (1959-1971) - IC Fourth generation (1971-present) - microprocessor Http://history.acusd.edu/gen/recording/computer1.html
Evolution of Computers Http://history.acusd.edu/gen/recording/computer1.html http://www.cs.virginia.edu/brochure/museum.html http://www.columbia.edu/acis/history/650.html First generation (1939-1954) - vacuum tube IBM 650, 1954
Evolution of Computers Second generation (1954-1959) - transistor Http://history.acusd.edu/gen/recording/computer1.html http://www.computer50.org/kgill/transistor/trans.html Manchester University Experimental Transistor Computer
Evolution of Computers Third generation (1959-1971) - IC Http://history.acusd.edu/gen/recording/computer1.html http://www.piercefuller.com/collect/pdp8.html PDP-8, Digital Equipment Corporation Thanks to the use of ICs, the DEC PDP-8 is the least expensive general purpose small computer in 1960s
Evolution of Computers Fourth generation (1971-present) - microprocessor In 1971, Intel developed 4-bit 4004 chip for calculator applications. http://www.intel.com A good review article: The History of The Microprocessor, Bell Labs Technical Journal, Autumn, 1997 Block diagram of Intel 4004 4004 chip layout
Evolution of Intel Microprocessors Number of transistors Minimum transistor sizes (µm) Clock frequencies (MHz) MIPS
Описания (модели) МП library IEEE; use ieee.std_logic_1164. all; use ieee.numeric_std.all; entity Mux8 is port (InBus : in STD_LOGIC_VECTOR(7 downto 0); Sel : in STD_LOGIC_VECTOR(2 downto 0); OutBit : out STD_LOGIC); end Mux8; architecture Synthesis_1 of Mux8 is begin process (InBus, Sel) begin OutBit <= InBus(TO_INTEGER (UNSIGNED(Sel))); end process ; end Synthesis_1;
Программная модель МП
What are microprocessors? A microprocessor is a processor (or Central Processing Unit, CPU) fabricated on a single integrated circuit. A simple microprocessor architecture
Other Commercial Microprocessors PowerPC (IBM, Motorola) Athlon, Dulon, Hammer (AMD) Crusoe (Transmeta) SPARC, UltraSPARC (Sun Microsystems) ARM cores (Advanced RISC Machines) MIPS cores (MIPS Technologies) TI’s TMS DSP chips (Texas Instruments) StarCore (Motorola, Agere)
Applications of Microprocessor-Based Systems Computers Block diagram of a computer System performance is normally the most important design concern
Applications of Microprocessor-Based Systems Microcontrollers Block diagram of a microcontroller In general, microcontrollers are cheap and have low performance A microcontroller is a simple computer implemented in a single VLSI chip. Microcontrollers are widely used in industrial control, automobile and home applications
http://www.ti.com Applications of Microprocessor-Based Systems ASICs 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 Programming of microprocessor-based systems Microprocessor architecture Memory organization I/O units of microprocessor-based systems How to put them together Intel 80x86 instruction set Microprocessor Interrupt services Assembly language programming
Регистры общего назначения
Сегментные регистры
регистр флагов
Сегментация памяти 1 сегмент 2 сегмент 3 сегмент 1000F 10010 00000 00010 00020 Память 00010 + FFFF 1000F
Формат кодирования команд ассемблера [метка] [префикс] команда [операнд(ы)] ; [комментарий] Метка (если имеется), команда и операнд (если имеется) pазделяются по крайней мере одним пробелом или символом табуляции. Максимальная длина строки - 132 символа Метка Команда Операнд count db 1 ;Имя, команда, один операнд mov ax, 0 ;Команда, два операнда
Метки Метка в языке ассемблера может содержать следующие символы: Буквы: от 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 AH, 02h ; загружаем в AH число 02h mov DL, 2Ah ; загружаем в DL число 2Ah INT 21H ; печать * на экране INT 20H ; 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 21/02/05 01:42:50 Page 1 PRIM1.ASM 1 0000 code_seg segment 2 assume CS:code_seg, DS:code_seg 3 org 100h 4 0100 start: 5 0100 B4 02 mov AH, 2h 6 0102 B2 2A mov DL, 2Ah 7 0104 CD 21 int 21h 8 0106 CD 20 int 20h 9 0108 code_seg ends 10 end start
Вывод на экран строки символов Функция 02h – Выводит 1 символ Функция 09Н – печатает целую строку, пока не встретит символ ‘$’ mov AH, 09 ; 09h≡ 9H ≡ 9 ≡ 11O ≡ 1001B lea DX, mes ; адрес сообщения Int 21H
Пример 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
13 10 Листинг трансляции (пример 2) Turbo Assembler Version 3.1 21/02/05 01:17:20 Page 1 PRIM2.ASM 1 0000 code_seg segment 2 assume cs:code_seg,ds:code_seg,ss:code_seg 3 org 100h 4 0100 start: 5 0100 EB 0C 90 jmp begin 6 0103 0D 0A AF E0 A8 A2 A5+ mes DB 13,10,'привет',13,10,'$' 7 E2 0D 0A 24 8 010E begin: 9 010E B4 09 mov AH, 9h 10 0110 BA 0103r lea DX, mes 11 0113 CD 21 int 21h 12 0115 CD 20 int 20h 13 0117 code_seg ends 14 end start
Вывод на экран шестнадцатеричной цифры mov AH, 02h mov DL, 30h ; вывод цифры 0 int 21h mov AH, 02h mov DL, 39h ; вывод цифры 9 int 21h Вместо хранения таблицы ASCII в программе, код цифры можно сформировать сложением цифры и константы 30h
Продолжение ASCII таблицы mov AH, 02h mov DL, 41h ; вывод цифры (буквы) A int 21h РОН = РОН+ 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 Primer_proc … … Primer_proc: proc near инструкция ... инструкция ... ret тело процедуры
Вывод на экран содержимого регистра BL mov DL, BL rcr DL, 4 ; сдвиг вправо на 4 бита call print_hex mov DL, BL call print_hex int 20h ; print_hex: proc near mov AH, 02h and DL, 0Fh add DL, 030h cmp DL, 03Ah jl print add DL, 07h print: int 21h ret
Команды циклического сдвига 0 0 0 0 1 0 rcr DL, 4 результат 0 1 1 0 0 1 rcl DL, 4 результат 0 1 0 0 CF
Поразрядное логическое AND 0 1 0 1 1 1 and DL, 0Fh результат 0 1 0
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 near push DX cycle: mov AH, 08h ; function - input char without echo int 21h cmp AL, 030h jb beep ; if < beep (unsigned) cmp AL, 046h ja beep ; if > beep (unsigned) cmp AL, 039h ja cont mov AH, 02h ; print char mov DL, AL int 21h sub AL, 030h ; code ASCII-030h--> hex digit pop DX ret
beep: mov AH, 02h mov DL, 07h ; code of beep int 21h jmp short cycle cont: cmp AL, 041h jb beep mov AH, 02h mov DL, AL int 21h sub AL, 037h pop DX ret inp_hex endp code_seg ends end start
Домашнее задание Вывод содержимого регистра BX Ввод 4-х шестнадцатиричных цифр и формирование из них содержимого регистра BX
Если шестнадцатеричное число начинается с буквы, то в программе такое число должно записываться с ведущим 0 (для того, чтобы отличить от меток или от обозначения регистров), Например, число А – 0Ah, а не Ah – чтобы не спутать с регистром AH. Вывод на экран двоичного числа 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 разряд влево mov DL, 00 ; сложение с учетом значения флага переноса CF adc DL, 30h int 21H loop cycle int 20h code_seg ends end start приемник=приемник+источник+CF
Работа с файлами В 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, которые автоматически предоставляются любой программе Остальные номера с большими логическими номерами DOS предоставляет по требованию
Проверка ошибок Так как АХ используется для возврата как логического номера, так и кода ошибки, то в качестве признака ошибки используеся флаг CF (флаг переноса) Возможны коды возврата: 3 – путь не найден 4 – нет свободного логического номера 5 – отказ в доступе – либо в каталоге нет места для новой записи, либо уже существующий файл защищен от записи и не может быть открыт для вывода данных.
Файловая функция mov AH, 3Ch ; AH 3Ch, 3D, …. …. …. int 21h CF=0 ? Ошибок нет – в AX - дескриптор Произошла ошибка, в 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. Бит 7 – бит наследования Биты 4-6 – режимы совместного использования. Коды возврата в АХ: 2 – файл не найден 3 – путь не найден 4 – нет свободного логического номера файла 5 – отказ в доступе 12 – недопустимый код доступа
3Eh – закрыть файл (CLOSE) Логический номер в ВХ Номер функции 3Eh AH int 21h Код ошибки: 6 – ошибочный логический номер
3Fh – читать данные из файла (READ) Логический номер ВХ Число байт СХ Адрес буфера DS:DX В АХ возвращается число действительно считанных байтов Если в АХ 0, то программа пыталась считать данные за концом файла Код ошибки: 5 – отказ в доступе 6 – ошибочный логический номер
Процесс чтения из файла Область программы
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.001’,0 ; ASCIIZ строка спецификации файла
Пример 2 ; Открыть файл MOV AH, 3Dh ; функция OPEN MOV AL, 2 ; Доступ для чтения/записи MOV DX, OFFSET Filename ; Адрес имени файла INT 21h MOV Handler, AX ; Сохранение дескриптора ; Пытаемся прочитать 65535 байт MOV AH, 3Fh ; Функция READ MOV BX, Handler ; Дескриптор MOV CX, 65535 ; Сколько читать 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.001’,0 ;спецификация файла
Функции для работы с файлами 43h – получить, установить аттрибуты файла 56h – переименовать файл 57h – получить/установить дату и время последнего изменения файла в DOS 3.00 5Ah – создать временный файл CX - атрибут DS:DX – имя пути, должно заканчиваться ‘\’ Строка должна иметь длину на 12 байт больше длины имени пути, чтобы DOS могла бы дополнить уникальным именем файла. 5Bh – создать новый файл. В отличие от 3Сh, если файл уже существует, то 5Bh сообщает об ошибке. 5Сh – блокировать/разблокировать доступ к файлу.
Программный загрузчик Ц е л ь: Понять как DOS загружает программу в память и управляет ее исполнением
DOS состоит из четырех основных программ
Распределение адресного пространства в DOS
Командный процессор COMMAND.COM Система загружает три части программы COMMAND.COM в память во время сеанса работы постоянно или временно. Ниже описано назначение каждой из трех частей COMMAND.COM: Резидентная часть непосредственно следует за программой ibmdos.com. Резидентная часть обрабатывает все ошибки дисковых операций ввода-вывода и управляет следующими прерываниями: int 22h Адрес программы обработки завершения задачи. int 23h Адрес программы реакции на ctrl/break. int 24h Адрес программы реакции на ошибки дисковых операций чтения/записи или сбойный участок памяти в таблице распределения файлов (FAT). int 27h Завершение работы, после которого программа остается резидентной.
Часть инициализации COMMAND.COM Часть инициализации непосредственно следует за резидентной частью и содержит средства поддержки autoexec-файлов. В начале работы системы данная часть первой получает управление. Она определяет сегментный адрес, куда система должна загружать программы для выполнения. Ни одна из этих программ инициализации не потребуется больше во время сеанса работы. Поэтому первая же команда вводимая с клавиатуры и вызывающая загрузку некоторой программы с диска перекрывают часть инициализации в памяти.
3. Транзитная часть COMMAND.COM Транзитная часть загружается в самые старшие адреса памяти. Выводит на экран приглашение C>, вводит и выполняет запросы. Содержит настраивающий загрузчик и предназначена для загрузки COM- или EXE-файлов с диска в память для выполнения. Если поступил запрос на выполнение какой-либо программы, то транзитная часть строит префикс программного сегмента (PSP) непосредственно вслед за резидентной частью COMMAND.COM. Затем она загружает запрошенную программу с диска в память по смещению 100h от начала программного сегмента, устанавливает адреса выхода и передает управление в загруженную программу.
Ниже приведена данная последовательность: Выполнение команды RET или INT 20H в конце программы приводит к возврату в резидентную часть COMMAND.COM. Если транзитная часть была перекрыта, то резидентная часть перезагружает транзитную часть с диска в память IBMBIO.COM IBMDOS.COM COMMAND.COM (резидент) Префикс программного сегмента Выполняемая программа ... COMMAND.COM (транзитная часть, может быть перекрыта).
Образ памяти программы типа .COM После загрузки программы все четыре сегментных регистра указывают на начало единственного сегмента. Указатель стека автоматически инициализируется числом FFFEh. Таким образом программе выделяется 64 Кб адресного пространства, всю нижнюю часть которого занимает стек.
ПРЕФИКС СЕГМЕНТА ПРОГРАММЫ (PSP) (program segment prefix) PSP – это область размером 100h (25610), которая содержит информацию, необходимую DOS для обеспечения работы программы. Для СОМ-программы сегментные регистры (CS, DS и ES) указывают на начало PSP, а программа размещается сразу вслед за PSP, то есть со смещением 100h от начала PSP.
Структура префикса программного сегмента
Поле 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 - загрузить из памяти один байт в регистр al или одно слово в регистр ax; stos - записать содержимое регистра al или ax в память; cmps - сравнить содержимое двух областей памяти, размером в один байт или в одно слово; scas - сравнить содержимое регистра al или ax с содержимым памяти. Префикс rep позволяет этим командам обрабатывать строки любой длины.
СВОЙСТВА ОПЕРАЦИЙ НАД СТРОКАМИ
rep: ПРЕФИКС ПОВТОРЕНИЯ ЦЕПОЧЕЧНОЙ КОМАНДЫ Несмотря на то, что цепочечные команды имеют отношение к одному байту или одному слову, префикс rep обеспечивает повторение команды несколько раз. Префикс кодируется непосредственно перед цепочечной командой, например, rep movsb. Для использования префикса rep необходимо установить начальное значение в регистре cx. При выполнении цепочечной команды с префиксом rep происходит уменьшение на 1 значения в регистре cx до нуля. Таким образом, можно обрабатывать строки любой длины. Флаг направления определяет направление повторяющейся операции: для направления слева направо необходимо с помощью команды cld установить флаг df в 0; для направления справа налево необходимо с помощью команды std установить флаг df в 1.
Пример: выполняется пересылка 20 байт из string1 в string2 Предположим, что оба регистра ds и es инициализированы адресом сегмента данных string1 db 20 dup('*') string2 db 20 dup(' ') ... cld ;Сброс флага df mov cx,20 ;Счетчик на 20 байт lea di,string2 ;Адрес области "куда« lea si,string1 ;Адрес области "откуда" rep movsb ;Переслать данные
При выполнении команд cmps и scas возможна установка флагов состояния, так чтобы операция могла прекратиться сразу после обнаружения необходимого условия. Ниже приведены модификации префикса rep для этих целей: rep - повторять операцию, пока cx не равно 0; repz или repe - повторять операцию, пока флаг zf показывает "равно или ноль". Прекратить операцию при флаге zf, указывающему на не равно или не ноль или при cx равном 0; repne или repnz - повторять операцию, пока флаг zf показывает "не равно или не ноль". Прекратить операцию при флаге zf, указывающему на "равно или нуль" или при cx равным 0.
Пример проверки командной строки mov CL, ES:80h ; Длина хвоста в PSP cmp CL, 0 ; Длина хвоста=0? je install_without_arg ; Да, прогр.запущена без пар. xor CH, CH ; CX=CL= длина хвоста cld ; DF=0 - флаг направления вперед mov DI, 81h ; ES:DI-> начало хвоста в PSP mov SI, offset key ; DS:SI-> поле key mov AL, ' ' ; Уберем пробелы из начала хвоста repe scasb ; Сканируем хвост пока пробелы ; AL - (ES:DI) -> флаги процессора ; повторять пока элементы равны dec DI ; DI-> на первый символ после пробелов mov CX, 4 ; ожидаемая длина команды repe cmpsb ; Сравниваем введенный хвост с ожидаемым ; (DS:SI)-(ES:DI) -> флаги процессора jne print_mes_and_exit ; Неизвестная команда inc flag . . . ;----------------------------------------------------------------- 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.
Процедура прерывания
Программа обработки прерывания iret Сохранение используемых регистров в стеке Восстановление регистров из стека Тело ISR Вход по прерыванию, например, по команде int Восстанавливает из стека 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, DS ;и сегментную часть sti ;разрешить прерывания ... ... new_65h: push ... ... pop iret
Функции DOS для сохранения/изменения вектора прерывания Получить вектор прерывания Функция 35h Применение: 35h AH Номер вектора AL int 21h Возврат ES:BX – содержимое вектора (указатель на программу обработчика)
Изменить вектор прерывания Функция 25h Применение: 25h AH Номер вектора AL int 21h В DS:DX – новое содержимое вектора (указатель на программу обработчика)
Пример изменения вектора прерывания old_09h DD ? ... ... 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 - указатель программы обработки прер. ... ... 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 номером. Адрес диспетчера внесем в один из свободных векторов прерывания.
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 Номер функции пересылается из AH в регистр BX, который в дальнейшем используется в качестве индексного. Сдвиг BX соответствует умножению на 2. Теперь BX - индекс, в таблице адресов addr_tbl, в которой записаны смещения (относительные адреса) подпрограмм в порядке, определяющем их номера.
Продолжение программы... ;Подпрограммы-функции 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, 0 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 программы org 100h entry: jmp boot ; ; Обработчик прерывания (резидентная часть) ; ; вызов старого обработчика (с возвратом ; или без возврата) ; boot: ; часть инициализации ; изменение вектора прерывания mov dx, offset boot int 27h end entry
Функция DOS - завершить программу и оставить в памяти int 27h - завершить программу и оставить резидентной CS - сегментный адрес PSP DX - смещение первого байта освобождаемой памяти
Вызов старого обработчика Передача управления без возврата. Передать управление исходному обработчику можно: jmp dword ptr [old_int_vect] Передача управления с возвратом. (Имитация прерывания по старому вектору): pushf call dword ptr [old_int_vect] Здесь old_int_vect - двойное слово, в котором сохранен исходный вектор прерывания. old_int_vect DD ? Это для iret, которая извлекает из стека три слова
Защита резидентной программы от повторной загрузки Если в резидентной программе нет защиты от повторной загрузки, то при повторном её запуске станет резидентной её вторая копия. И т.д. этот процесс может продолжаться до тех пор, пока не будет исчерпана оперативная память Наиболее распространенным методом защиты резидентной программы от её повторной установки является использование мультиплексного прерывания 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 descriptor 00h 8 bytes имя произв 08h 8bytes имя прогр. 10h 64bytes 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 удаляется из памяти
До удаления:
После удаления: Программа B Программа C Int 16h vect Int 21h vect Int 09h vect Адр. обр прер. 16h BIOS Адр. обр прер. 21h прогр. A (висячая ссылка) Адр. обр прер. 09h прогр. A (висячая ссылка)
Функция Освободить память int 21h AH=49h ES сегментный адрес освобождаемого блока памяти возврат: CF=0 ошибок нет CF=1 AX=9
Пример процедуры выгрузки из памяти remove proc mov CX,CS mov AX, 3509h ;проверить вектор 09h int 21h mov DX, ES cmp CX, DX jne not_remove cmp BX, offset int_09h jne not_remove mov AX, 3521h ;проверить вектор 21h int 21h mov DX, ES cmp CX, DX jne not_remove cmp BX, offset inr_21h je uninstall not_remove: ret
uninstall: push DS ; восстановить 09h lds DX, int_09h_vect ; Эта команда эквивалентна ; следующим двум ; mov DX, word ptr int_09h_vect ; mov DS, word ptr int_09h_vect+2 mov AX, 2509h int 21h lds DX, int_21h_vect mov AX, 2521h int 21h pop DS push CS pop ES mov AH, 49h int 21h ret remove 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 100h start: jmp begin ss_seg dw 0 ss_offs dw 0 mem dw 0 . . 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 . . . Int 1Сh . iret . . iret iret Программа BIOS отсчета времени Прикладная обработка iret Заглушка BIOS
Контроллер прерываний и его программирование Если необходимо написать обработчик аппаратного прерывания – то нужно выполнить все необходимые действия: аппаратура, от которой пришло прерывание; микросхемы контроллера прерываний. Сигналы прерываний поступают от ВУ через контроллер прерываний (микросхема Intel 8259A) Основное назначение контроллера – направление сигналов запросов прерываний от восьми устройств на единств.вход прерываний процессора Контроллер передает в процессор номер вектора по линиям данных. Сигнал INT поступающий на одноименный вход СРU инициирует процедуру прерывания.
Организация аппаратных прерываний в IBM РС/ХТ Баз. вектор – 8 IRQ - Interrupt Request Порты 20h, 21h Запрос прерывания IRQ0 IRQ1 IRQ2 IRQ3 IRQ4 IRQ5 IRQ6 IRQ7 КОНТРОЛЛЕР ПРЕРЫВАНИЙ СРU INT vector
Формирование вектора прерывания Базовый вектор 08h 0 0 0 IRQ0 IRQ1 IRQ2 IRQ3 IRQ4 IRQ5 IRQ6 IRQ7 таймер 09h 0Ah 0Bh 0Ch 0Dh 0Eh 0Fh Резерв Сом2 Сом1 Жесткий диск Гибкий диск LPT1 клавиатура
В IBM PC/AT 2 контроллера прерываний IRQ8 IRQ9 IRQ10 IRQ11 IRQ12 IRQ13 IRQ14 IRQ15 КОНТРОЛЛЕР ПРЕРЫВАНИЙ Ведо мый СРU INT vector IRQ0 IRQ1 IRQ3 IRQ4 IRQ5 IRQ6 IRQ7 КОНТРОЛЛЕР ПРЕРЫВАНИЙ Веду щий Баз.вектор – 70h Базовый вектор - 8 Порты А0h, А1h Порты 20h, 21h
Соответствие векторов прерываний устройствам компьютера
Структура контроллера Регистр Запросов IRR Port 20h Регистр маски IMR Port 21h Схема анализа приоритетов Port 20h Регистр обслуживаемых запросов ISR Port 20h EOI
Структура программы обработки аппаратного прерывания
Обработчик прерываний, допускающий вложенность прерываний IRQi MOV AL, 20h ОUT 20h, AL IRET EOI Interrupt - STI Возможны прерывания более высоких уровней IRQØ – IRQ(i-1) Возможны прерывания всех уровней IRQ Ø,..,i,i+1,..
Обработчик прерываний, не допускающий вложенности прерываний IRQi MOV AL, 20h ОUT 20h, AL IRET EOI Запрещены все прерывания STI Возможны прерывания более высоких уровней IRQØ – IRQ(i-1) CLI
Примеры программирования контроллера прерывания mov AL, 20h out 20h, AL out A0h, AL in AL, 21h ; прочитать текущую маску or AL, 1 ; установить в 1 разряд рег-ра IMR out 21h, AL ; вернуть в IMR in AL, 21h ; прочитать текущую маску and AL, 0FEh ; сбросить бит в out 21h, AL ; вернуть в IMR
Резидентный обработчик прерываний от клавиатуры с подключением до системного
Байт флагов клавиатуры
Кольцевой буфер ввода 40h:1Аh BUFFER_HEAD DW ? ; указатель головного симв. 40h:1Сh BUFFER_TAIL DW ? ; указатель хвостового симв. ; HEAD = TAIL - указывает, что буфер пустой 40h:1Eh КВ_BUFFER 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 proc far push АХ ; Сохраним используемый регистр in AL, 60h ; Введем скен-код сmp AL, 44h ; Это скен-код (F10)? je gogo ; Да exit1: роp АХ ; Восстановим АХ jmp CS:old_09h ; В системный обработчик без возврата gogo: push ES ; Сохраним ES mov AХ, 40h ; Настроим ES на начало mov ES, АХ ; Данных BIOS mov AL, ES: 17h ; Получим байт флагов клавиатуры рор ES ; Восстановим ES – он больше не нужен сmр AL, 08h ; (Alt) уже нажата? je hotkey ; Да jmp exit1 ; Нет, в системный обработчик 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 SEGMENT ASSUME CS:CODE_SEG,DS:code_seg ORG 100H START: JMP BEGIN int_2Fh_vector DD ? old_09h DD ? ;============================================================================= ; ;============================================================================= new_09h proc far pushf ; В системный обработчик call CS:old_09h ; с возвратом push AX push BX push ES mov AX,40h ; Настроим ES на сегментный mov ES,AX ; адрес области данных BIOS mov BX,ES:[lCh] ; Адрес нового хвоста dec BX ; Сместимся назад к последнему dec BX ; введенному символу cmp BX,lEh ; Хвост не вышел за пределы буфера? jae go ; Нет, значит он был где-то внутри буфера mov 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,OC700h jne pass_2Fh mov AL,OFFh iret pass_2Fh: jmp dword PTR CS:[int_2Fh_vector] int_2Fh endp ;============================================================================= begin: mov AX,OC700h ; 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
Состояние кольцевого буфера Пусть перед вводом данного символа буфер был пуст Это адрес указателя, а не его содержимое
Состояние кольцевого буфера после ввода символа В программе после вычитания 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 0 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 BX pop AX iret new_09h endp int_2Fh proc far cmp AX,OC700h jne pass_2Fh mov AL,OFFh iret pass_2Fh: jmp dword PTR CS:[int_2Fh_vector] int_2Fh endp begin: mov AX, OC700h ; 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
Использование памяти BIOS
Использование памяти BIOS (продолжение)
Режимы дисплея
Функции int 10h
Атрибут символа Яркость фона или мерцание символа Цвет фона Яркость символа Цвет символа 7 6 5 4 3 2 1 0
Цвет символа
Очистим экран, наложив на него черно-белое окно mov AH, 06h ; функция задания окна mov Al, 0 ; режим создания (не ; прокрутка) mov BH, 07h ; атрибут всех символов в ; окне – ч/б mov CH, 0 ; верхняя Y – коорд. mov CL, O ; левая Х – коорд. mov DH, 24 ; нижняя Y – коорд. mov DL, 79 ; правая X – коорд. int 10h ; прер. BIOS.
x y 0,0 79 24
Выведем на экран цветное окно mov AH, 06h ; функция задания окна mov AL, 0 ; режим создания (не прокрутки) mov BH, 1Eh ; атрибут желтый по синему mov CH, 5 ; верхняя Y – коорд. mov CL, 40 ; левая X – коорд. mov DH, 9 ; нижняя Y – коорд. mov DL, 75 ; правая X – коорд. int 10h ; прер. BIOS
Позиционируем курсор mov AH, 02h ; функция позиционирования mov BH, 0 ; видеостраница mov DH, 7 ; строка mov DL, 45 ; столбец Int 10h
Вывод строки символов в окно без задания атрибутов (т.е. с атрибутами окна) mov CX, len1 ; длина строки mov BX, offset mes1 ; адрес строки символа mov AH, 0Eh ; вывод одного символа в реж. телетайпа metka: mov AL, [Bx] ; символ в AL Int 10h ; сдвиг по строке Loop metka
; Строка вне окна, с указанием атрибутов символов mov AH, 13h ; функция вывода строки mov AL, 0 ; режим (атрибут в BL) mov BH, 0 ; видеостраница 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, O ; видеострока mov DH, 24 ; строка mov DL, 0 ; столбец 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Кб.
Логическая организация текстового видеобуфера B800h:00 B800h:01 B800h:02 B800h:03 B800h:04… знакоместо 0 знакоместо 1 знаком...
Принципы работы с видеобуфером 2-х байтовые коды символов записываются в видеобуфер в том порядке, в каком они должны появляться на экране, т.е. первые 80 двухбайтовых полей - соответствуют первой строке, вторые 80 - второй строке и т. д. Таким образом, переход на следующую строку осуществляется не с помощью управляющих кодов возврата каретки или перевода строки, а с размещением кодов символа в другом месте буфера, в полях, соответствующих следующей строке. Вообще при формировании изображения непосредственно в видеобуфере, в обход программ DOS и BIOS, все управляющие коды ASCII теряют свои управляющие функции и отображаются в виде соответствующих им символов. Трактовка же кодов 10,13 - ПС и ВК- выполняется программами DOS или BIOS, которые в данном случае не активизируются.
Пример программы непосредственной работы с видеобуфером mov AX, 0B800h ; сегментный адрес видеобуфера mov ES, AX ; загрузка в ES mov BX, 80*2*5 ; смещение в видеобуфере(в байтах) mov AL, ’*’ ; код ASCII символа в AL ; соответствует первому (четному) ; байту знакоместа mov AH, 0Eh ; атрибут- желтый на черном ; соответствует второму (нечетному) ; байту знакоместа - код атрибута mov ES:[BX], AX ; запись в видеобуфер mov ES:[BX+162],0B0Fh ; цвет светлобирюзовый по черному, ; символ с кодом ASCII Fh Выражение 80*2*5 – смещение от начала видеобуфера первого байта строки 5
Запишем строку в видеобуфер push CS ;DS на наш сегмент pop DS ; команд mov AX, 0B800h ; mov ES, AX ;ES-> на видеобуфер mov SI, offset msg ;SI= адрес источника Mov DI, 80*2*12+37*2 ;DI= адрес приёмника mov CX, msglen ;CX-число пересылаемых битов cld ; сброс DF - вперед rep movsb ; пересылка в цикле ;Данные msg DB ‘П’,1Eh,’р’,1Eh,’и’,1Eh,’в’,1Eh,’е’,1Eh,’т’,1Eh msglen=$-msg Сдвиг от начала видеобуфера составляет 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 ; атрибут всех символов строк
Программы с несколькими сегментами команд Поскольку окружение и сама программа ( включая PSP) рассматриваются DOS , как отдельные блоки памяти, и та, и другая структура предваряются блоками управления памяти МСВ, размером 16 байт. С помощью этих блоков DOS ведёт учёт свободной и занятой памяти. DS:[2Сh], ES:[2Ch] DS,ES CS Рассмотрим программы с расширением ЕХЕ. Любая программа, загружаемая в память, включает три компонента: окружение ENVIRONMENT префикс программы PSP собственно программу, в случае ЕХЕ может состоять из нескольких сегментов. CS,SS,IP и SP инициализируются заголовками из ЕХЕ-файла.
СОМ программы В этом случае единственный сегмент содержит все компоненты программы. PSP коды команд данные стек В терминах языков высокого уровня это соответствует минимальной или крошечной модели памяти. Преимущество .СОМ прогр. перед ЕХЕ- компакность. Как правило резидентная программа пишется в формате .СОМ. В терминах языков высокого уровня это соответствует минимальной или крошечной модели памяти SP = 0FFFEh IP = 0100h
Формат MCB блока
Пример программы с двумя сегментами команд 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); .MODEL small .CODE PUBLIC _Test _Test Proc push BP mov BP, SP mov AX, [BP+4] add AX, [BP+6] sub AX, [BP+8] pop BP ret _Test ENDP END
Интерфейс с программами на С 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 extern caps(char); main() { char c; for(c='a'; c <= 'z'; c++) caps (c); }
36148-lectures_arch+asm.ppt
- Количество слайдов: 180

