Thread overview
Referencing class members with the inline assembler and other assembler questions
Jun 18, 2005
Uwe Salomon
Jun 24, 2005
Walter
Jun 24, 2005
Uwe Salomon
June 18, 2005
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
June 24, 2005
"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.



June 24, 2005
>> 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.


#### code ####
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]
}
#### end code ####


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:

#### code ####
fld double ptr Sphere.pos[ECX];
// and for sphere[0].pos[2]:
fsub double ptr Sphere.pos+16[EBX];
#### end code ####

With these statements i get the errors at the beginning of the email.

Thanks for the prompt answer!
uwe