汇编语言是最贴近机器硬件、运行效率很高的一种低级编译型语言。由于它与硬件紧密相关,因此它的开发完全受平台限制,所开发的程序基本上不具有移植性。当然,只要硬件(主要是中央处理器)相近,那就有可能采用同一套汇编语言编程工具进行程序开发。MSYS2 是 GCC 工具链在 MS Windows 上极为成功的移植!利用 MSYS2 提供的编程工具,就可以通过 C/C++/Python 等编程语言进行 MS Windows 上的原生程序开发。这既可以借鉴 GNU Linux 上优秀开源软件的成功开发经验,还可以将这些优秀的软件移植到 MS Windows 平台。不过,这里要介绍的是如何利用 MSYS2 中基于 MinGW x64 工具链提供的 GNU as 与 ld 工具进行 GNU 汇编程序的开发。
先来看一个示例,它主要通过指令 call 调用了标准 C 函数:
/* test.s */ .section .data msg: .asciz "Hello, MSVC Library!" .section .text .global main main: pushq %rbp movq %rsp, %rbp subq $8, %rsp leaq msg(%rip), %rcx call printf xor %eax, %eax call exit
上述汇编源代码在 MSYS2 环境下的编译以及运行过程是这样的:
$ as -o test.o test.s $ ld -o test.exe test.o -lmsvcrt $ ./test.exe
为了正确编写 GNU 汇编源代码,除了熟悉 AT&T 汇编语法与 Amd64 指令集之外,特别需要了解 MS Windows x64 的调用协定(FASTCALL 的一种变体)、MS Windows C/C++ 运行库,请参看 https://learn.microsoft.com/en-us/cpp/build/x64-software-conventions?view=msvc-170、https://learn.microsoft.com/en-us/cpp/c-runtime-library/crt-library-features?view=msvc-170。
再来看如何调用 MS Windows 的应用程序编程接口?
.section .rodata mba_msg: .asciz "Hello ASM world!" mba_title: .asciz "Simple Message Box" .section .text .globl _start _start: # align RSP pushq %rbp movq %rsp, %rbp subq $0x20, %rsp # https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messageboxa # display a message box xorl %ecx, %ecx # hWnd = NULL leaq mba_msg(%rip), %rdx leaq mba_title(%rip), %r8 movl $0x40, %r9d # MB_ICONINFORMATION call MessageBoxA # exit with zero xorl %ecx, %ecx call ExitProcess
上述源代码在 MSYS2 环境下的编译以及运行过程是这样的:
$ as -o test.o test.s $ ld test.o -lkernel32 -luser32 -o test.exe $ ./test.exe
Linux 与 MS Windows API 对照表 https://www.cnblogs.com/UnGeek/p/2981439.html。如果 GNU 汇编代码中还调用了 Nt/Zw 开头的 MS Windows API,那么只需在使用 GNU 链接器时增加 NTDLL 选项。