Page 3 of 3

Re: segmentation fault

Posted: Tue Jan 27, 2009 5:44 pm
by yemista
stlw wrote:
yemista wrote:In that case, how do you load the idtr with a calculated linear offset that includes the base through ds? how can I make idtr 0x00100088 if I cant do it by lidt [ds:idt]?
Open Intel manual and read about LIDT instruction:

Loads the values in the source operand into the interrupt descriptor table register (IDTR). The source operand specifies a 6-byte memory location that contains the base address (a linear address) and the limit (size of table in bytes) of the interrupt descriptor table (IDT).

pseudocode is trivial:
IDTR(Limit) ← SRC[0:15];
IDTR(Base) ← SRC[16:47];

and you decide what do you put in your memory location addressed by [ds:idt].
put there correct linear address as manual requires :)

Stanislav
yea obviously, but the question is why isnt this code generating the correct address?

Code: Select all

_idt:
   %rep  51 
      make_idt_entry         ;(32+16+3) ; exceptions+interrupts+syscall
   %endrep
idt_end:

   
idtp:    dw    idt_end - _idt -1       ; IDT limit
   dd    _idt             ; address of IDT

lidt [idtp]
I also tried this with the same results

Code: Select all

lidt [ds:idtp]

Re: segmentation fault

Posted: Tue Jan 27, 2009 6:08 pm
by Combuster
Because you told it to. You told the assembler to assume the file is executed at virtual location 0.
Then you expect that it will magically see the IDT and fill in the correct linear address (which is what the IDTR is expected to contain).

Go back for once and check what numbers are wrong, and what needs to be done to fix those. If we have to go and spoon feed you all your bugfixes then it will get very annoying for us.

Re: segmentation fault

Posted: Tue Jan 27, 2009 8:36 pm
by yemista
Yea but shouldnt ds do that for me?

Re: segmentation fault

Posted: Tue Jan 27, 2009 10:00 pm
by Firestryke31
No. The IDTR does not use DS. It's already been said twice I believe (at least once by me). Only the LIDT instruction uses DS, and that's for the pointer to the structure that gets loaded to the IDTR.

Re: segmentation fault

Posted: Wed Jan 28, 2009 7:24 am
by yemista
Look, Im not expecting people to fix everyone of my bugs and there is still something I dont get here. Here is the problem as I see it. I understand idtr does nto use ds to reference memory, and just contains a linear address. It only uses ds during the lidt instruction. So if idt is at 0x88, and ds is 0x00100000, lidt [idt] should effectivley load 0x00100088 into the idtr? Is that correct or am I mistaken in thinking that? However, for some reason, after the lidt instruction, idtr reads 0x00000088. I dont believe anything is wrong with my ds, because when I change it other memory reads fail. idt is located at offset 0x88, and everything seems to be right except for what is actually loaded into idtr. I double checked everything. I also looked at the intel instruction set and i dont think im using the instruction wrong.

Re: segmentation fault

Posted: Wed Jan 28, 2009 8:48 am
by Brendan
Hi,
yemista wrote:Look, Im not expecting people to fix everyone of my bugs and there is still something I dont get here. Here is the problem as I see it. I understand idtr does nto use ds to reference memory, and just contains a linear address. It only uses ds during the lidt instruction. So if idt is at 0x88, and ds is 0x00100000, lidt [idt] should effectivley load 0x00100088 into the idtr? Is that correct or am I mistaken in thinking that?
That's correct (unless you're using a segment override prefix, like "lidt [gs:foo]").
yemista wrote:However, for some reason, after the lidt instruction, idtr reads 0x00000088.
The LIDT instruction loads the base and the limit of the IDT from the address you said. So, if you do:

Code: Select all

    lidt [foo]

foo:
    dd 0x12345678
    dw 256*8 - 1
Then, the IDTR will contain 0x12345678, the CPU will expect to find an IDT (and IDT entries) at 0x12345678, and the IDT limit will be enough for 256 IDT entries.

However, if you do:

Code: Select all

    lidt [foo]

foo:
    dd my_IDT
    dw 256*8 - 1
Then the IDTR will contain whatever the assembler thought "my_IDT" is. If your code is using DS = 0x00100000 and the assembler thinks that "my_IDT" is equal to 0x00000123, then the IDT might be at 0x00100123 but the IDTR will only be 0x00000123. To fix that you'd need to do something like:

Code: Select all

    lidt [foo]

foo:
    dd my_IDT + <whatever_the_code_segment's_base_address_is>
    dw 256*8 - 1

Cheers,

Brendan