FASM - 将字符串传递给Delphi DLL

Jos*_*ine 2 delphi dll messagebox dllimport fasm

我在Delphi XE2中使用以下代码编写了一个DLL:

procedure xMain(MSG:String);export;
begin
  MessageBox(0,PWideChar(MSG),'Title',0);
end;

exports xMain;
Run Code Online (Sandbox Code Playgroud)

现在,我在FASM应用程序中导入此函数,如下所示:

library  dllfile, "testdll.dll"

import   dllfile,\
         xMain,   "xMain"
Run Code Online (Sandbox Code Playgroud)

利用就是如此:

section ".data" data readable writeable

szMSG     db "Message from FASM application!",0

section ".code" code readable executable

invoke    xMain,szMSG
Run Code Online (Sandbox Code Playgroud)

但是生成的消息框会出现扭曲的字符,如下所示:

在此输入图像描述

这是函数调用的确切结果.

我该如何解决这个问题?

Dav*_*nan 6

您的输出是将ANSI文本发送到期望UTF-16编码文本的函数时发生的情况.从中我得出结论,您的FASM代码正在向DLL发送ANSI有效负载.并且DLL在Unicode识别Delphi中编译,其string手段UnicodeString,Char手段WideChar等等.

你需要让双方匹配.例如,通过更改Delphi代码:

procedure xMain(Msg: PAnsiChar); stdcall;
begin
  MessageBoxA(0, Msg, 'Title', 0);
end;
Run Code Online (Sandbox Code Playgroud)

其他一些注意事项:

  1. 您不需要export在函数声明的最后.它被现代Delphi编译器忽略了.
  2. 不要跨模块边界使用Delphi的托管字符串.在FASM端的任何情况下,您都声明该参数是一个以null结尾的指向ANSI编码字符数组的指针.那就是PAnsiChar.
  3. 您的代码使用Delphi register调用约定.很难相信FASM会使用它.我期待stdcall和Sertac的答案支持这一点


Ser*_*yuz 6

以下是两个工作示例(使用Windows的FASM 1.70.03):

安西版,
DLL:

library testdll;

uses
  windows;

procedure xMain(MSG: PAnsiChar); export; stdcall;
begin
  MessageBoxA(0, PAnsiChar(MSG), 'Title', 0);
end;

exports xMain;

begin
end.
Run Code Online (Sandbox Code Playgroud)

可执行程序:

format PE CONSOLE 4.0
entry start

include 'win32a.inc'

section '.code' code readable executable
  start:
    invoke xMain, szMSG
    invoke ExitProcess, 0

section '.data' data readable writeable
    szMSG db 'Message from FASM application!', 0

section '.idata' import data readable writeable
  library kernel32, 'kernel32.dll',\
          dllfile, 'testdll.dll'

  include 'api\kernel32.inc'

  import dllfile,\
         xMain, 'xMain'
Run Code Online (Sandbox Code Playgroud)


Unicode版本,
DLL:

library testdll;

uses
  windows;

procedure xMain(MSG: PChar); export; stdcall;
begin
  MessageBox(0, PChar(MSG), 'Title', 0);
end;

exports xMain;

begin
end.
Run Code Online (Sandbox Code Playgroud)

可执行程序:

format PE CONSOLE 4.0
entry start

include 'win32w.inc'

section '.code' code readable executable
  start:
    invoke xMain, szMSG
    invoke ExitProcess, 0

section '.data' data readable writeable
    szMSG du 'Message from FASM application!', 0

section '.idata' import data readable writeable
  library kernel32, 'kernel32.dll',\
          dllfile, 'testdll.dll'

  include 'api\kernel32.inc'

  import dllfile,\
         xMain, 'xMain'
Run Code Online (Sandbox Code Playgroud)