If I am not mistaken this is the first and possibly only document on cpu interrupts on the forums.No BAMs!! or sudden jokes but just giving out much needed documentation. Before we get to the main, let's quickly go over interrupts.
Imagine the entire internal memory of the cpu as one big book. Now imagine all the letters as individual locations in the cpu memory. The cpu goes along and reads it as we wrote it. Now imagine we call an interrupt. The cpu puts the book down and goes to another part of the book to read, all the while remembering where it stopped. Once the interrupt is done, the cpu will return to where it left off in the book. The interrupt "interrupted" the cpu and told it to perform something else.
Now imagine the actual cpu. It's a d-bag who doesn't want to be interrupted unless it can do so. What's letting it do so is the protected mode. If the protected mode isn't on,however, the cpu will not just ignore it but stop reading entirely. If protected mode is on but the cpu doesn't know what to read at that point, it will also stop reading entirely.
We learned two things from that, for a cpu to handle interrupts it must both know what code to run and it must be in protected mode.
Putting the cpu in protected mode is easy, putting stp to be ran somewhere in your code will turn it on while putting clp will turn it off.Note that putting stp it in the end of the code will do nothing since it wasn't "ran".
Now that that's done we get to the hard part, the interrupt table. The interrupt table is extremely tricky and has its ups and downs. For one, the table is 512 bytes in size and that amount must be allocated for it. To "allocate" it we use the alloc opcode. We also must make a label and then immediately afterwards put alloc 512. This allocates 512 bytes starting from that label.
Think we're done, nope. After allocating 512 bytes after the label(And yes it is really 512 bytes check your code size) we must state that the table is to begin after the label. This is done with the lidtr opcode. This is telling the cpu to start the "interrupt descriptor table resgistry" (or lidtr) at where the lidtr is pointing. The lidtr is where all the ints(or interrupts) are located. To clarify it's
Code:
lidtr(Label Name here)
Think we're done now, nope. This next part has to be done with a register like edi,eax,etc..
Now you will set the register to point at the label you specified for the lidtr to start at. Then you will add to that register twice the number of the interrupt you want to use.Note that the interrupt table looks like.... 0..31 are the reserved ints(like the ones you see when the code screws up like 2 is end of code...) 32..256 are the user ints and nmis and thats what we will be using, specifically int 32. Now most of you with good math skills will be asking,"If there are only 256 interrupts(or ints) then why is the table 512 bytes?" Now here's why smartass, the table goes like entry point ,present ,entry point ,present....
Each int has an entry point and a present value (which is always 32).So two for every int means twice as many ints for memory or 2*256=512 bytes for space. The entry point is where you want the code to be directed to or where the code will go when that certain interrupt is there. You must also set the next byte, or present, to 32. All of that would look like..
Code:
stp//This puts protected mode on
jmp Int_SetterUpper
Int_Table://Let's say this is at memory location #3
alloc 512//There are 512 free bytes between these two lines of code(I.E. this is at #515)
Int_SetterUpper:
sti// This makes all interrupts be capable of being activated
lidtr Int_table// Int_Table is where the table will start and we just set it to start there.
mov edi,int_table// This is so we can do stuff inside the table
add edi,64//We added 64 to get to int 32 cuz each one has 2 parts, remember?
mov #edi,Int_Code// We just set int 32 to do "Int_Code" whenever int 32 is ran
inc edi// To get to the "present" cuz we just came from the entry point
mov #edi,32// Now int 32 is "present" Note the 32 is constant and has nothing to do
// with it being int 32 Still think we're done, well we are. Note that "Int_Code" can be any piece of code and doesn't have to have int in it. Any questions can be sent to me or Black Phoenix when he gets back from the 13th dimension. Also note that cli turns ints off while clp turns protected mode off. Also heavily note that the ints from 32..255 have to be activated from the nmi on the cpu and ALSO HEAVILY note to return from nmi's you use nmiret.
And here is the unabridged version of my own code..
Code:
stp
jmp Init
Interrupt_Table:
alloc 512
Init:
sti
lidtr Interrupt_Table
mov ebx,Interrupt_Table
add ebx,64
mov #ebx,Int_Start
inc ebx
mov #ebx,32
jmp Idler
Int_Start:
cli
out 0,1337
nmiret
Idler:
add eax,0.001
out 0,eax
jmp Idler
Thanks to Black Phoenix for the book example.
Bookmarks