www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Referencing class members with the inline assembler and other assembler questions

reply "Uwe Salomon" <post uwesalomon.de> writes:
Hi,

i am currently writing some calculation stuff that needs to be optimized,  
thus i directly program the FPU. The function to be written in assembler  
belongs to the class SphereConnection:


class SphereConnection
{
   Sphere[2] spheres;

   int func()
   {
     asm
     {
       // Hard work here...
     }
   }
}

class Sphere
{
   double[3] pos;
}


As you can see, the class has 2 pointers to another class Sphere as  
members. In the assembler code i want to access members of Sphere then:


push EBX;
mov EBX, spheres[EAX];
mov ECX, spheres+4[EAX];

fld double ptr Sphere.pos[EBX];
// etc.


That's what i get from DMD for the last assembly line:

sphere.d(114): 'this' is required, but sphere.Sphere is not a base class  
of SphereConnection
sphere.d(114): this for pos needs to be type Sphere not type  
sphere.SphereConnection
sphere.d(114): class sphere.SphereConnection member pos is not accessible
sphere.d(114): bad type/size of operands 'this.pos'

He doesn't believe me that EBX points to class Sphere. :(  Thing is, i  
don't want to hardcode the offset of Sphere.pos because DMD can rearrange  
the members. How do i tell it the compiler "the right way"?

Another question: which registers need to be conserved by assembly  
functions (besides the obvious EBP, ESP)? I have found that EBX is needed  
when compiling with -O, are there others the compiler expects unchanged  
after a D function call? And am i right to assume that "this" is always  
passed in EAX? And how do i access constant values that are needed for the  
FPU:

const double FunnyConstant;
// later...
fld double ptr FunnyConstant;

Or do i simply have to declare them as static variables (it works then, of  
course)?

Thanks a lot!
uwe
Jun 17 2005
parent reply "Walter" <newshound digitalmars.com> writes:
"Uwe Salomon" <post uwesalomon.de> wrote in message
news:op.ssjy38tp6yjbe6 sandmann.maerchenwald.net...
 i am currently writing some calculation stuff that needs to be optimized,
 thus i directly program the FPU. The function to be written in assembler
 belongs to the class SphereConnection:


 class SphereConnection
 {
    Sphere[2] spheres;

    int func()
    {
      asm
      {
        // Hard work here...
      }
    }
 }

 class Sphere
 {
    double[3] pos;
 }


 As you can see, the class has 2 pointers to another class Sphere as
 members. In the assembler code i want to access members of Sphere then:


 push EBX;
 mov EBX, spheres[EAX];
 mov ECX, spheres+4[EAX];

 fld double ptr Sphere.pos[EBX];
 // etc.


 That's what i get from DMD for the last assembly line:

 sphere.d(114): 'this' is required, but sphere.Sphere is not a base class
 of SphereConnection
 sphere.d(114): this for pos needs to be type Sphere not type
 sphere.SphereConnection
 sphere.d(114): class sphere.SphereConnection member pos is not accessible
 sphere.d(114): bad type/size of operands 'this.pos'

 He doesn't believe me that EBX points to class Sphere. :(  Thing is, i
 don't want to hardcode the offset of Sphere.pos because DMD can rearrange
 the members. How do i tell it the compiler "the right way"?
It's hard to see why you're getting the error, as the example is incomplete.
 Another question: which registers need to be conserved by assembly
 functions (besides the obvious EBP, ESP)?
Same as for C/C++: EBX, ESI, EDI. But you don't need to worry about it, the compiler will keep track of which ones are used and save/restore them automatically.
 I have found that EBX is needed
 when compiling with -O, are there others the compiler expects unchanged
 after a D function call? And am i right to assume that "this" is always
 passed in EAX?
Yes.
 And how do i access constant values that are needed for the
 FPU:

 const double FunnyConstant;
 // later...
 fld double ptr FunnyConstant;

 Or do i simply have to declare them as static variables (it works then, of
 course)?
Make them static variables.
Jun 24 2005
parent "Uwe Salomon" <post uwesalomon.de> writes:
 sphere.d(114): 'this' is required, but sphere.Sphere is not a base class
 of SphereConnection
 sphere.d(114): this for pos needs to be type Sphere not type
 sphere.SphereConnection
 sphere.d(114): class sphere.SphereConnection member pos is not  
 accessible
 sphere.d(114): bad type/size of operands 'this.pos'
It's hard to see why you're getting the error, as the example is incomplete.
public class SphereConnection { public: Sphere[2] spheres; int calculate() { asm { naked; // Get the cell pointers. push EBX; mov EDX, EAX; mov EBX, spheres[EAX]; mov ECX, spheres+4[EAX]; // Calculate the distance between the cells. fld double ptr [ECX+0x30]; fsub double ptr [EBX+0x30]; fld double ptr [ECX+0x38]; fsub double ptr [EBX+0x38]; fld double ptr [ECX+0x40]; fsub double ptr [EBX+0x40]; fld ST(2); fmul ST, ST(0); fld ST(2); fmul ST, ST(0); fld ST(2); fmul ST, ST(0); faddp ST(1), ST; faddp ST(1), ST; fsqrt; // More code follows... } } } public class Sphere { public: size_t id; Vector!(SphereConnection) connections; Float mass; // [kg] Float radius; // [m] Float stiffness; // [kg/s²] Vect pos; // [m] Vect vel = [0, 0, 0]; // [m/s] Vect n_pos; // [m] Vect n_vel; // [m/s] } This little code snippet shows the two classes SphereConnection and Sphere. A connection has 2 Sphere-pointers as members. In the function SphereConnection.calculate() i load the two pointers into EBX and ECX (via EAX = this), and want to access their Sphere.pos members. Currently this is hardcoded ("fld double ptr [ECX+0x30];" loads sphere[1].pos[0] into ST0), and i want to write something like that instead: fld double ptr Sphere.pos[ECX]; // and for sphere[0].pos[2]: fsub double ptr Sphere.pos+16[EBX]; With these statements i get the errors at the beginning of the email. Thanks for the prompt answer! uwe
Jun 24 2005