Click here to Skip to main content
Click here to Skip to main content

Finally, 64-Bit Delphi is here and with 64-Bit BASM!

, 3 Oct 2011 CPOL
Rate this:
Please Sign up or sign in to vote.
Using Borland Assembler Language in 32-bit and 64-bit Delphi programs.

Introduction

Delphi was once a great and popular Pascal programming language, but after years of bad management and false promises, developers just abandoned it in favor of more fashionable languages like C#.

One of the main criticisms was the lack of support for 64-bit computing. But now, things have really changed under the management of Embarcadero (which took over the company from CodeGear, which had taken it from Inprise, which in turn had done the same from Borland).

I have been testing the new Delphi XE2 for a couple of days. One thing I have no doubts right now is that Embarcadero was able to gather a fantastic team of coders and come up with a great product. There are really amazing features, and I am pretty sure most of them are not being properly advertised to developers.

Well, marketing and documentation are important and coders were never great guys for that, so I hope Embarcadero can assemble other teams of guys/girls to produce decent documentation and to show the developers how great the product is. This is probably more important than doing marketing near the board of directors of companies.

During my tour with Delphi XE2, I was particularly surprised with the 64-bit BASM facility. Well, I started as an Assembly Language nerd in my old days and still can not resist to experiment a bit when the opportunity arises.

With BASM, we can mix Assembly Language with Delphi code in the same source file (even inline in the same function for 32-bit BASM). Microsoft Visual Studio allows as well the mix of C/C++ with Assembly Language but only in 32-bit code. So, Embarcadero won here because it supports both 32-bit and 64-bit. Really amazing.

I know there are limitations in BASM, there are also many limitations with the Microsoft inline Assembly Language and, of course, for very complex Assembly Language parts, it is still better to compile in a separate file and link all together.

Using the code

I have prepared a small demonstration program were BASM is called from Delphi. It will compile both in 32-bit and 64-bit. The program is simple although more advanced than most samples you can find in the internet. The program shows as well how you can return a large amount of information from the call, in this case an array.

Basm1.jpg

One thing you will notice immediately by looking at the code below is that 32-bit Assembly Language is totally different from 64-bit Assembly Language. So, if you want to port 32-bit routines to 64-bit, forget about that and start new ones from scratch.

Basm2.jpg

Here is the source code (you can download the full source code for the demo program from the provided link):

unit basmTestUnit;

interface

uses
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, 
    Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
    TBasmTest = class(TForm)
    GroupBox1: TGroupBox;
    lblCaption: TLabel;
    edCaption: TEdit;
    lblInput: TLabel;
    edInput: TEdit;
    btGo: TButton;

procedure btGoClick(Sender: TObject);
private

public
    { Public declarations }
end;

var
    BasmTest: TBasmTest;

implementation

{$R *.dfm}

var
    myReturnString : string = 'I am back in Delphi!';
    charCount : integer;

type
    bigarray = array[0..127] of char;


function assemblyTestFunction(myCaption: string; myText : string): bigarray;
{$IFDEF CPUX86}
asm
    // This is the 32-bit case with the default Register (Borland Fastcall) calling convention
    // where the Result is an extra var parameter.
    // Arguments are passed in EAX, EDX and ECX, left to right. So, the Result (i.e, the 
    // return value pointer) will come to the function in ECX.
    push edi
    push esi
    push dword ptr 0
    push dword ptr myCaption
    push dword ptr myText
    push dword ptr 0
    mov edi, ecx; // Save the return pointer to EDI because we need ECX as a counter and 
                  // EDI is the destination pointer in a rep movsw instruction
    call MessageBox
    mov esi, dword ptr myReturnString
    mov ecx, [charCount]
    rep movsw
    pop esi
    pop edi
    ret
end;
{$ELSE}
{$IFDEF CPUX64}
    // This is the 64-bit case
    // General rule: Integer and pointer arguments are passed left to right in RCX, RDX, R8
    // and R9. HOWEVER, when there is a large return value, this is the case, RCX contains
    // a pointer to the return space when the callee is called and all Registers usage are
    // pushed one to the right
    //
asm
    push rsi
    push rdi
    push rbx
    push rbp // Yes, it is a kludge. No need to push rbp, it is just to align the stack.
             // The alternative is 'and rsp,-16'
    sub rsp, 28h

    xor r9, r9
    mov rbx, rcx
    mov rax, rdx
    mov rdx, r8
    mov r8, rax
    xor rcx, rcx
    call MessageBox

    mov rdi, rbx
    mov rsi, qword ptr myReturnString
    mov ecx, [charCount]
    rep movsw
    add rsp, 28h
    pop rbp
    pop rbx
    pop rdi
    pop rsi
    ret
end;
{$ENDIF CPUX64}
{$ENDIF}

procedure TBasmTest.btGoClick(Sender: TObject);
var
    retValue : bigArray;
begin
    fillchar(retValue, sizeof(bigArray),0);
    charCount := length(myReturnString);
    retValue := assemblyTestFunction(edCaption.Text, edInput.Text);
    showMessage(retValue);
end;

end.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Jose A Pascoa
AtelierWeb Software
Portugal Portugal
Jose Pascoa is the owner of AtelierWeb Software (http://www.atelierweb.com) and Open Source Penguindow Valley (http://www.ospv.com). We produce security and network software and mixed utilities since 1999. The first program I published (in a BBS) was a MS-DOS utility, had the size of 21 KB and was done in Assembly Language. Nowadays, my low level languages are more likely to be "C", "C++" and "Delphi" rather than Assembly Language but I still like it. I have nothing against more fashionable languages like C# and technologies like WPF, actually I have played with them and published software with them.
Follow on   Twitter

Comments and Discussions

 
Question$IFDEFs [modified] Pinmemberrvelthuis6-Oct-11 3:57 
AnswerRe: $IFDEFs PinmemberJose A Pascoa6-Oct-11 6:53 
QuestionCompany history is slightly incorrect Pinmemberrvelthuis6-Oct-11 3:49 
FWIW, CodeGear, the developer tools division, was still owned by Borland when Embarcadero bought it, and Borland and Inprise were the same company.
 
The name was (foolishly, IMO) changed from Borland to Inprise a long time ago and then changed back to Borland. Borland started as developer tools company, but in the Inprise days, wanted to concentrate on large business customers. This stayed so after the name change back to Borland, and the developer tools were more or less neglected and only used as cash cow. At the end the developer tools were factored out as a subsidiary company, CodeGear, which was eventually sold to Embarcadero.
 
After Embarcadero bought CodeGear, they put a lot of resources in improving the developer tools, and the current result is RAD Studio XE2. And they are still improving things.
AnswerRe: Company history is slightly incorrect PinmemberJose A Pascoa6-Oct-11 7:03 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141223.1 | Last Updated 3 Oct 2011
Article Copyright 2011 by Jose A Pascoa
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid