【问题标题】:(Cross-)Compile 64bit assembly on windows on clang (from linux)(交叉)在clang的windows上编译64位程序集(来自linux)
【发布时间】:2021-11-30 15:17:37
【问题描述】:

我正在用 C 和汇编语言编写一个小型库。我几乎完成了linux版本。我用-static -nostdlib 构建,让windows 构建linux 二进制文件很简单。在 linux 上,我使用程序集为 main 获取 argc+argv 并通过 syscall 实现 linux 调用,这样我就可以执行 mmap、打开/写入/读取/关闭等操作。

现在我想为 windows 编写程序集。据我了解,我不想进行系统调用或依赖硬编码地址。在研究时,我发现few examples 使用 NASM 和 MASM 通过在程序集文件中指定函数名称来调用窗口函数。我想编写与 clang 兼容的程序集,而且我对程序集很陌生

我的问题是如何从 clang 理解的程序集文件中调用 OpenFileVirtualAlloc?我可能需要哪些构建选项?我最终会想从 linux 构建 windows 二进制文件,但我将从在 windows 上构建开始,直到我得到程序集和我的其余代码工作

【问题讨论】:

  • 半相关:你提到想在 Linux 上用最少的库编写纯 asm 的东西。有关 Windows 等效的问答是 FASM write Hello World to console with NO includes or dependencies at all。显然,Windows 程序加载器 always 将几个 DLL 映射到进程的地址空间中,即使它们没有明确提及。 (我忘记了答案/cmets是否在我学到的地方或其他地方。)

标签: c windows assembly clang x86-64


【解决方案1】:

在 64 位 Windows 上调用系统函数需要将函数名标记为从其 DLL 导入、对齐 RSP、推送或加载其参数、创建 影子空间、调用函数名并最终恢复 RSP到 equilibrum (到它在调用之前的相同值)。

函数 OpenFile 已弃用,MS 建议改为使用 CreateFileA
查看示例:快速版本的调用WinABI: 以下示例采用 Intel 语法,可在 Windows 上使用euroasm.exe example.asm 进行汇编。它可能需要对其他汇编器进行一些修改:SPL 在其他一些汇编器中称为SPB,这也可能需要default rel 更喜欢LEAADD qword [RSP],8 的RIP 相对编码而不是ADDQ [RSP],8。 如果您的工具更喜欢 AT&T 语法而不是 Intel 语法,请更改 ASM 操作数的顺序并使用 % 前缀寄存器名称。

IMPORT CreateFileA, LIB="kernel32.dll" 

 PUSH RSP                    ; Store original stack pointer value (equilibrum).
 TEST SPL,1000b              ; Test RSP OWORD alignment at run-time.
 JNZ .WinABI1                ; Skip to the label when not aligned.
 PUSH RSP                    ; Store and update 2nd copy of original RSP (equilibrum).
 ADDQ [RSP],8                ; Those two instructions aren't executed if RSP was properly aligned.
.WinABI1:                    ; Local label. 
 PUSHQ 0                     ; Push 7th argument.
 PUSHQ FILE_ATTRIBUTE_NORMAL ; Push 6th argument.
 PUSHQ OPEN_EXISTING         ; Push 5th argument.
 MOV R9,0                    ; Load 4th argument.
 MOV R8,FILE_SHARE_READ      ; Load 3rd argument.
 MOV RDX,GENERIC_READ        ; Load 2nd argument.
 LEA RCX,[FileName]          ; Load 1st argument.
 SUB RSP,4*8                 ; Make room for shadow space in fast mode. RSP is OWORD-aligned.
 CALL CreateFileA            ; Call the imported function.
 LEA RSP,[RSP+7*8]           ; Discard transferred arguments, keep RFlags.
 POP RSP                     ; Restore RSP to equilibrum from 1st or 2nd copy.

与 Linux 不同,如果您希望在 FileName 中允许非 ASCII 字符,则它们应采用宽 (UTF-16) 编码,并且应调用 CreateFileW 而不是 CreateFileA
虽然在 64 位 Windows 版本中调用约定有很大不同,但函数仍在从%SystemRoot%\System32\kernel32.dll%SystemRoot%\System32\user32.dll 等导入。

【讨论】:

  • 这应该与 clang / GNU 汇编器组装 + 链接吗?它看起来不像,没有.intel_syntax noprefix,并且缺少[RIP + FileName] 用于寻址模式。这是 EuroAssembler 语法吗?如果有,请说出来;本问答的重点在于,Eric 发现的示例不适用于纯 clang。
  • 此外,问题的另一个关键部分是您可以(在 Linux 上)运行哪些确切命令来构建 Windows 可执行文件。因此,一个有效的答案需要构建命令和源代码,即使您选择使用与所要求的不同的汇编程序来回答也是如此。
  • @PeterCordes Eric 不太了解汇编,我也不知道铿锵声,所以我只想帮助解决他的一部分问题:如何从汇编中调用 Windows 函数。是的,该示例采用 €ASM 语法,但足够通用,只需稍作调整即可供其他工具使用(我希望如此)。
  • 是的,这样的答案肯定有一些价值。但是,如果您包含必要的构建命令,它将更加有用(这将清楚地表明这 不是 GAS / clang 语法;您甚至没有在当前答案中提到这一点!Asm初学者无法通过查看代码来识别必要的工具)。
猜你喜欢
  • 1970-01-01
  • 2011-02-11
  • 2017-06-22
  • 1970-01-01
  • 2011-05-18
  • 2021-03-04
  • 1970-01-01
  • 1970-01-01
  • 2023-04-02
相关资源
最近更新 更多