Board index » delphi » Pointer to Object Variable

Pointer to Object Variable


2005-10-12 02:19:31 AM
delphi26
Hello,
We are currently writing some high performance code in ASM and we run into
the following problem.
We initially had a global variable gloptr which stores a pointer.
However since we want to include our ASM code into an object we had to
replace our global pointer with a pointer (locptr) owned by the object.
When the form is created we allocate a single byte and store the pointer to
the byte into gloptr and locptr (FormCreate).
If we click Button1 then the first block of assembly code runs fine: the
address of the global pointer is stored in eax and then we store 100 at this
address.
The next section tries to do the same with the object pointer (locptr) and
this time it fails. I do have replacement code that does work (see
Button2Click event) but:
1) I am wondering whether the code in Button1Click event can be re-written so
that it does work with an object variable.
B.t.w. I noticed a difference between "mov eax, locptr" and "mov eax,
self.locptr".
2) I am wondering whether the code in Button2Click event can be improved.
Thanks a lot,
Alain
unit uMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TfmTest = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
locptr: PByte;
end;
var
fmTest: TfmTest;
gloptr: PByte;
implementation
{$R *.dfm}
procedure TfmTest.FormCreate(Sender: TObject);
begin
gloptr:= New(PByte);
locptr:= gloptr;
end;
procedure TfmTest.Button1Click(Sender: TObject);
begin
asm
mov eax, gloptr;
mov byte [eax], 100;
end;
ShowMessage(IntToStr(gloptr^));
asm
mov eax, locptr;
mov byte [eax], 200;
end;
ShowMessage(IntToStr(locptr^));
end;
procedure TfmTest.Button2Click(Sender: TObject);
begin
asm
mov eax, self;
add eax, locptr;
mov eax, [eax];
mov byte [eax], 250;
end;
ShowMessage(IntToStr(locptr^));
end;
end.
 
 

Re:Pointer to Object Variable

Hi Alain,
Quote
2) I am wondering whether the code in Button2Click event can be improved.
The first parameter in an object method is always an implied "self"
(normally that would be in eax). I'd suggest:
procedure TfmTest.Button2Click(Sender: TObject);
asm
mov eax, TfmTest([eax]).locptr
mov byte ptr [eax], 250
end;
This is not the kind of code that will gain much from being in assembler
though. I reckon the following code will generate similar if not the exact
same machine code:
procedure TfmTest.Button2Click(Sender: TObject);
asm
locptr^ := 250;
end;
Regards,
Pierre
 

Re:Pointer to Object Variable

Pierre,
Apparently this doesn't work in Delphi 7.0.
However, it does work when using the ebx register
asm
mov eax, TfmTest([ebx]).locptr
mov byte ptr [ebx], 250
end;
or even
asm
mov eax, ebx.locptr
mov byte ptr [eax], 250
end;
<<The first parameter in an object method is always an implied "self"
(normally that would be in eax).>>
Apparently this is not always the case. Is this documented somewhere? I
assume that for bookkeeping and performance reasons a reference to Self must
always be loaded in a register.
The question is in which one and does it change over compiler versions?
Isn't there a notation that does tell the compiler to use the register that
points to Self no matter in which register it is loaded?
<<This is not the kind of code that will gain much from being in assembler
though.>>
I agree but this is just a demo to demonstrate the coding problem I was
facing. The actual code is much more complex and does benefit from the
assembler code.
Regards,
Alain
 

Re:Pointer to Object Variable

I just tried to implement the code from my previous post in my development
project and it sometimes worked and it sometimes didn't.
I have tried to find an explanation and I think it makes sense and it also
explains why the reference to Self was loaded in eax in Pierre's example and
in ebx in my example.
Let me start with saying that Pierre is right and the reference to Self is
in the eax register.
However depending on what you are doing the compiler might add code that
resets the eax register at the time that your assembler code is called.
Put a breakpoint at the begin statement of the Button2Click event and check
the code. you will notice that the content of eax is moved to ebx and eax is
reset to 0.
Put a breakpoint at the begin statement of the Button3Click event and check
the code. you will notice that the content of eax is not modified and can be
used.
The Button4Click is just used to check whether Button3Click works as
expected (I know you can also use the debug (CPU) windows)
procedure TfmTest.Button2Click(Sender: TObject);
begin
asm
mov eax, ebx.locptr
mov byte ptr [eax], 250
end;
ShowMessage(IntToStr(locptr^));
end;
procedure TfmTest.Button3Click(Sender: TObject);
begin
asm
mov eax, eax.locptr
mov byte ptr [eax], 234
end;
end;
procedure TfmTest.Button4Click(Sender: TObject);
begin
ShowMessage(IntToStr(locptr^));
end;
Whether the eax register contains the reference to Self fully depends on
whether the ASM code is followed by Delphi code.
This means that I am still seeking a way of writing my code so that it always
works.
Regards,
Alain
"Alain Sienaert" <XXXX@XXXXX.COM>writes
Quote
Pierre,

Apparently this doesn't work in Delphi 7.0.

However, it does work when using the ebx register

asm
mov eax, TfmTest([ebx]).locptr
mov byte ptr [ebx], 250
end;

or even

asm
mov eax, ebx.locptr
mov byte ptr [eax], 250
end;

<<The first parameter in an object method is always an implied "self"
(normally that would be in eax).>>
Apparently this is not always the case. Is this documented somewhere? I
assume that for bookkeeping and performance reasons a reference to Self
must always be loaded in a register.
The question is in which one and does it change over compiler versions?
Isn't there a notation that does tell the compiler to use the register
that points to Self no matter in which register it is loaded?

<<This is not the kind of code that will gain much from being in assembler
though.>>
I agree but this is just a demo to demonstrate the coding problem I was
facing. The actual code is much more complex and does benefit from the
assembler code.

Regards,
Alain



 

Re:Pointer to Object Variable

I'm not an assembly god, so take this for what its worth: But if it depends
upon the following or prefixing of Delphi code then wouldn't it make sense
that if you placed these methods into a seperate method(s) that only
contained assembly and called these methods from the root methods that you
wouldn't have to worry about this part of the problem?
Jeremy
 

Re:Pointer to Object Variable

Quote
procedure TfmTest.Button2Click(Sender: TObject);
begin
asm
mov eax, ebx.locptr
mov byte ptr [eax], 250
end;

ShowMessage(IntToStr(locptr^));
end;


procedure TfmTest.Button3Click(Sender: TObject);
begin
asm
mov eax, eax.locptr
mov byte ptr [eax], 234
end;
end;
There is no 'begin' in assembler method(procedure or function). The above are not an assembler methods. They are regular methods with assembler blocks in them. As such you cannot expect the registers to have any specific values upon entry of 'asm' block.
Les.
 

Re:Pointer to Object Variable

Hi Alain,
Quote
Apparently this doesn't work in Delphi 7.0.
As Les pointer out earlier, you're not comparing apples to apples. What I
sent you was a BASM function, and what you're comparing it to is an ASM
block inside a normal function.
Quote
I agree but this is just a demo to demonstrate the coding problem I was
facing. The actual code is much more complex and does benefit from the
assembler code.
I would suggest that you tell us exactly what you want to do, perhaps even
post the Pascal code. That way we will be able to help you better.
Regards,
Pierre