May 26, 2004
Hi Everyone,
 How can I access the memory address of a function? I want the
address for
loading into an Interrupt Descriptor Table.

example :

void
enableInterrupts( ... ) {
 ...
 tables[14].handler=cast(void*)&_interrupt14;
// This generates an error - e2ir: cannot cast from void delegate() to void*
..
}
void _interrupt14() {
 asm {
  pusha; push DS; push ES; push FS; push
GS;
  mov EAX,CR2;
  push EAX;
  call interrupt14;
  pop GS; pop FS; pop ES;
pop DS; popa;
  iret;
 }
}
void interrupt14() {
 // Handler
}


Thanks
a lot!

 Braden


May 26, 2004
What you're doing should work fine. I suspect something else is going on in the omitted code. Try boiling it down to the minimum.

"Braden MacDonald" <bradenm_k@shaw.ca> wrote in message news:c91951$i1s$1@digitaldaemon.com...
> Hi Everyone,
>  How can I access the memory address of a function? I want the
> address for
> loading into an Interrupt Descriptor Table.
>
> example :
>
> void
> enableInterrupts( ... ) {
>  ...
>  tables[14].handler=cast(void*)&_interrupt14;
> // This generates an error - e2ir: cannot cast from void delegate() to
void*
> ..
> }
> void _interrupt14() {
>  asm {
>   pusha; push DS; push ES; push FS; push
> GS;
>   mov EAX,CR2;
>   push EAX;
>   call interrupt14;
>   pop GS; pop FS; pop ES;
> pop DS; popa;
>   iret;
>  }
> }
> void interrupt14() {
>  // Handler
> }
>
>
> Thanks
> a lot!
>
>  Braden
>
>


May 26, 2004
In article <c91cfg$mjj$1@digitaldaemon.com>, Walter says...
>
>What you're doing should work fine. I suspect something else is going on in the omitted code. Try boiling it down to the minimum.
>
>"Braden MacDonald" <bradenm_k@shaw.ca> wrote in message news:c91951$i1s$1@digitaldaemon.com...
>> Hi Everyone,
>>  How can I access the memory address of a function? I want the
>> address for
>> loading into an Interrupt Descriptor Table.
>>
>> example :
>>
>> void
>> enableInterrupts( ... ) {
>>  ...
>>  tables[14].handler=cast(void*)&_interrupt14;
>> // This generates an error - e2ir: cannot cast from void delegate() to
>void*
>> ..
>> }
>> void _interrupt14() {
>>  asm {
>>   pusha; push DS; push ES; push FS; push
>> GS;
>>   mov EAX,CR2;
>>   push EAX;
>>   call interrupt14;
>>   pop GS; pop FS; pop ES;
>> pop DS; popa;
>>   iret;
>>  }
>> }
>> void interrupt14() {
>>  // Handler
>> }
>>
>>
>> Thanks
>> a lot!
>>
>>  Braden
>>
>>
>
>
Braden, I'm looking at the Intel 386 Asm Manual, and it states, "CR2 is used for handling page faults when PG (CR0, Paging, bit 31) is set. The processor stores in CR2 the linear address that triggers the fault." Since I don't see CR0 bit 31 being set in your above code...maybe that's it. ;)


May 26, 2004
In article <c92s45$2ude$1@digitaldaemon.com>, David L. Davis says...
>
>In article <c91cfg$mjj$1@digitaldaemon.com>, Walter says...
>>
>>What you're doing should work fine. I suspect something else is going on in the omitted code. Try boiling it down to the minimum.
>>
>>"Braden MacDonald" <bradenm_k@shaw.ca> wrote in message news:c91951$i1s$1@digitaldaemon.com...
>>> Hi Everyone,
>>>  How can I access the memory address of a function? I want the
>>> address for
>>> loading into an Interrupt Descriptor Table.
>>>
>>> example :
>>>
>>> void
>>> enableInterrupts( ... ) {
>>>  ...
>>>  tables[14].handler=cast(void*)&_interrupt14;
>>> // This generates an error - e2ir: cannot cast from void delegate() to
>>void*
>>> ..
>>> }
>>> void _interrupt14() {
>>>  asm {
>>>   pusha; push DS; push ES; push FS; push
>>> GS;
>>>   mov EAX,CR2;
>>>   push EAX;
>>>   call interrupt14;
>>>   pop GS; pop FS; pop ES;
>>> pop DS; popa;
>>>   iret;
>>>  }
>>> }
>>> void interrupt14() {
>>>  // Handler
>>> }
>>>
>>>
>>> Thanks
>>> a lot!
>>>
>>>  Braden
>>>
>>>
>>
>>

Post1: Braden, I'm looking at the Intel 386 Asm Manual, and it states, "CR2 is used for handling page faults when PG (CR0, Paging, bit 31) is set. The processor stores in CR2 the linear address that triggers the fault." Since I don't see CR0 bit 31 being set in your above code...maybe that's it. ;)

Post2: Braden, it looks like I may have misread your problem...sorry. To set up a pointer to a function in D:

// Creates a void function pointer with void // parameters, this matchs void _interrupt14() void function( ) pt2Function;

// Assigns the function's address to the pointer pt2Function = &_interrupt14;

// Then can call the function thru the point
pt2Function();

Hope I got it right this time?


May 27, 2004
You were right. If both functions were members of the same struct, then it
won't compile. If I make _interrupt14 global, then it compiles fine. Is there
any way around this? I'd rather not have a global function if possible.
___________________________________
struct Something {
 void f1() {
  void*
p2 = cast(void*)&_f2; // Error
  void* p3 = cast(void*)&_f3; // OK
 }
 void
f2() {
  //Something
 }
}

void f3() {
 //Something
}
___________________________________

In article
<c91cfg$mjj$1@digitaldaemon.com>, Walter says...
> 
>What you're doing should
work fine. I suspect something else is going on in
>the omitted code. Try
boiling it down to the minimum.
> 
>"Braden MacDonald" <bradenm_k@shaw.ca>
wrote in message
>news:c91951$i1s$1@digitaldaemon.com...
>> Hi Everyone,
>>
How can I access the memory address of a function? I want the
>> address for
>> loading into an Interrupt Descriptor Table.
>> 
>> example :
>> 
>> void
>> enableInterrupts( ... ) {
>>  ...
>>  tables[14].handler=cast(void*)&_interrupt14;
>> // This generates an error - e2ir: cannot cast from void delegate() to
>void*
>> ..
>> }
>> void _interrupt14() {
>>  asm {
>>   pusha; push DS; push ES; push FS; push GS;
>>   mov EAX,CR2;
>>   push EAX;
>>   call interrupt14;
>>   pop GS; pop FS; pop ES; pop DS; popa;
>>   iret;
>>  }
>> }
>> void interrupt14() {
>>  // Handler
>> }

>> Thanks a lot!
>> 
>>  Braden


May 27, 2004
Braden MacDonald wrote:

> You were right. If both functions were members of the same struct, then it
> won't compile. If I make _interrupt14 global, then it compiles fine. Is there
> any way around this? I'd rather not have a global function if possible.
> ___________________________________ struct Something { 
>  void f1() { 
>   void*
> p2 = cast(void*)&_f2; // Error 
>   void* p3 = cast(void*)&_f3; // OK 
>  } 
>  void
> f2() { 
>   //Something 
>  } } 
>  void f3() { 
>  //Something }

You'll have to make f2 static.  As it stands, &f2 is 8 bytes long, not four. (four for a pointer to the Something instance, four more for the address of the method)

 -- andy
May 27, 2004
>Post2: Braden, it looks like I may have misread your problem...sorry. To set
up
>a pointer to a function in D:
> 
>// Creates a void function pointer with void // parameters, this matchs void _interrupt14() void function( ) pt2Function;
> 
>// Assigns the function's address to the pointer pt2Function = &_interrupt14;
> 
>// Then can call the function thru the point pt2Function();
> 
>Hope I got it right this time?

Thanks, I have it working now (see my reply to Walter).

As you may have guessed, I'm writing an operating system in D. I already have paging set up and working, and I have a kmalloc/free working as well. What I'm trying to do now is set up interrupt handling (especially Page Fault) - which has proved more difficult than it first appeared.

Do you happen to know how to use the "lidt" assembler instruction from D? I thought that it took a pointer to a 6-byte structure, but my code will only compile if I pass it a 64-bit paramater:


/* Pointer to IDT table: */ struct idtPtr { ushort length=256*8-1; //Size of table uint addr; // Actual pointer to first entry }

void enableInterrupts() { IDTEntry[256]* base = cast(IDTEntry[256]*)kmalloc(IDTEntry.size*256); idtPtr p; p.addr = cast(uint)&((*base)[0]); for (int i=0;i<256;i++) { ..  // fill IDT table pointed to by "base" } /* Now, load the table into the CPU register: */ asm { lidt p; } /* Now our interrupt handler should be working. (but it isn't) */ }

/* One Interrupt Descriptor Entry: */ struct IDTEntry { ushort _handlerH;//High 16 bits of handler address ushort _flags=0; ushort _segment; ushort _handlerL; void handler(void* addy) { _handlerH = cast(uint)addy>>16; _handlerL = cast(uint)addy & 0x0000FFFF; } void* handler() { return cast(void*)((_handlerH<<16) | (_handlerL)); } void segment(ushort s) { _segment=s; } void present(bit p) { if (p) {_flags |= 1<<15;} else { _flags &= 0xFFFF ^(1<<15); } } bit present() { return (_flags & (1<<15)) != 0; } void kernel(bit kernel) { if (!kernel) { _flags = _flags | 3<<13; } else { _flags &= 0xFFFF ^ (3<<13); } } bit kernel() { return (_flags & (3<<13)) != 0; } void type(bit interrupt/* opposed to trap*/) { _flags &= (0xFFFF) ^ (15<<8); if (interrupt) { _flags |= 14<<8; } else           { _flags |= 15<<8; } } }

___
This code (extracted from my kernel) doesn't work - because any (or all) of
several things could be wrong, I'm not sure which to change. Any ideas?

Thanks a lot!


May 27, 2004
Make it a static member function, and you can take the address of it just like a global function.

"Braden MacDonald" <bradenm_k@shaw.ca> wrote in message news:c93fh9$pme$1@digitaldaemon.com...
> You were right. If both functions were members of the same struct, then it won't compile. If I make _interrupt14 global, then it compiles fine. Is
there
> any way around this? I'd rather not have a global function if possible.
> ___________________________________
> struct Something {
>  void f1() {
>   void*
> p2 = cast(void*)&_f2; // Error
>   void* p3 = cast(void*)&_f3; // OK
>  }
>  void
> f2() {
>   //Something
>  }
> }
>
> void f3() {
>  //Something
> }


May 27, 2004
In article <c93gig$qv9$1@digitaldaemon.com>, Andy Friesen says...
>You'll have
to make f2 static.  As it stands, &f2 is 8 bytes long, not
>four. (four for a
pointer to the Something instance, four more for the
>address of the method)
Right. Thanks for for the explanation, that part compiles fine now. (My IDT still isn't working, though - see my other email)


Top | Discussion index | About this forum | D home