invalid opcode

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Tyler Southwick

invalid opcode

Post by Tyler Southwick »

hi
i'm a newbie os programmer. i've mostly just copied and pasted code, but i think that i got a working gdt and idt. at least int0 works (divide by zero). but, when i try to add an interrupt for the timer, but i get an invalid opcode message (from my idt). i know that the timer isr is being called becuase i have it print a character to the screen each time its called, and the character is being printed. i don't know why i'm getting an invalid opcode message. please help
Carnac

Re:invalid opcode

Post by Carnac »

What does the code of your interrupt handler look like?
tyler s

Re:invalid opcode

Post by tyler s »

this is the isr handler:

Code: Select all

[extern _timer_isr]
[global _irq0]
_irq0:
     pusha
     push ds
     push es
     push fs
     push gs
     mov eax,0x10    ; Data segment
     mov ds,eax
     mov es,eax
     cld
     call _timer_isr    ; 
     pop gs
     pop fs
     pop es
     pop ds
     popa
     iret
and it calls timer_isr() from a c file:

Code: Select all

void timer_isr()
{

   kprintf("d");

   outportb(0x20, 0x20);

   outportb(0xA0, 0x20);

}
i have it print a 'd' each time the isr is called to let me know if its being called. i then enable the timer irq with:

Code: Select all

outportb(0x21, 0x2);
if i enable the irq, the 'd' is printed, but i also get an invalid opcode message. if it is never enabled, nothing happens.
slacker

Re:invalid opcode

Post by slacker »

i used to get an invalid opcode with my isr--first of all make sure you push/pop 32BIT registers and i also got the exception when i pushed/popped fs/gs registers or some reason
Carnac

Re:invalid opcode

Post by Carnac »

Well I'm not sure how this line assembles:

mov ds, eax

The assembler should throw a big tantrum about that, as ds is a 16bit register, and eax is a 32bit register.

Make sure that your stack isn't being clobbered and blowing up the return address on the stack.
Tim

Re:invalid opcode

Post by Tim »

No, that's fine. It has the same effect as MOV DS, AX but it saves one prefix byte.
Carnac

Re:invalid opcode

Post by Carnac »

It must be some hacky NASM/MASM/whatever throwback then, coz opcode prefixes should have no effect on a segment register load. ;)
Carnac

Re:invalid opcode

Post by Carnac »

In fact, if the assembler was putting in opcode prefixes before a 'mov ds, ax', I'd probably be trading that assembler in for a better model. ;) I'd definitely be trading it in if

(a) It was putting in opcode prefixes before the segment load
(b) If it didn't throw up an error when trying to load a 32bit register into a 16bit segment register
Tim

Re:invalid opcode

Post by Tim »

In 32-bit code, an O16 prefix is required before any instruction that uses a 16-bit register. This includes MOV DS, AX. No prefix is required before MOV DS, EAX because EAX is a 32-bit register, and it's valid to assign a 32-bit register to a segment register (only the bottom 16 bits are used).
Carnac

Re:invalid opcode

Post by Carnac »

I think the difference between:

mov ds, ax

and

mov ds, eax

Is simply the fact that the assembler has looked at the 'eax' and just assumed that the programmer meant 'ax', without throwing up a warning or error. If you assembled both of those lines of code in an assembler that actually parsed it, it would very most definitely generate exactly the same code. I very much doubt it would put in a prefix.

Most assemblers should really throw a tantrum about a mov ds, eax instruction.
Tim

Re:invalid opcode

Post by Tim »

Intel Volume 2 is the authority on this. According to the section on MOV (and I wish I could copy and paste this, but Craprobat Reader won't let me):

-- No O16 prefix is necessary in 32-bit mode
-- Some assemblers insert it anyway if you write "MOV DS, AX"
-- CPU treats this instruction as if it had no prefix, but there may be one clock overhead to decode the prefix

NASM apparently assembles "MOV DS, AX" and "MOV DS, EAX" the same way, without any prefix, although you can add an O16 manually if you want. I don't have MASM installed currently so I can't easily check that.
Curufir

Re:invalid opcode

Post by Curufir »

Just as another avenue of investigation:

Let's say you switch to protected mode but fail to load FS and GS with decent selectors. Now you hit the interrupt and the value of FS/GS get pushed fine because it's just a value, but the pop is taking those pushed values and treating them as selectors. Unless they were initialised to something (Even if it's the null selector) then they're unlikely to contain a good reference into the GDT. So perhaps it's a problem with selector loading and the error is just not explaining what's going on clearly.

Just speculating of course, I've never had the problem, but then again I set everything to known values after a switch to pmode.
Carnac

Re:invalid opcode

Post by Carnac »

You would assume that you'd get a GP fault (which, he possibly is, if his GP fault handler is screwy/not initialised properly) if you tried loading up an invalid FS/GS selector due to the POP FS/POP GS.

What does the GP Fault handler look like, and is its vector initialised correctly?
Post Reply