digitalmars.D - Referencing class members with the inline assembler and other assembler questions
- Uwe Salomon (49/49) Jun 17 2005 Hi,
- Walter (8/56) Jun 24 2005 It's hard to see why you're getting the error, as the example is incompl...
- Uwe Salomon (63/72) Jun 24 2005 #### code ####
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
"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
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! uwesphere.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.
Jun 24 2005