Какой номер прерывания отвечает за таймер и клавиатуру? К одном месте написано, что 0x08 и 0x09, а в другом 0x32 и 0x33. Вот часть проги по адресу 0x1000:0000. Компилятор fasm. Не реагирует на таймер. Код (Text): ... xor eax, eax mov ax, cs shl eax, 4 add eax, idt mov [cs:idt_addr], eax lidt fword ptr idtr ... idt: dq 0 ;0 dq 0 ;1 dq 0 ;2 dq 0 ;3 dq 0 ;4 dq 0 ;5 dq 0 ;6 dq 0 ;7 dq 0 ;8 dq 0 ;9 dq 0 ;10 dq 0 ;11 dq 0 ;12 exGP: dw (gp+0x10000) and 0xFFFF dw 00001000b dw 1000111000000000b exGP2: dw (gp+0x10000) shr 16 rb idt+32*8-$ extimer: dw (timer+0x10000) and 0xFFFF dw 00001000b dw 1000111000000000b extimer2: dw (timer+0x10000) shr 16 rb idt+256*8-$ idt_end: idtr: idt_size: dw idt_end - idt idt_addr: dd 0x6c00 ... in al, 070h and al, 7Fh out 70h, al sti ... gp: pop eax pusha mov eax, 0xB8000+80*2*4+2 mov esi, eax inc byte [ds:esi] popa iretd timer: mov eax, 0xB800 shl eax, 4 add eax, 80*2*4+4 mov esi, eax inc byte [ds:esi] jmp int_EOI int_EOI: mov al, 20h out 020h, al out 0a0h, al iretd Почему-то в начале генерируется GP с кодом 43. основной цикл программы вывода на экран выполняется, а обработчик таймера - нет.
Я читал про то что нужно разрешать прерывания, чтобы они работали, но не было написано как. Не это их инициализация? Код (Text): mov al, 0x00 out 0x21, al out 0xA1, al
PIC - PROGRAMMABLE INTERRUPT CONTROLLER Программируемый контроллер прерываний - ПКП Или также известный как 8259А Контроллер этот появился так давно, что совместим с процессорами 8080/8085 . Так как современные компьютеры их не используют. То нас больше интересует его работа в режиме совместимости с 8086/8088. Поэтому будет описана только часть относящаяся к нему. Контроллер имеет 8 линий прерываний, называемых IRQ. Этого мало, поэтому была разработана возможность каскадного подключения контроллеров. Когда к видущему Master контроллеру подключались, ведомые Slave контроллеры. Теоретически возможно, что мы имеем один ведущей и восемь подчиненных. Но в стандартном компьютере всего два - первый ведущий и второй ведомый. Первый контроллер прерываний 8259А использует порты 20h-21h, второй 8259А использует 0A0h-0A1h Второй контроллер сидит на IRQ2 первого контроллера. Стандартное назначение прерываний следующее. Согласно документации на Award BIOS и ряда других спецификаций. Код (Text): +-----+-------+----------------------------------------+ | INT | IRQ | Назначение | +-----+-------+----------------------------------------+ | 08h | IRQ0 | Системный таймер (канал 0 8253/8254) | +-----+-------+----------------------------------------+ | 09h | IRQ1 | Клавиатура | +-----+-------+----------------------------------------+ | 0Ah | IRQ2 | Каскадное подключение #2 8259A | +-----+-------+----------------------------------------+ | 0Bh | IRQ3 | COM2 | +-----+-------+----------------------------------------+ | 0Ch | IRQ4 | COM1 | +-----+-------+----------------------------------------+ | 0Dh | IRQ5 | LPT2 | +-----+-------+----------------------------------------+ | 0Eh | IRQ6 | FDC(Floppy Disk Controller) | +-----+-------+----------------------------------------+ | 0Fh | IRQ7 | LPT1 | +-----+-------+----------------------------------------+ +-----+-------+----------------------------------------+ | 70h | IRQ8 | Real time clock | +-----+-------+----------------------------------------+ | 71h | IRQ9 | Резерв, используется PCI | +-----+-------+----------------------------------------+ | 72h | IRQ10| Резерв, используется PCI | +-----+-------+----------------------------------------+ | 73h | IRQ11| Резерв, используется PCI | +-----+-------+----------------------------------------+ | 74h | IRQ12| Мышь PS/2, Резерв, используется PCI | +-----+-------+----------------------------------------+ | 75h | IRQ13| 80387 математический сопроцессор | +-----+-------+----------------------------------------+ | 76h | IRQ14| Первичный канал IDE HDD | +-----+-------+----------------------------------------+ | 77h | IRQ15| Вторичный канал IDE HDD | +-----+-------+----------------------------------------+ Пример программирования PIC. В защищенном режиме процессора прерывания от процессора занимают вектора с 0 по 13h и c 14h по 1Fh зарезервированы для внутренних исключений и прерываний процессора. Так что аппаратные прерывания надо подвинуть. ПКП может находиться в двух основных состояниях: настройки и обслуживания запросов на прерывания. В состоянии настройки контроллер принимает управляющие слова инициализации (Initialization Command Words, ICW), в состоянии обслуживания - операционные управляющие слова (Operation Control Words, OCW). Initialization Command Words (ICW1- ICW4) Командные слова для инициализации. Operation Command Words (OCW1- OCW3) Командные слова для действий. Перед началом работы процессор должен инициировать контроллер. Последовательностью из 2-4 команд ICW. После инициализации можно отправлять OCW. Команды инициализации подаются одна за другой. Сначала ICW1 затем ICW2 если был выбран каскадный режим, то подается ICW3 и если был запрошен то ICW4. Формат команд 9битный. 8 бит сама команда, а 9 бит это бит с шины адреса, он задается номером порта. Четный порт соответствует 0, а нечетный 1. Для вывода информации в ПКП используются 2 порта ввода-вывода. Порт с четным адресом (обычно это порт 20h) и порт с нечетным адресом (обычно 21h). Через эти порты могут быть переданы 4 слова инициализации (Initialization Control Word, ICW1 - ICW4), задающие режим работы ПКП, и 3 операционных управляющих слова (слова рабочих приказов, Operation Control Words, OCW1 - OCW3). В порт с четным адресом выводятся ICW1, OCW2 и OCW3. OCW2 отличается от OCW3 тем, что бит 3 в ocw2 равен 0, а в OCW3 равен 1. В то же время бит 4 в OCW2 и OCW3 равен 0, а в ICW1 равен 1. Таким образом по значению, выводимому в порт с четным адресом, однозначно определяется, в какой регистр (ICW1, OCW2 или OCW3) заносятся данные. Порт с нечетным адресом используется для вывода ICW2, ICW3, ICW4 и OCW1. Неоднозначности интерпретации данных в этом случае так же не возникает, т. к. слова инициализации ICW2 - ICW4 должны непосредственно следовать за ICW1, выведенным в порт с четным адресом и выводить в промежутке между ними OCW1 не следует, онo не будет опознанo контроллером. Выводом в порт с четным адресом управляющего слова инициализации ICW1 начинается инициализация ПКП. В процессе инициализации контроллер последовательно принимает управляющие слова ICW1 - ICW4. При наличии в системе одного контроллера ICW3 не выводится. Наличие ICW4 определяется содержанием ICW1. При наличии каскада из нескольких ПКП каждый из них инициализируется отдельно. Код (Text): A0 7 6 5 4 3 2 1 0 +----+----+----+----+----+----+----+----+----+ | 1 | T7 | T6 | T5 | T4 | T3 | 0 | 0 | 0 | +----+----+----+----+----+----+----+----+----+ Формат ICW2 , это номер начального вектора прерывания. Биты 0-2 должны быть 0. При приходе прерывания. Номер линии, на которую пришло прерывание, складывается с этим числом. И выставляется на шину адреса. Пример инициализации ПКП. Вектора ведущего будут иметь базу 20h, а ведомого 28h Код (Text): MOV DX, 20h // Ведущий MOV AH, 20h //Номер начального прерывания для ведущего контроллера 08 стандартное для реального режима // Для защищенного Я выбрал 20h MOV AL,11h //ICW1 бит 0=1 сигнализирует, что будет послан ICW4 OUT DX,AL MOV AL,AH //ICW2 - начальный номера прерываний биты 2-0=0. INC DX OUT DX,AL MOV AL,4 //ICW3 ведущий 00000100 - ведомый подключен ко второй линии OUT DX,AL MOV AL,1 //ICW4 режим 86/88 OUT DX,AL MOV DX, 0A0h // Ведомый MOV AH, 28h //Номер начального прерывания для ведомого контроллера 70h стандартное для реального режима // Для защищенного Я выбрал 28h MOV AL,11h //ICW1 бит 0=1 сигнализирует, что будет послан ICW4 OUT DX,AL MOV AL,AH //ICW2 - начальный номера прерываний биты 2-0=0. INC DX OUT DX,AL MOV AL,2 //ICW3 ведомый, ведомый подключен ко второй линии ведущего OUT DX,AL MOV AL,1 //ICW4 режим 86/88 OUT DX,AL Управляющее слово OCW1 Код (Text): A0 7 6 5 4 3 2 1 0 +----+----+----+----+----+----+----+----+----+ | 1 | M7 | M6 | M5 | M4 | M3 | M2 | M1 | M0 | +----+----+----+----+----+----+----+----+----+ Установленный в 1 бит маскирует соответствующее прерывание. Это значит, что пришедшее прерывание не будет обрабатываться.
Замаскировать прерывания можно по разному. К примеру в ЦП, а именно в регистре EFLAG Командами CLI // сбрасывает флаг прерываний IF. Тем самым запрещает прерывания. STI // устанавливает флаг прерываний IF. Тем самым разрешает прерывания. Также как я уже писал прерывания можно замаскировать в самом ПКП Код (Text): MOV AL, 0FFh // маскируем все прерывания OUT 21h, AL // OCW1 MOV AL, 000h // разрешаем все прерывания на ведущем OUT 21h, AL // OCW1 MOV AL, 000h // разрешаем все прерывания на ведомом OUT 0A1h, AL // OCW1
BVOG А ты какой таймер программируешь? Интервальный? Так от него прерывания и так разрешены. И генерирует он IRQ0 / INT8 18.2 раза в секунду. И прерывания от клавиатуры разрешены. IRQ1 / INT9 И несколько вопросов, так как в твоем коде откровенно не разобрался. Ты бы подсказал, где у тебя точки входа в обработчики...... И как ты определяешь, что обработчики не вызываются? И вызывает интерес, вот такой еще разрез... Ты уверен, что при входе в твой обработчик процессор переходит в 32 битный режим?
MisHel64 Вот весь код Код (Text): ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Protected Mode Initialization ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; pmode_init: in al, 092h or al, 2 out 092h, al in al, 070h or al, 080h out 070h, al xor eax, eax mov ax, cs shl eax, 4 add eax, gdt mov [cs:addr], eax lgdt fword ptr gdtr xor eax, eax mov ax, cs shl eax, 4 add eax, idt mov [cs:idt_addr], eax lidt fword ptr idtr mov eax, cr0 or ax, 1 mov cr0, eax jmp pword 0x08:pmode+0x10000 gdt: null db 8 dup(0) code db 0ffh, 0ffh, 00h, 00h, 00h, 10011010b, 11001111b, 00h data db 0ffh, 0ffh, 00h, 00h, 00h, 10010010b, 11001111b, 00h video db 0ffh, 00h, 080h, 0bh, 00h, 10010010b, 01000000b, 00h gdt_end: gdtr: size: dw gdt_end - gdt addr: dd 0x7400 idt: dq 0 ;0 dq 0 ;1 dq 0 ;2 dq 0 ;3 dq 0 ;4 dq 0 ;5 dq 0 ;6 dq 0 ;7 dq 0 ;8 dq 0 ;9 dq 0 ;10 dq 0 ;11 dq 0 ;12 exGP: dw (gp+0x10000) and 0xFFFF dw 00001000b dw 1000111000000000b exGP2: dw (gp+0x10000) shr 16 rb idt+32*8-$ extm: dw (timer+0x10000) and 0xFFFF dw 00001000b dw 1000111000000000b extm2: dw (timer+0x10000) shr 16 rb idt+256*8-$ idt_end: idtr: idt_size: dw idt_end - idt idt_addr: dd 0x6c00 rb start+512+1024*4-$ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Protected Mode Entry Point ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Use32 pmode: ; Загрузить сегментные регистры и инициализировать стек mov ax, 00010000b mov ds, ax mov ss, ax mov fs, ax mov gs, ax mov esp, 0x2FFFC mov ax, 00011000b mov es, ax mov eax, 0xB800 shl eax, 4 add eax, 80*2*3 mov esi, eax mov eax, 0x1000 shl eax, 4 add eax, pm mov edi, eax mov ah, 0x0f mov cx, 68 cirpm: mov al, [ds:edi] mov [ds:esi], ax inc edi inc esi inc esi loop cirpm ;include "gui.inc" mov cl, 0x20 mov ch, 0x28 mov al, 0x11 ; IWC1 out 0x20, al out 0xA0, al mov al, cl ; IWC2 out 0x21, al mov al, ch out 0xA1, al mov al, 0x04 ; IWC3 out 0x21, al mov al, 0x02 out 0xA1, al mov al, 0x01 ; IWC4 out 0x21, al out 0xA1, al mov al, 0x00 out 0x21, al out 0xA1, al in al, 070h and al, 7Fh out 70h, al sti mov eax, 0xB800 shl eax, 4 add eax, 80*2*4+20 mov esi, eax circle: inc byte [ds:esi] jmp circle pm db ' Protected mode initializated. To return in Real Mode Reset Computer ' hextostr: mov edx, ebx xor ecx, ecx xor eax, eax mov eax, 0x1000 shl eax, 4 add eax, hex and ebx, 0x0000000F add eax, ebx mov esi, eax mov cl, [ds:esi] xor eax, eax mov eax, 0xB800 shl eax, 4 add eax, 80*2*4+8 mov edi, eax mov ch, 0x0F mov [ds:edi], cx mov ebx, edx xor ecx, ecx xor eax, eax mov eax, 0x1000 shl eax, 4 add eax, hex and ebx, 0x000000F0 shr ebx, 4 add eax, ebx mov esi, eax mov cl, [ds:esi] xor eax, eax mov eax, 0xB800 shl eax, 4 add eax, 80*2*4+6 mov edi, eax mov ch, 0x0F mov [ds:edi], cx ret hex db '0123456789ABCDEF' gp: pop eax pusha mov ebx, eax call hextostr mov eax, 0xB8000+80*2*4+2 mov esi, eax inc byte [ds:esi] popa iretd timer: pusha mov eax, 0xB800 shl eax, 4 add eax, 80*2*4+4 mov esi, eax inc byte [ds:esi] popa jmp int_EOI int_EOI: mov al, 20h out 020h, al out 0a0h, al iretd rb start+65536-2-$ dw 0xB0B0 Проверку на 32-битный режим япроводил двумя способами: выводом на экран в текством режиме и графическом VESA в высших адресах. Проверку прошёл. К памяти свыше 1МБ адресуется как положено.
Прости, но огромное количество комментариев, так усложнило разбор кода, что мой мозг просто не с правился с поиском кода устанавливающего прерывания и точек входа в обработчики. Успехов!
Прошу прощения за оффтоп, но помню у меня не получилось обрабатывать прерывания от клавы в RM. Контроллер прерываний настроен на базовый адрес. Прерывание 1Сh обрабатывается прекрасно. А вот 09h никак не обрабатывается, хотя ставлю аналогично 1Ch (но если 09h вызвать ручками, то всё прекрасно работает). В чём может быть проблема?
Что то странно. В регистр команд клавы прописал следующее: Код (Text): mov al, 11110010b out 64h, al Нет результата. Может что-нибудь не так с приоритетами?
Вот кусок кода: Код (Text): off_09h equ 9h*4 xor es, es mov ax, keyboard ;адрес обработчика mov [es:off_09h], ax push cs pop ax mov [es:off_09h+2], ax keyboard: push ax push bx push es push ds push cs pop ds in al, 60h; показываем что нажали mov ah, 07h mov bx, 0b800h mov es, bx mov [es:0], ax mov al, 20h; шлём EOI out 0A0h, al out 20h, al pop ds pop es pop bx pop ax iret
Я вот не совсем понял, как вы обрабатываете прерывания клавиатуру в реальном режиме? Я знаю только один вариант - перезаписать адресы обработчиков c адреса 0000 по адрес 0x03F0 .
Таблица прерываний находится в 1'ом кб. Я по смещению 09h*4 в первые 2 байта записываю адрес обработчика, в остальные 2 - сегмент.