Page 1 of 1

Inline ASM problem

Posted: Thu Aug 26, 2004 11:39 pm
by Neo
I've been converting most of my early (N)ASM code into C wherever possible and have a problem in the code reloading the IDTR, my knowledge of inline ASM is fairly limited (sucks actually :-) ). Anyway heres the C code I wrote

Code: Select all

 IDTR_s IDTR;
void reloadIDTR()
{
  IDTR.limit= 256*(sizeof(IDT_s))-1;
  IDTR.base= IDT_entry; // array of IDT_s entries

  __asm__ __volatile__ ("LIDT (%0)": :"p"(&IDTR));
}
I also tried replacing the asm statement with a pointer as in

Code: Select all

  IDTR_s *idtrptr= &IDTR;
  __asm__ __volatile__ ("LIDT (%0)": :"p"(idtrptr));
which also gives an error. The code compiles fine, but LD says "undefined reference to $IDTR" in both cases.
An 'objdump' of the idt object file gives this

Code: Select all

000000f0 <reloadIDTR>:
  f0:   55                      push   %ebp
  f1:   89 e5                   mov    %esp,%ebp
  f3:   83 ec 0c                sub    $0xc,%esp
  f6:   66 c7 05 10 00 00 00    movw   $0x7ff,0x10
  fd:   ff 07 
  ff:   c7 05 12 00 00 00 00    movl   $0x800,0x12
 106:   08 00 00 
 109:   0f 01 1d 00 00 00 00    lidtl  0x0
 110:   68 00 08 00 00          push   $0x800
 115:   68 ff 07 00 00          push   $0x7ff
 11a:   68 40 00 00 00          push   $0x40
 11f:   e8 dc fe ff ff          call   0 <loadInt>
 124:   89 ec                   mov    %ebp,%esp
 126:   5d                      pop    %ebp
 127:   c3                      ret    
 128:   90                      nop
I dont really know why the "p" is used in the output constraint. I tried using "m" and got the code linked but it tripple faults the CPU when an INT is generated after reloading the IDTR.
Can anybody tell me what is wrong here? I've been sitting all night with this thing.

Re:Inline ASM problem

Posted: Fri Aug 27, 2004 12:24 am
by Candy
try using "r" for it.

I think that P defines a pointer for the content, IE, passing &&IDTR. M puts it in memory and passes a pointer to that, so it's similar to P in giving &&IDTR. Putting the address in a register passes &IDTR, which you then correctly dereference with the (%0) to give IDTR, for the idtr.

On the other hand, you might want to type the lidt with lower case characters. AT&T assembly is case sensitive, afaik.

Re:Inline ASM problem

Posted: Fri Aug 27, 2004 1:08 am
by Solar
Candy wrote: On the other hand, you might want to type the lidt with lower case characters. AT&T assembly is case sensitive, afaik.
Affirmative.

Re:Inline ASM problem

Posted: Fri Aug 27, 2004 4:40 am
by IRBMe
I don't know if it'll be of any help, Neo, but the code I use is:

Code: Select all

IDT_REGISTER *pIDTR = &m_interruptRegister;
__asm__ __volatile__ ("lidt %0" : "=m" (pIDTR));
and it seems to work ok.

Re:Inline ASM problem

Posted: Fri Aug 27, 2004 6:58 am
by Pype.Clicker
just to add my grain of salt, make sure sizeof(IDTR) is 6 bytes... many GCC configurations will not like the word+dword packing of Intel and will read

Code: Select all

struct IDTR {
    word limit;
    dword base;
}
as

Code: Select all

struct IDTR {
     word limit;
     word _padding; //make sure the next DWORD is aligned
     dword base;
}
...

Re:Inline ASM problem

Posted: Fri Aug 27, 2004 7:23 am
by Solar
Hint: Use -fpack-struct to have GCC pack all structures. That's usually what you want in kernel code anyway.

Re:Inline ASM problem

Posted: Fri Aug 27, 2004 7:40 am
by IRBMe
Good hint, Solar. I didn't know about that, so my structs look like:

Code: Select all

typedef struct
{
   unsigned short   Limit;
   INTERRUPT_GATE  *Base;
} 
__attribute__ ((packed)) IDT_REGISTER;
*takes note of that switch*

Re:Inline ASM problem

Posted: Fri Aug 27, 2004 5:41 pm
by Neo
I am using the 'packed' attribute.
The "=m" did not work, but the "r" did the thing nicely and then my handler was called (thanks candy), but it triple faulted after printing its message. I must try looking at that now, right now all it does is print a message in an ASM wrapper, i cant see whats wrong there,anyway let me try. :P

Re:Inline ASM problem

Posted: Sat Aug 28, 2004 5:57 am
by Pype.Clicker
probably some mismatching push/pops ... also make sure you did remove any "error code" the CPU could have pushed before you attemp to return from an exception...

Re:Inline ASM problem

Posted: Sat Aug 28, 2004 10:23 pm
by Neo
Yes Pype, found the buggy code, actually i thought
PUSH AX in a 32 bit code segment also decremented the ESP by 4 bytes, the same as PUSH EAX but was wrong.