#1 2010-08-18 18:58:23

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,231
Website

Help about method parameters and assembler

Amir, by email wrote:

Dear Mr. Bouchez
   
I like to know where the parameters of object-function(s)/procedure(s) [e.g. procedure (...) of object  like TNotifyEvent] are posted when they are called through the event handler.

I am practicing low level coding and I am very new to it, as a practice, I have written an assembley event handler routine for OnKeyPress Event for a decendant of TCustomEdit class, and when I want to access the by-reference parameter called Key via [EDX] or by its name, I encountered an error, an Exception of class EAccessViolation. but when I use a temporary character variable, and assign the Key parameter to it, it works !!!

now I like to know how I can access that parameter (Key) directly, without using a temorary variable.

Here's the routine:  Here I assumed that the address of Key param has been passed to EDX (like native procedures), but this code does not work, but it works correctly, if it is written as a native procedure.

I have checked that the EDX does not contain the address of Key parameter,  so I changed this code by replacing the EDX register with the name of the parameter, but It failed again, and I like to know where the Key param is located ??

// DOES NOT WORK  :((

procedure Tfrmmenumng.edGroupNameKeyPress(Sender: TObject; var Key: Char);
asm
        mov   ecx, dword ptr [edx]
        cmp   cx, '9'
        ja    @@KillChar
         cmp   cx, '0'
        jb    @@CheckForBackSpace
        ret
CheckForBackSpace:
        cmp  cx, 8h         // VK_BACK
         je   @@Quit
@@KillChar:
        xor   ecx, ecx
        mov   dword ptr [edx], ecx
        push  ecx
        call MessageBeep
@@Quit:
end;

//======================================

//  DOES NOT WORK :((

procedure Tfrmmenumng.edGroupNameKeyPress(Sender: TObject; var Key: Char);
asm
        mov   ecx, dword ptr [Key]
         cmp   cx, '9'
         ja    @@KillChar
         cmp   cx, '0'
         jb    @@CheckForBackSpace
         ret
 CheckForBackSpace:
         cmp  cx, 8h         // VK_BACK
         je   @@Quit
 @@KillChar:
         xor   ecx, ecx
         mov   dword ptr [Key], ecx
         push  ecx
         call MessageBeep
 @@Quit:
end;

//======================================


// BUT THIS UGLY WORKS ????

procedure Tfrmmenumng.edGroupNameKeyPress(Sender: TObject; var Key: Char);

var  cTemp: Char;
label CheckForBackSpace, KillChar, Quit;

begin

    cTemp := Key;

    asm
        movzx   ecx, cTemp
        cmp     cx, '9'
        ja      KillChar
        cmp     cx, '0'
        jb      CheckForBackSpace
     end;

    Exit;

    CheckForBackSpace:
    asm
        cmp     cx, 8h         // VK_BACK
        je      Quit
    end;

    KillChar:
    asm
        xor     ecx, ecx
        mov     cTemp, cx
        push    ecx
        call    MessageBeep
     end;

    Key := cTemp;

  Quit:
end;

Thanks in advance.

best regards,

Offline

#2 2010-08-18 18:59:16

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,231
Website

Re: Help about method parameters and assembler

In a method, you have the "self" parameter that is always transmitted in asm as first parameter.

So for:

 procedure Tfrmmenumng.edGroupNameKeyPress(Sender: TObject; var Key: Char);

you have:

eax = self
edx = Sender
ecx = @key

So you'll have to change your asm code to use these registers instead of eax=Sender and edx=@key.

Happy coding!
smile

Offline

#3 2010-08-18 19:02:56

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,231
Website

Re: Help about method parameters and assembler

Here could be the resulting code (compatible with Delphi 7 up to Delphi 2010):

procedure Tfrmmenumng.edGroupNameKeyPress(Sender: TObject; var Key: Char);
asm
{$ifdef UNICODE}
        movzx   eax, word ptr [ecx]
{$else}
        movzx   eax, byte ptr [ecx]
{$endif}
        cmp   eax, '9'
        ja    @@KillChar
         cmp   eax, '0'
        jb    @@CheckForBackSpace
        ret
CheckForBackSpace:
        cmp  eax, 8h         // VK_BACK
         je   @@Quit
@@KillChar:
        xor   eax, eax
        mov   dword ptr [ecx], eax
        push  eax
        call MessageBeep
@@Quit:
end;

But I guess the Delphi compiler is able to code it in a similar manner.
No speed we'll be noticed here, even more because it's an even handler, which rely on both WinApi + VCL, therefore is somewhat CPU consuming!

But that's a nice try to write assembler.

Offline

Board footer

Powered by FluxBB