Реализовать прерывание через порты ввода-вывода

ElvenDragon

,

если процессор старше intel 386 — для организации задержки используй команду rdtsc. Если нужно чтение клавиатуры на уровне портов, то вот фрагмент обработчика прерывания INT 9. Это прерывание вызывается всякий раз при нажатии любой клавиши на клавиатуре. Обработчик этого прерывания должен прочитать скан-код клавиши, подтвердить микропроцессору клавиатуры факт приема скан-кода, преобразовать этот код в соответствии с клавишами-переключателями и поместить преобразованный код в буфер клавиатуры, находящийся в области BIOS. Действия чтения и подтверждения приема скан-кода могут выглядеть, к примеру, так:

AssemblerВыделить код

1
2
3
4
5
6
7

IN AL,60h ;читаем скан-код в порт 60h
PUSH AX ;сохраним его на время
IN AL,61h ;читаем порт 61h
OR AL,80h ;старший бит байта из порта 61h в 1
OUT 61h,AL ;подтверждаем факт приема скан-кода
POP AX
OUT 61h,AL ;восстановили байт в порту 61h

Можно напрямую читать кольцевой буфер клавиатуры. С адреса 400h начинается область памяти, используемая программами BIOS для хранения данных, в том числе для буфера клавиатуры. Буфер начинается с адреса 41Eh и заканчивается адресом 43Dh. Все 32 адреса сгруппированы попарно — один байт для хранения ASCII-кода, выработанного программой INT 09h, а второй — для хранения скан-кода. Смещения первого и последнего байтов буфера указывают на положение самого буфера относительно адреса 400h. Эти смещения хранятся в двух последовательных словах по адресам 480h и 482h. Два дополнительных указателя «голова» и «хвост» используются для отслеживания содержимого буфера. Эти указатели находятся в области данных BIOS, их адреса — 0040:001Ah и 0040:001Ch. «Голова» и «хвост» указывают на позицию справа от возврата каретки (0FFFFh для 101-клавишной клавиатуры). «Хвост» указывает на ту позицию, в которую будут занесены данные о следующем нажатии на клавишу, «голова» указывает на первый введенный символ (логическое начало буфера). Если «голова» равна «хвосту», то INT 09h и INT 16h считают, что буфер пуст.

AssemblerВыделить код

1
2
3
4
5
6

push 0
pop ds
mov al,ds:[41Ah]
mov ah,ds:[41Ch]
cmp ah,al
jne exit