Page 2 of 2

Re:I need an IDT tutorial... Or a fix?

Posted: Mon Oct 21, 2002 12:48 am
by Pype.Clicker
and now comes the "real handler" code:

Code: Select all

processException:
   pushad                   ; save every generic register
   mov ebp,esp
   sub ebp,erShot._edi
   mov edx,[ebp+erShot.number] ; get back the exc number
   test byte [ebp+erShot._cs],IA_SELDPL 
; if the exception occured in user mode, the DPL field of the CS 
; register will not be nul. if so, we branch to a specific 
; save/call/restore chain (not here)
   jnz .userlevel

.kernlevel:
   mpush ss,gs,fs,ds,es ; do the following pushes in order
; this is a macro described in NASM manual.
   mov ax,S_dataos ; enforces well-known segments
   mov bx,S_zeroos
   mov ds,ax
   mov gs,bx
   mov es,ax
   marker YELLOW  ; just a debug trick of mine: turn border to yellow -- see debug.ash in clicker-kernel/src/head/asm
   and edx,0xf
   mov al,[HexTable+edx]
   mov ah,0x09
   mov [gs:158+0xb8000],ax 
; debug: write exception number in the top-right corner of the 
; screen

; now we call the C exception handler and give it a pointer to the 
; stack frame so that it can change the registers value, or dump 
; them, whatever :)
   fcall _processExcList,ebp
   marker LBLUE ; border blue -> all right
   mpop gs,fs,ds,es
   add esp,4      ; ss skipped!

.common:
   popad
   add esp,8 ; pops EXC number & error code
   iretd
The thing I don't get is this: I don't know how I would pick up the error codes that are passed to them, would I pop them off the stack onto a temp variable?
i've showed you the easiest way i found for doing this: you have a er_shot structure that defines everything that will be useful on the stack in case of an exception.

Code: Select all

struc erShot
._es:   resd 1  ;; mpush ss,gs,fs,ds,es
._ds:   resd 1
._fs:   resd 1
._gs:   resd 1
._ss:   resd 1

._edi:   resd 1  ;; pushad
._esi:   resd 1
._ebp:   resd 1
._esp:   resd 1
._ebx:   resd 1
._edx:   resd 1
._ecx:   resd 1
._eax:   resd 1

.number:   resd 1  ;; push %1
.errcode:   resd 1   ;; CPU | push 0

._eip:   resd 1  ;; interrupt frame
._cs:   resd 1  ;;
._flags:   resd 1
endstruc
Note that this structure is to be used only in case of a kernel-mode exception. you also have to get a pointer on it. The easiest way i found is to catch the stack pointer and substract the offset within the structure, for instance just after the pushad

Code: Select all

lea ebp,[esp-er_Shot._edi]
but it should also be done after pushing the segments.
I have to say Thanks Pype, for at least trying to fix my code, and for making me realize that my junk exceptions will never do...
no problemo ... i think with this post, you have your tutorial as well ;)

Re:I need an IDT tutorial... Or a fix?

Posted: Wed Oct 23, 2002 6:20 pm
by Warmaster199
I haven't quite had time to fix my handlers, but I have check over my code again (several times). I think that for now, I'm going to make all of my exceptions recive a 0 for error code (Will that be a problem?). My code that I will implement will be like this:

EXTERN _do_exp00

EXP_00
   push gs
   push fs
   push es
   push ds
   push ss
   pusha
   mov eax, KERNEL_DS   ; load our seg regs up...
   mov ds,eax
   mov es,eax
   mov fs,eax
   mov gs,eax
   mov eax,esp
   push eax      ; push pointer to regs
   push 0      ; push error code
   call _do_exp00
   add esp, 4
   pop eax
   popa
   pop ss
   pop ds
   pop es
   pop fs
   pop gs
   iret

/* I think we should be allowed to continue after this... */
void do_exp00(int errorcode, struct *pt_regs)
{
printk("EXCEPTION 00: DIVISION BY ZERO OR DIVISION OVERFLOW\n");
}

I can't test because I have no disk to test with... (I am too lazy to go into my backpack and get it - maybe tomarrow ;D ). Any suggestions to prevent serious stack leaks, make sure the args are passed correctly, etc... ?