Mail Archives: djgpp/2000/01/08/23:09:02
From: | NoEmailAds AT execpc DOT com (Chris Giese)
|
Newsgroups: | alt.os.development,alt.os.assembly,comp.os.msdos.djgpp,alt.lang.asm
|
Subject: | Re: ISR with DJGPP in a kernel.
|
Date: | Sun, 09 Jan 2000 02:43:47 GMT
|
Organization: | Church of the SubGenius - Propulsion Group
|
References: | <s7dr49t5oj886 AT corp DOT supernews DOT com>
|
X-Newsreader: | Forte Free Agent 1.11/32.235
|
Lines: | 151
|
Message-ID: | <3877f58e$0$1379@news.execpc.com>
|
NNTP-Posting-Host: | 6b640537.news.execpc.com
|
X-Trace: | 0RW8S?BXNaRI5[332>a9Y[bfNiaEHUgJWRYcgIRLSUE]>VTjIHLkV<WfXg\jTb[AT]lO<3E9iRX4W6=oZ8VFQiOQ
|
X-Complaints-To: | abuse AT execpc DOT com
|
To: | djgpp AT delorie DOT com
|
DJ-Gateway: | from newsgroup comp.os.msdos.djgpp
|
Reply-To: | djgpp AT delorie DOT com
|
Mind-control rays from black helicopters made Groman
<groman AT thehelm DOT com> write:
>I am writing a small kernel using DJGPP and NASM, and I bumped into several
>problems(again).
>
>Ok...here are my steps.
>
>1) I create the IDT and load the register.
>2) I reprogram the PIC to shift the IRQs so they do not overlap with the
>exceptions.
>3) I disable all IRQs beside 2 and 0.
>Now I want to create a handler for 0(the timer) in C...
>now, how exactly do I do that... I mean it jumps out of the code right in
>the middle of the function...and starts another one?
Yes, that's how interrupts work.
>shoud I do the handler in assembly that calls C functions then? or is there
>a way to turn an ordinary DJGPP function
>into a handler...
Using DPMI (DJGPP + CWSDPMI or Win95 + DOS):
#include <sys/farptr.h> /* _farpokeb(), _farpeekb() */
#include <conio.h> /* kbhit(), getch() */
#include <dos.h> /* outportb() */
#include <go32.h> /* _my_cs() */
#include <dpmi.h> /* _go32_dpmi_... */
/*****************************************************************************
*****************************************************************************/
void irq8(void)
{/* increment char at upper left corner of screen */
_farpokeb(_dos_ds, 0xB8000L,
_farpeekb(_dos_ds, 0xB8000L) + 1);
/* reset 8259-compatible interrupt controller */
outportb(0x20, 0x20); }
/*****************************************************************************
name: main
*****************************************************************************/
int main(void)
{ _go32_dpmi_seginfo OldVector, NewVector;
/* save the old vector */
_go32_dpmi_get_protected_mode_interrupt_vector(8, &OldVector);
/* install new interrupt handler */
NewVector.pm_selector=_my_cs();
NewVector.pm_offset=(unsigned long)irq8;
_go32_dpmi_allocate_iret_wrapper(&NewVector);
_go32_dpmi_set_protected_mode_interrupt_vector(8, &NewVector);
/* main loop */
getch();
/* restore old vector */
_go32_dpmi_set_protected_mode_interrupt_vector(9, &OldVector);
return(0); }
If you're writing an interrupt handler for your own OS, you need code
to replace the _go32_dpmi...() functions above. The main concern is
saving the values of the CPU registers when the interrupt occurs.
This has to be done in assembler. Maybe something like this:
[SECTION .text]
[BITS 32]
isr0: push byte 0 ; push error code
push byte 0 ; push interrupt #
jmp short fault1
isr1: push byte 0
push byte 1
jmp short fault1
;
; ...
;
isr8: nop ; interrupt 8 is Double Fault
nop ; It pushes an error code, so we don't have to
push byte 8
jmp short fault1
;
; ...
;
isr0D: nop ; general protection fault
nop
push byte 0x0D
jmp short fault1
;
; ...
;
isr20: nop ; timer tick
nop
push byte 0x20
jmp short fault1
;
; ...
;
isr30: nop ; syscall!
nop
push byte 0x30
jmp short fault1
;
; ...
;
fault1: push gs
push fs
push es
push ds
; save the 7 general-purpose registers
pusha
; hopefully, the interrupt set SS automatically
; if the data and stack are in the same segment, we can do this:
; copy SS to DS, ES, FS, and GS
mov ax,ss
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
[EXTERN _my_isr]
call _my_isr
popa
pop ds
pop es
pop fs
pop gs
; drop exception # and error code
add esp,8
iret
The C language handler looks like this:
void fault(volatile long EDI, volatile long ESI, volatile long EBP,
volatile long ESP, volatile long EBX, volatile long ECX,
volatile long EAX, volatile long DS, volatile long ES,
volatile long FS, volatile long GS, volatile long WhichInt,
volatile long ErrCode, volatile long EIP, volatile long CS,
volatile long EFLAGS, volatile long UserESP,
volatile long UserSS)
{
// look at WhichInt, figure out if this is a fault,
// hardware interrupt, or syscall
}
If this is a system call interrupt (interrupt 0x30 in this case), you
can fiddle with the user-mode register values on the stack. The
assembly-language code will pop those values back into the registers
when you return. This is NOT something you want to do with a hardware
interrupt (timer, keyboard, etc.)
--
geezer@ | Sales rushes in where
execpc.com | Engineering fears to tread
pmode tutorial, homebrew OS: http://www.execpc.com/~geezer/os
- Raw text -