www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Get memory address of a function?

reply Braden MacDonald <bradenm_k shaw.ca> writes:
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 25 2004
parent reply "Walter" <newshound digitalmars.com> writes:
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 _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 25 2004
next sibling parent reply David L. Davis <David_member pathlink.com> writes:
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 _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


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
parent reply David L. Davis <David_member pathlink.com> writes:
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 _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 26 2004
parent Braden MacDonald <bradenm_k shaw.ca> writes:
Post2: Braden, it looks like I may have misread your problem...sorry. To set

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 26 2004
prev sibling parent reply Braden MacDonald <bradenm_k shaw.ca> writes:
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

the omitted code. Try

 
"Braden MacDonald" <bradenm_k shaw.ca>

news:c91951$i1s$1 digitaldaemon.com... 
 Hi Everyone, 


 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 _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
next sibling parent reply Andy Friesen <andy ikagames.com> writes:
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 26 2004
parent Braden MacDonald <bradenm_k shaw.ca> writes:
In article <c93gig$qv9$1 digitaldaemon.com>, Andy Friesen says... 
You'll have

four. (four for a

address of the method)

still isn't working, though - see my other email)
May 27 2004
prev sibling parent "Walter" <newshound digitalmars.com> writes:
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

 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