Inline ASM problem

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
User avatar
Neo
Member
Member
Posts: 842
Joined: Wed Oct 18, 2006 9:01 am

Inline ASM problem

Post 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.
Only Human
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:Inline ASM problem

Post 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.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:Inline ASM problem

Post 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.
Every good solution is obvious once you've found it.
IRBMe

Re:Inline ASM problem

Post 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.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Inline ASM problem

Post 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;
}
...
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:Inline ASM problem

Post by Solar »

Hint: Use -fpack-struct to have GCC pack all structures. That's usually what you want in kernel code anyway.
Every good solution is obvious once you've found it.
IRBMe

Re:Inline ASM problem

Post 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*
User avatar
Neo
Member
Member
Posts: 842
Joined: Wed Oct 18, 2006 9:01 am

Re:Inline ASM problem

Post 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
Only Human
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Inline ASM problem

Post 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...
User avatar
Neo
Member
Member
Posts: 842
Joined: Wed Oct 18, 2006 9:01 am

Re:Inline ASM problem

Post 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.
Only Human
Post Reply