Page 1 of 2

Interrupt Error Code and the Stack

Posted: Wed Aug 17, 2011 2:43 am
by mark3094
I've been looking at Brans Kernel Development Tutorial (http://www.osdever.net/bkerndev/Docs/isrs.htm), and for the dummy error code, a BYTE is being pushed:

Code: Select all

_isr1:
    cli
    push byte 0
    push byte 1
    jmp isr_common_stub
I was looking in the Intel Manual 3A, section 6.13, and it appears that the error code is 32 bits, not 8.

In this case, why push a byte, not a DWORD?

Re: Interrupt Error Code and the Stack

Posted: Wed Aug 17, 2011 2:54 am
by Combuster
Because it only requires a byte to push more than one. There is no such thing as adding one byte to the stack with that opcode, it's always two/four/eight depending on operating mode.

Re: Interrupt Error Code and the Stack

Posted: Wed Aug 17, 2011 3:04 am
by mark3094
ah... I see...

Makes perfect sense now


Thankyou for you insight

Re: Interrupt Error Code and the Stack

Posted: Wed Aug 17, 2011 3:11 am
by Nessphoro
But I recommend to change that to push dword, because later you might have some problems.

Re: Interrupt Error Code and the Stack

Posted: Wed Aug 17, 2011 3:14 pm
by Gigasoft
I'm glad I stopped using NASM. I've been using MASM for a while, then switched over to JWASM. It saves a lot of typing, "push byte" being an example. However, this seems like it was written a very long time ago, and since then the -Ox option has been introduced in NASM, which takes care of "push byte ..." and "add dword [...],byte ..." for you.

Re: Interrupt Error Code and the Stack

Posted: Wed Aug 17, 2011 4:00 pm
by mark3094
Thankyou for your help. I'll look at changing those BYTEs to DWORDs.

Would passing control to a C function like this be suitable?:

Code: Select all

void isr(unsigned char isr, unsigned int err) {
/* Code in here */
}
I think I saw somewhere that using pointers was good (but I can't find it now, so I can't be sure what they were doing)

...
since then the -Ox option has been introduced in NASM, which takes care of "push byte ..." and "add dword [...],byte ..."
I had a look at NASMs -Ox option (http://www.nasm.us/doc/nasmdoc2.html#section-2.1.22), but I don't see how it relates to PUSH with BYTE, DWORD, etc...
Was it just a problem with older versions of NASM that has since been fixed?

Re: Interrupt Error Code and the Stack

Posted: Mon Aug 22, 2011 5:01 am
by mark3094
berkus wrote:Which problems exactly?
I did find that when I was pushing larger numbers for higher interrupts (eg, > 128), NASM didn't like using BYTE.
Not surprising really. Not really a big problem though.

Re: Interrupt Error Code and the Stack

Posted: Mon Aug 22, 2011 5:25 am
by mark3094
I have another question...

I have tried to fill the IDT with empty ISRs, the same as shown earlier in this thread.

I can add in the 31 descriptors, and then use inline assembly to initiate one of the interrupts, say int 31.
The interrupt handler prints '31' to the screen as it should.

If I add a lot more empty ISRs, it will eventually get to a point where it will stop working.
For example, if I add 213 descriptors, then using inline assembly to initiate int 31, nothing will happen.
This is odd, as I'm not even trying to use interrupt 213, but it's still causing problems.

Could it be a problem where the table is too big or something? If I miss a few earlier ISR's, interrupt 213 works fine...

Code to add descriptors:

Code: Select all

void idt_entries(uword i, udword base, uword selector, ubyte flags) {
	idt[i].lowoffset = base & 0xFFFF;
	idt[i].selector = selector;
	idt[i].reserved = 0;
	idt[i].flags = flags;
	idt[i].highoffset = (base >> 16) & 0xFFFF;
}
Adding descriptors to the IDT:

Code: Select all

	idtr.limit = (sizeof((udword)idt) * IDTDESCRIPTORS) - 1;
	idtr.base = (udword)&idt;

	idt_entries (0, (udword)isr0, 0x08, 0x8e);
	idt_entries (1, (udword)isr1, 0x08, 0x8e);
	idt_entries (2, (udword)isr2, 0x08, 0x8e);
        ...
Sample ISR:

Code: Select all

_isr213:
	CLI
	PUSH	BYTE 0
	PUSH	DWORD 213
	JMP	isrhandler

isrhandler:
	MOV	EAX, _isr
	CALL	EAX
	ADD	ESP, 8
	IRET
    

Re: Interrupt Error Code and the Stack

Posted: Mon Aug 22, 2011 6:38 am
by Combuster
Your ISRs don't preserve registers.

Re: Interrupt Error Code and the Stack

Posted: Mon Aug 22, 2011 11:24 am
by Nessphoro
NASM 2.09, if you pass a a value larger than 128 to "push byte" it will overflow the signed boundary - and it becomes 0xFFFFFF7F- when viewing the interrupt number in the ISR.

Re: Interrupt Error Code and the Stack

Posted: Mon Aug 22, 2011 1:55 pm
by Gigasoft
Just use the damn -Ox option, and save yourself the trouble of typing "byte" or "dword" every time.

Or better yet, get a decent assembler, such as JWASM.

Re: Interrupt Error Code and the Stack

Posted: Mon Aug 22, 2011 3:28 pm
by mark3094
Combuster wrote:Your ISRs don't preserve registers.
would a simple pusha and popa be suitable to preserve registers?

eg:

Code: Select all

isrhandler:
   PUSHA
   MOV   EAX, _isr
   CALL   EAX
   POPA
   ADD   ESP, 8
   IRET

Re: Interrupt Error Code and the Stack

Posted: Mon Aug 22, 2011 3:37 pm
by Nessphoro
test.asm:4: warning: signed byte value exceeds bounds
test.asm:5: warning: signed byte value exceeds bounds

Yes, but now if you printf that value on interrupt - you'll get a very funny value.

Re: Interrupt Error Code and the Stack

Posted: Mon Aug 22, 2011 5:10 pm
by Owen
I believe it is sign extended - so it should be correct as long as you only read the lower byte (and the assembler is sane)

Re: Interrupt Error Code and the Stack

Posted: Mon Aug 22, 2011 11:45 pm
by Nessphoro
Just test it via real code guys.

You'll see.

Since the value is over the sign limit it will be negative, so the unsigned int (byte IS extended to dword) for that will have 0xFFFFFF80 stored in it (if 0x80 was pushed), which proves that 0x80!=0xFFFFFF80, which in fact will trash your ISR at the part where you chose what to do with that interrupt (IRQ,Syscall,etc)