Search code examples
delphiassemblylazarusfreepascalcalling-convention

x64 asm assign value to a by ref parameter works in Delphi, but not Lazarus Free Pascal


In the simplified code below, Len is not being assigned.

function Test64(const Val: Int64; var Len: Integer): Integer;
begin
asm
  mov           [Len], $1
end;
end;

I'm compiling in 64 bit mode.

This works in Delphi (32 bit), though. How do I get it to work in Lazarus?


Solution

  • I always prefer to be explicit about the registers used to pass parameters when writing asm. It makes it much easier to spot register misuse.

    So I would write it like this:

    function Test64(const Val: Int64; var Len: Integer): Integer;
    asm
      mov dword ptr [rdx], $1
    end;
    

    I suspect that you are actually compiling for x86 because the Delphi x64 compiler does not support mixing Pascal and asm as you do in the question. So, as I understand things, the code in the question does not compile under the Delphi x64 compiler.

    You can see that in my code above I am not mixing Pascal and asm. This is a pure asm function. My advice is always to code this way, even on x86. Doing so will allow you to be sure that the compiler does not interfere with your stack and register usage.

    In x86 the code would be:

    function Test64(const Val: Int64; var Len: Integer): Integer;
    asm
      mov dword ptr [edx], $1
    end;
    

    On Windows x64 Microsoft define the ABI and there is only one calling convention. It is documented here: https://msdn.microsoft.com/en-us/library/zthk2dkh.aspx

    The x64 ABI for non Microsoft platforms (the System V x64 ABI) is different. I've assumed you target Windows.

    The Delphi x86 ABI is described here: http://docwiki.embarcadero.com/RADStudio/en/Program_Control