Автор: Пользователь скрыл имя, 22 Октября 2012 в 18:24, курсовая работа
Ассемблером называется машинно-зависимый компилятор, преобразующий специальным образом составленные текстовые строки в машинные инструкции. Как и любой другой компилятор, ассемблер упрощает разработку программ за счет того, что предоставляет пользователю доступ к кодам машинных инструкций и операндам с помощью символьных имен.
Достоинство заключается в том, что, программируя на ассемблере, программист обычно выбирает последовательность машинных инструкций так, чтобы реализовать нужные вычисления с максимальной скоростью при минимальных затратах памяти. С другой стороны, программирование на уровне машинных инструкций – чрезвычайно хлопотное занятие и не может сравниться по скорости разработки с программированием на языках высокого уровня. В этом заключается главный недостаток ассемблера.
IRQ0 (INT 8) — прерывание системного таймера. Это прерывание вызывается 18,2 раза в секунду. Стандартный обработчик этого прерывания вызывает INT 1Ch при каждом вызове, так что, если программе необходимо только регулярно получать управление, а не перепрограммировать таймер, рекомендуется использовать прерывание 1Ch.
IRQ1 (INT 9) — прерывание клавиатуры. Это прерывание вызывается при каждом нажатии и отпускании клавиши на клавиатуре. Стандартный обработчик этого прерывания выполняет довольно много функций, начиная с перезагрузки по Ctrl-Alt-Del и заканчивая помещением кода клавиши в буфер клавиатуры BIOS.
IRQ2 — к этому входу на первом контроллере прерываний подключены аппаратные прерывания IRQ8 – IRQ15, но многие BIOS перенаправляют IRQ9 на INT 0Ah.
IRQ8 (INT 70h) — прерывание часов реального времени. Это прерывание вызывается часами реального времени при срабатывании будильника и если они установлены на генерацию периодического прерывания (в последнем случае IRQ8 вызывается 1024 раза в секунду).
IRQ9 (INT 0Ah или INT 71h) — прерывание обратного хода луча. Вызывается некоторыми видеоадаптерами при обратном ходе луча. Часто используется дополнительными устройствами (например, звуковыми картами, SCSI-адаптерами и т.д.).
IRQ10 (INT 72h) — используется дополнительными устройствами.
IRQ11 (INT 73h) — используется дополнительными устройствами.
IRQ12 (INT 74h) — мышь на системах PS используется дополнительными устройствами.
IRQ13 (INT 02h или INT 75h) — ошибка математического сопроцессора. По умолчанию это прерывание отключено как на FPU, так и на контроллере прерываний.
IRQ14 (INT 76h) — прерывание первого IDE-контроллера «операция завершена».
IRQ15 (INT 77h) — прерывание второго IDE-контроллера «операция завершена».
IRQ3 (INT 0Bh) — прерывание последовательного порта COM2 вызывается, если порт COM2 получил данные.
IRQ4 (INT 0Ch) — прерывание последовательного порта СОМ1 вызывается, если порт СОМ1 получил данные.
IRQ5 (INT 0Dh) — прерывание LPT2 используется дополнительными устройствами.
IRQ6 (INT 0Eh) — прерывание дисковода «операция завершена».
IRQ7 (INT 0Fh) — прерывание LPT1 используется дополнительными устройствами.
Самые полезные для программ аппаратные прерывания — прерывания системного таймера и клавиатуры. Так как их стандартные обработчики выполняют множество функций, от которых зависит работа системы, их нельзя заменять полностью. Следует обязательно вызвать предыдущий обработчик, передав ему управление следующим образом (Например, если его адрес сохранен в переменной old_handler):
pushf
call old_handler
Эти две команды выполняют действие, аналогичное команде INT (сохранить флаги в стеке и передать управление подобно команде call), так что, когда обработчик завершится командой IRET, управление вернется в нашу программу. Так удобно вызывать предыдущий обработчик в начале собственного. Другой способ — простая команда jmp:
jmp cs:old_handler
приводит к тому, что, когда старый обработчик выполнит команду IRET, управление сразу же перейдет к прерванной программе. Этот способ применяют, если нужно, чтобы сначала отработал новый обработчик, а потом он передал бы управление старому.
Когда микропроцессор клавиатуры помещает скан-код в порт A микросхемы 8255 (адрес порта 60Н ), то при этом вызывается прерывание 9. Задача этого прерывания преобразовать скан-код символа, основываясь на состоянии клавиш-переключателей, и поместить его в буфер клавиатуры. (Если скан-код соответствует клавише-переключателю, то в буфер клавиатуры не пишется ничего, за исключением случая клавиши Ins, а вместо этого прерывание изменяет байты статуса, расположенные в области данных BIOS). Прерывания "ввода с клавиатуры" DOS и BIOS на самом деле всего лишь прерывания "ввода из буфера клавиатуры". На самом деле они не распознают нажатия клавиш. Точнее, они читают интерпретацию введенных клавиш, которую обеспечило прерывание 9.
В прерывании клавиатуры можно выделить три основных шага:
1. Прочитать
скан-код и послать клавиатуре
2. Преобразовать скан-код в номер кода или в установку регистра статуса клавиш-переключателей.
3. Поместить
код клавиши в буфер
В момент вызова
прерывания скан-код будет
Сначала скан-код анализируется на предмет того, была ли клавиша нажата (код нажатия) или отпущена (код освобождения). На всех машинах, кроме AT, код освобождения индицируется установкой бита 7 скан-кода в 1. Для AT, у которого бит 7 всегда равен 0, код освобождения состоит из двух байтов: сначала 0F0Н, а затем скан-код. Все коды освобождения отбрасываются, кроме случая клавиш-переключателей. С другой стороны, все коды нажатия обрабатываются.
После того как введенный символ идентифицирован, процедура ввода с клавиатуры должна найти соответствующий ему код ASCII или расширенный код. В общем случае скан-коды сопоставляются элементам таблицы данных, которая анализируется инструкцией XLAT. XLAT принимает в AL число от 0 до 255, а возвращает в AL 1-байтное значение из 256-байтной таблицы, на которую указывает DS:BX.
Наконец, номера кодов должны быть помещены в буфер клавиатуры.
Процедура должна сначала проверить, имеется ли в буфере место для следующего символа. Этот буфер устроен как циклическая очередь. Ячейка памяти 0040:001A содержит указатель на голову буфера, а 0040:001C указатель на хвост. Эти словные указатели дают смещение в области данных BIOS (которая начинается в сегменте 40Н) и находятся в диапазоне от 30 до 60.
Новые символы вставляются в ячейки буфера с более старшими адресами, а когда достигнута верхняя граница, то следующий символ переносится в нижний конец буфера. Когда буфер полон, то указатель хвоста на 2 меньше указателя на голову кроме случая, когда указатель на голову равен 30 (начало области буфера), а в этом случае буфер полон, когда указатель хвоста равен 60.
Для вставки
символа в буфер, надо
Под перепрограммированием клавиши понимается способ заставить ее выдавать другой код. Но к тому времени, когда программа получает код нажатой клавиши, прерывание клавиатуры уже проинтерпретировало входящий скан-код и преобразовало его в некоторый заранее предопределенный код ASCII или расширенный код. К счастью, начиная с MS DOS версии 2.0, система содержит средства перепрограммирования клавиш. Это средство действует только если ввод воспринимается через функции DOS ввода с клавиатуры функции прерывания BIOS 16Н продолжают интерпретировать нажатия клавиш нормальным образом.
Перепрограммирование доступно за счет Esc последовательностей. Короткая строка, которая начинается с символа Esc (ASCII 27), предназначается для вывода на "стандартное устройство вывода", т.е. на терминал. Но благодаря наличию кода Esc символы даже не достигают монитора. Вместо этого такая строка заставляет MS DOS по другому интерпретировать клавишу, указанную в этой строке. Каждое изменение клавиши требует собственной строки, при этом один и тот же код может присваиваться какому угодно количеству клавиш.
Общий вид такой строки такой:
27,'[66;98p' ; данная строка меняет «Б» на «б»
она начинается с кода Esc (ASCII 27), за которым идет [, затем номер кода переопределяемой клавиши, затем точка с запятой (;), затем новый номер кода, присваиваемый клавише и, наконец, символ p.
Расширенные коды записываются с указанием обоих байтов, причем за первым нулевым байтом должны стоять точка с запятой. Например, строка
27,'[0;68;0;83p' ; переопределяет F10 (0;68) -> Delete (0;83)
Esc последовательности ничего более, чем строки, в которых первый код или символ указывает какую клавишу нужно переопределить, а оставшаяся часть строки указывает какое значение Вы хотите ей придать. Номера кодов должны быть всегда разделены точкой с запятой, а символы заключены в кавычки. Коды и символы могут быть перемешаны в любых сочетаниях. Для того чтобы такие переопределения клавиш были возможны, необходимо чтобы драйвер ANSI.SYS был загружен при загрузке операционной системы. В противном случае Esc последовательности будут игнорироваться.
Имеется несколько вариантов допустимого вида строки. Во-первых, символьные клавиши могут обозначаться самим символом, заключенным в кавычки.
Таким образом, строка 27,'["Б";"б"p' также меняет Б на б.
Во-вторых клавише может быть присвоена целая строка символов, путем указания символов или их кодовых номеров в выражении. Строка 27,'["Б";"пробел Б"p' приведет к тому, что при нажатии на клавишу Б в верхнем регистре, будет печататься строчка - пробел Б.
На самом деле эти Esc последовательности ничего более, чем строки, в которых первый код или символ указывает какую клавишу нужно переопределить, а оставшаяся часть строки указывает какое значение Вы хотите ей придать. Коды и символы могут быть перемешаны в любых сочетаниях. Для того чтобы такие переопределения клавиш были возможны, необходимо чтобы драйвер ANSI.SYS был загружен при загрузке операционной системы. В противном случае Esc последовательности будут игнорироваться
Для решения поставленной задачи программный код будет иметь вид приведенный ниже. Используем функцию 9 прерывания 21Н для посылки строки на стандартное устройство вывода. DS:DX должны указывать на первый символ строки в памяти и строка должна завершаться символом $ (24Н). Здесь клавиша «Б» переопределяется таким образом, чтобы она действовала как строка « Б» (символ пробел и символ заглавная Б).
;в сегменте данных
CНANGE_КEY DB 27,'["Б";" Б"p$'
;для изменения определения клавиши
LEA DX,CНANGE_КEY ;DS:DX должны указывать на строку
MOV AН,9 ;номер функции
INT 21Н ;переопределение клавиши
NEW_КEYBOARD PROC FAR ;сохраняем все изменяемые
PUSН AX ;регистры
PUSН BX ;
PUSН CX ;
PUSН DI ;
PUSН ES ;
;получаем скан-код
и посылаем сигнал
IN AL,60Н ;получаем скан-код из порта A
MOV AН,AL ;помещаем копию в AН
PUSН AX ;сохраняем скан-код
IN AL,61Н ;читаем состояние порта B
OR AL,10000000B ;устанавливаем бит 7
OUT 61Н,AL ;посылаем измененный байт в порт
AND AL,01111111B ;сбрасываем бит 7
OUT 61Н,AL ;возвращаем состояние порта B
;ES должен указывать на область данных BIOS
MOV AX,40Н ;устанавливаем сегмент
MOV ES,AX ;
POP AX ;возвращаем скан-код из стека
; установить наш обработчик
CНANGE_КEY DB 27,'["Б";" Б"p$'
;для изменения определения клавиши
LEA DX,CНANGE_КEY ;DS:DX должны указывать на строку
MOV AН,9 ;номер функции
INT 21Н ;переопределение клавиши
: POP ES ;восстанавливаем изменяемые
POP DI ;регистры
POP CX ;
POP BX ;
POP AX ;
MOV AL,20Н ;выдаем сигнал об окончании
OUT 20Н,AL ;аппаратного прерывания
IRET ;возврат из прерывания
NEW_КEYBOARD ENDP
Выполнив данную курсовую работу, я познакомился с программированием на языке ассемблера во всей широте его проявлений — от создания простых программ и процедур, вызываемых из программ на других языках, до драйверов устройств и операционных систем. Теперь должно быть очевидно, что ассемблер не только не сдает свои позиции, но и не может их сдать — ассемблер неотъемлемо связан с компьютером, и всюду, как только мы опускаемся с уровня абстракций языков высокого уровня, рано или поздно встречаемся с ним. В то же время и абстракции, и сложные управляющие структуры, и структуры данных выражаются на языке ассемблера наиболее эффективно. Ассемблер настолько многогранен, что нет никакой возможности описать все. Методы защиты от копирования и противодействия отладчикам, строение различных файловых систем, программирование на уровне портов ввода-вывода.