flat assembler
Message board for the users of flat assembler.
Index
> OS Construction > PIC, IRQ, IDT, and ISR's...? Goto page 1, 2 Next |
Author |
|
newport 08 Nov 2014, 20:26
So I've got my os working(32-bit PMode) and the kernel loads it's messages, and system halts...no problem here. I've decided to go back and actually implement a working IDT instead of the temporary one I've been using. But I don't understand how it all works together. According to osdev,
Quote: Basically, when a key is pressed, the keyboard controller tells a device called the Programmable Interrupt Controller, or PIC, to cause an interrupt. Because of the wiring of keyboard and PIC, IRQ #1 is the keyboard interrupt, so when a key is pressed, IRQ 1 is sent to the PIC. The role of the PIC will be to decide whether the CPU should be immediately notified of that IRQ or not and to translate the IRQ number into an interrupt vector (i.e. a number between 0 and 255) for the CPU's table.
Last edited by newport on 08 Nov 2014, 22:05; edited 2 times in total |
|||||||||||
08 Nov 2014, 20:26 |
|
newport 08 Nov 2014, 21:09
ok.. this didn't work, i set int 33 to point to isr 33 to simply display the letter 'a' on the screen whenever i press a key but that didn't work.. so back to square one....
|
|||
08 Nov 2014, 21:09 |
|
smiddy 09 Nov 2014, 18:17
I wrote mine a long time ago, I'll see if I can piece this together for you:
PIC.ASM Code: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; PIC.asm - Contains the Programmable Interrupt Controller interface routines ;; for the kernel. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; IRQMap dd 0FFFFFFFFh ; 32bit (LSb to MSb) map of IRQs: 1 = Off, 0 = On ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; RemapPICToProtectedMode - Remaps IRQs from the BIOS defaults interrupts to ;; INT 20h - 2Fh. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RemapPICToProtectedMode: push eax mov al,11h ; Initialization Command Word (ICW) 1 out 20h,al ; Into first PIC out 0A0h,al ; Into casscaded second PIC mov al,20h ; Load starting interrupt 20h (ICW2) out 21h,al ; Into first PIC mov al,28h ; Load starting interrupt 28h out 0A1h,al ; Into second PIC mov al,04h ; ICW3 out 21h,al ; First PIC mov al,02h ; ICW3 out 0A1h,al ; Second PIC mov al,01h ; ICW4 out 21h,al ; First PIC out 0A1h,al ; Second PIC pop eax ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; RemapPICToRealMode - Remaps IRQs from the BIOS defaults interrupts to ;; INT 20h - 2Fh. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RemapPICToRealMode: push eax mov al,11h ; Initialization Command Word (ICW) 1 out 20h,al ; Into first PIC out 0A0h,al ; Into casscaded second PIC mov al,08h ; Load starting interrupt 08h (ICW2) out 21h,al ; Into first PIC mov al,70h ; Load starting interrupt 70h out 0A1h,al ; Into second PIC mov al,04h ; ICW3 out 21h,al ; First PIC mov al,02h ; ICW3 out 0A1h,al ; Second PIC mov al,01h ; ICW4 out 21h,al ; First PIC out 0A1h,al ; Second PIC pop eax ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; DisableAllIRQs - Disables all IRQs regardless of masking: ;; ;; Operation Command Word 1: ;; ;; |7|6|5|4|3|2|1|0| OCW1 - IMR Interrupt Mask Register ;; | | | | | | | `---- 0 = service IRQ0 or IRQ8, 1 = mask off ;; | | | | | | `----- 0 = service IRQ1 or IRQ9, 1 = mask off ;; | | | | | `------ 0 = service IRQ2 or IRQA, 1 = mask off ;; | | | | `------- 0 = service IRQ3 or IRQB, 1 = mask off ;; | | | `-------- 0 = service IRQ4 or IRQC, 1 = mask off ;; | | `--------- 0 = service IRQ5 or IRQD, 1 = mask off ;; | `---------- 0 = service IRQ6 or IRQE, 1 = mask off ;; `----------- 0 = service IRQ7 or IRQF, 1 = mask off ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DisableAllIRQs: push eax mov al,0FFh ; Turn all IRQs off out 21h,al ; First PIC out 0A1h,al ; Second PIC pop eax ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; EnableAllMaskedIRQs - Enables all masked IRQs. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; EnableAllMaskedIRQs: push eax push ebx cli mov ebx,[IRQMap] ; Load current IRQ bitmap mov al,bl ; First 8 IRQs mapped out 021h,al mov al,bh ; Second 8 IRQs mapped out 0A1h,al sti pop ebx pop eax ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; EnableAllIRQs - Enables all IRQs. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; EnableAllIRQs: push eax cli mov al,0 ; First 8 IRQs mapped out 021h,al mov al,0 ; Second 8 IRQs mapped out 0A1h,al sti pop eax ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; EnableAnIRQ - Enables one IRQ based on 32bits. ;; ;; Input: EAX contains IRQ number to enable. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; EnableAnIRQ: push eax push ebx push ecx mov ecx,eax mov eax,1 shl eax,cl not eax and eax,[IRQMap] mov [IRQMap],eax call EnableAllMaskedIRQs pop ecx pop ebx pop eax ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; DisableAnIRQ - Disables one IRQ based on 32bits. ;; ;; Input: EAX contains IRQ number to disable. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DisableAnIRQ: push eax push ebx push ecx mov ebx,eax mov eax,1 mov ecx,ebx shl eax,cl or eax,[IRQMap] mov [IRQMap],eax call EnableAllMaskedIRQs pop ecx pop ebx pop eax ret I go back and forth between real and protected modes. I'll get you the ISRs and Keyboard and RTC stuff later....sorry, I have to run. |
|||
09 Nov 2014, 18:17 |
|
l_inc 09 Nov 2014, 18:49
newport
If you set a bit in the mask, the corresponding interrupt is masked. Therefore you don't receive any interrupts. And for your own convenience, please, start giving names to bits and enumeration values. Those bare numbers are not readable. _________________ Faith is a superposition of knowledge and fallacy |
|||
09 Nov 2014, 18:49 |
|
newport 09 Nov 2014, 20:07
Thank you both for the reply's!
|
|||
09 Nov 2014, 20:07 |
|
smiddy 10 Nov 2014, 11:03
Interrupt addition and deletion:
Code: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; AddISRToIDT - Adds an ISR to the IDT, then reloads the IDT. ;; ;; Assumptions: User has already turned off interrupts. ;; ;; Input: ESI = Address of ISR ;; EAX = The number of the IRQ to load ;; ;; Output: EDI = Address of previous ISR (not functioning yet) ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; AddISRToIDT: mov ebx,eax ; Copy EAX into EBX mov eax,8 ; Place 8 into EAX mul ebx ; Multiply EAX by EBX to get offset of IRQ in IDT mov ebx,eax ; Copy EAX into EBX mov eax,IDTISRStart ; Load address of starting IRQ in IDT add eax,ebx ; Add offset of IRQ into EAX mov ecx,esi ; Place address of ISR into ECX mov [ds:eax],cx ; Copy lower 16 bits into IDT entry shr ecx,16 ; Move upper 16 bits into CX mov [ds:eax + 6],cx ; Copy upper 16 bits into IDT entry ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; AddExceptionToIDT - Adds an exception ISR to the IDT, then reloads the IDT. ;; ;; Assumptions: User has already turned off interrupts. ;; ;; Input: ESI = Address of ISR ;; EAX = The number of the Exception to load ;; ;; Output: EDI = Address of previous ISR (not functioning yet) ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; AddExceptionToIDT: mov ebx,eax ; Copy EAX into EBX mov eax,8 ; Place 8 into EAX mul ebx ; Multiply EAX by EBX to get offset of IRQ in IDT mov ebx,eax ; Copy EAX into EBX mov eax,IDT ; Load address of starting IRQ in IDT add eax,ebx ; Add offset of IRQ into EAX mov ecx,esi ; Place address of ISR into ECX mov [ds:eax],cx ; Copy lower 16 bits into IDT entry shr ecx,16 ; Move upper 16 bits into CX mov [ds:eax + 6],cx ; Copy upper 16 bits into IDT entry ret |
|||
10 Nov 2014, 11:03 |
|
BAiC 11 Nov 2014, 02:16
smiddy wrote:
I don't usually comment on code optimization but I feel this example needs to be simplified. Code: lea eax,[ebx*8+IDTISRStart] mov ecx,esi ; Place address of ISR into ECX shr ecx,16 ; Move upper 16 bits into CX mov [ds:eax + 0],si ; Copy lower 16 bits into IDT entry mov [ds:eax + 6],cx ; Copy upper 16 bits into IDT entry ret you don't even need the LEA if you're willing to re-calculate the value for the second write. btw; DS doesn't need to be explicitly declared. DS is implicitly used when a segment register isn't referenced. - Stefan _________________ byte me. |
|||
11 Nov 2014, 02:16 |
|
revolution 11 Nov 2014, 02:43
Keep in mind that that only works when the magic value of 8 is hard coded into the source. If it is a defined constant (like say "sizeof.MYSTRUCTURE") then only certain values will work before the assembler complains about being unable to encode it.
|
|||
11 Nov 2014, 02:43 |
|
smiddy 11 Nov 2014, 03:15
BAiC wrote:
I appreciate the criticism actually. I wrote that about 8 years ago, when I was first learning to code in 32 bit ASM, There are a lot of way to skin a cat. Turpentine is a way, but I wouldn't recommend it. I haven't gotten back around to this part yet in my latest attempt but am getting better in my coding. Smiddy |
|||
11 Nov 2014, 03:15 |
|
smiddy 11 Nov 2014, 03:19
revolution wrote: Keep in mind that that only works when the magic value of 8 is hard coded into the source. If it is a defined constant (like say "sizeof.MYSTRUCTURE") then only certain values will work before the assembler complains about being unable to encode it. |
|||
11 Nov 2014, 03:19 |
|
BAiC 11 Nov 2014, 04:57
revolution wrote: Keep in mind that that only works when the magic value of 8 is hard coded into the source. If it is a defined constant (like say "sizeof.MYSTRUCTURE") then only certain values will work before the assembler complains about being unable to encode it. this is why I don't I don't talk about optimization: stupid mother fuckers like revolution twist my comments into something they're not... I wasn't providing a general optimization example. I was just optimizing a specific program. _________________ byte me. |
|||
11 Nov 2014, 04:57 |
|
revolution 11 Nov 2014, 09:01
Treat it as an opportunity to make a macro:
Code: ;... if sizeof.MYSTRUCTURE in <1,2,3,4,5,8,9> lea eax,[ebx*sizeof.MYSTRUCTURE+IDTISRStart] else mov eax,sizeof.MYSTRUCTURE mul ebx add eax,IDTISRStart end if ;... |
|||
11 Nov 2014, 09:01 |
|
newport 12 Nov 2014, 00:25
I have no idea what I'm doing wrong.. I've tried to use the suggestions and other posts i've read, and I just can't get it working... i'm so frustrated right now.
|
|||
12 Nov 2014, 00:25 |
|
smiddy 12 Nov 2014, 04:03
Here's my clock, uses the above code:
Code: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; CLOCK.ASM - Contains the driver code for the OS clock, which is internal ;; to the kernel at this time. Takes control of the PIT... ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Header - This is the header used by smiddyOS device drivers. ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Data elements ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; TimerCounter dq 0 ; Initialized to zero Frequency1KHz dw 004A9h ; Divisor 1193180 / 1193 = 1000 Frequency100Hz dw 02E9Bh ; Divisor 1193180 / 11931 = 100 Frequency18_2Hz dw 0FFFFh ; Divisor 1193180 / 65535 = 18.2 ClockInitializationMessage db 'smiddyOS Clock Initializing...',0 ClockInstalledMessage db 'Done!',13,10,0 InClockMessage db 13,10,'In the clock after 6,000 tics',13,10,0 InitializeClock: mov esi,ClockInitializationMessage call PrintString32 ; Disable interrupts cli ; Disable all IRQs call DisableAllIRQs ; Reprogram PIT - 0 for timer of 1/1000 seconds (if possible) ; Timer 8253/54 Ports: ; 40h Channel 0 counter (read/write) ; 41h Channel 1 counter (read/write) ; 42h Channel 2 counter (read/write) ; 43h Control Word (write only) ; ; Control Word: ; 7 6 5 4 3 2 1 0 ; SC1 SC0 RL1 RL0 M2 M1 M0 BCD ; ^ ; 0 Binary Counter ; 1 BCD (4 decades) ; ^ ^ ^ ; 0 0 0 Mode 0 Interrupt on terminal count ; 0 0 1 Mode 1 Programmable one shot ; x 1 0 Mode 2 Rate Generator ; x 1 1 Mode 3 Square wave rate Generator ; 1 0 0 Mode 4 Software triggered strobe ; 1 0 1 Mode 5 Hardware triggered strobe ; ^ ^ ; 0 0 Counter Latching operation ; 0 1 Read/Load LSB Only ; 1 0 Read/Load MSB Only ; 1 1 Read/Load LSB first, then MSB ; ^ ^ ; 0 0 Select Counter 0 ; 0 1 Select Counter 1 ; 1 0 Select Counter 2 ; 1 1 Illegal mov bx,[Frequency18_2Hz] mov al,34h ; Control Word: 00110100b out 43h,al ; Out control word port mov al,bl ; LSB in BL out 40h,al ; Out channel 0 mov al,bh ; MSB in BH out 40h,al ; Out channel 0 ; Reprogram PIT - 1 for timer of 1/18 seconds (DOS) ; mov bx,[Frequency18_2Hz] ; mov al,74h ; Control Word: 01110100b ; out 43h,al ; Out control word port ; mov al,bl ; LSB in BL ; out 41h,al ; Out channel 1 ; mov al,bh ; MSB in BH ; out 41h,al ; Out channel 1 ; call API to add IRQ ISR to IDT mov esi,ClockISR mov eax,0 call AddISRToIDT sti ; Reprogram PIC for IRQ 0 mov eax,0 call EnableAnIRQ mov esi,ClockInstalledMessage call PrintString32 ret ClockISR: ; 64-bit timer counter (24hrs/day x 60min/hr x 60sec/min x 1000tics/sec = 86,400,000tics/day) ; It can effectively run for 213,503,982,334 days or 584,542,046 years ; Will have to use MMX registers or something else. pushad ; push gs ; push fs ; push ds ; push es add dword [ds:TimerCounter],1 ; 64bit counter variable (there's gotta be a better way) adc dword [ds:TimerCounter + 4],0 ; If carry, then add CF and nothing else ; mov eax,dword [TimerCounter] ; cmp eax,6000 ; Check after one minute of install ; jne .FinishUp ; ; mov esi,InClockMessage ; call PrintString ; ; .FinishUp: mov al,20h ; Send EOI out 20h,al ; To PIC out 0A0h,al ; pop es ; pop ds ; pop fs ; pop gs popad iret To be honest, I haven't had a chance to open up your file yet. I'll try tomorrow while I'm traveling. |
|||
12 Nov 2014, 04:03 |
|
newport 13 Nov 2014, 00:03
Thank you so much smiddy! I'm sure if I could get a simple working example, I could learn how it all fits together to write my own code...it's just most examples i've found on the net include some-sort of C code for doing these things which i'm trying to avoid with my operating system and those which do include assembly have things scattered throughout multiple files which makes it difficult to understand how it all fits together. Thank you for your time...
|
|||
13 Nov 2014, 00:03 |
|
BAiC 13 Nov 2014, 21:35
I found one error while reading your code:
during Interrupt 33 execution the code fails to initialize the ES register. this can send the "a" character anywhere in memory. - Stefan _________________ byte me. |
|||
13 Nov 2014, 21:35 |
|
BAiC 14 Nov 2014, 04:25
I'm a bit slow since my focus is on an ACPI AML decoder but I know one very serious bug with your ISRs:
you don't respond to the interrupt controller. it's been awhile since I've actually written the code for it (I currently use an interrupt redirection service that does it automatically). the final instructions before returning (for the 8259 PIC) is: Code: mov al, 0x60 + 1;ISR1: the keyboard. out 0x20, al you then restore the registers and issue an IRET. _________________ byte me. |
|||
14 Nov 2014, 04:25 |
|
newport 14 Nov 2014, 08:51
I will give this a try BAiC and see what happens. Thank you all for the help.
|
|||
14 Nov 2014, 08:51 |
|
vendu 16 Nov 2014, 00:14
First of all, I just heard about this cool board and this is my first post. I hope it's not too off-topic to link some C code with inline assembly macros, so here you go:
https://github.com/vendu/OS-Zero/blob/master/kern/unit/x86/trap.h And for more info on how to use this junk: https://github.com/vendu/OS-Zero/blob/master/kern/unit/x86/trap.c I hope this helps. _________________ ----8<---- /* vendu */ |
|||
16 Nov 2014, 00:14 |
|
Goto page 1, 2 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.