Kno*_*how 0 windows assembly x86-64
我真的需要一些帮助。我已经在网上搜索了大约 2 天,似乎无法找到我遇到的问题的答案。
我下载了 nasm 并安装了它,它似乎可以工作,但我似乎找不到任何适用于 Windows 64 位的示例代码(如果你能为我或其他东西制作一个简单的 hello world 示例,那就太棒了)。(以及如何编译它)
我如何将 .o 文件变成 .exe?
我将如何访问屏幕或 GPU 内存(我认为)以在屏幕上打印内容(例如某种控制台应用程序)?
在 Windows 下使用 NASM 进行汇编编程时需要考虑以下几点:
NASM 只是一个汇编程序
创建可执行文件需要一个链接器。
Windows API 是作为用户空间库实现的。
该库并不完全在用户空间,有些函数跨越边界,但应用程序的接口是一组DLL,最显着的是:kernel32.dll、user32.dll等。
Windows 的可执行文件可以有不同的子系统。
其中IMAGE_SUBSYSTEM_WINDOWS_GUI和IMAGE_SUBSYSTEM_WINDOWS_CUI是最常用的,前者由创建窗口的应用程序使用,后者由使用控制台的应用程序使用1。
链接器获取汇编器生成的COFF对象 (.obj) 文件,获取一组库定义 (.lib) 并执行以下重要步骤:
它解析对目标文件中的外部函数的调用。
标记为外部的函数旨在在库定义之一中找到,然后链接器修复调用指令以指向将在运行时找到函数地址的位置。
它将依赖库添加到最终的可执行文件中。
这是在PE 文件格式的帮助下完成的,基本上如果F如果在库L上找到,那么L将与写入F的地址的位置一起添加到依赖项列表中。
装载机将完成剩下的工作。
链接实际上比这更复杂。
它还负责设置各种 PE 标志和设置,包括子系统和入口点。
要使用 NASM 编写可执行文件,请执行以下操作:
这些可以在Windows SDK 2 中找到。
我们将在此示例中使用的链接器是 Microsoft LINK 链接器。
正如@CodyGray 在其评论中指出的那样(引用是因为我很懒):
您链接的 SDK 的 Windows 7 版本包含所有构建工具。Windows 8 SDK 已更改,不再随命令行构建工具一起提供,迫使您下载 Visual Studio 包
一旦我们有了工具,我们就可以开始编程了。
我们将使用WriteFile将一个字符串写入标准输出(就像我们在 Linux 汇编中所做的那样)。
但是,必须使用GetStdHandle检索标准输出的处理程序。
在 Windows 中,ret即使没有 CRT(C 运行时)链接(即在裸进程中),您也可以退出进程。
我不会解释 Window 64 ABI 或 64 位编程的技巧。
BITS 64
DEFAULT REL ;RIP relative addressing by default
GLOBAL main ;Main must be visible to the linker
;Function the linker will look for in other modules (libs or objs)
EXTERN WriteFile
EXTERN GetStdHandle
STD_OUTPUT_HANDLE EQU -11
SECTION .data
strHelloWorld db "Hello world!", 13, 10, 0
lenHelloWorld dd $-strHelloWorld
hOut dd 0 ;Will store STDOUT handler
SECTION .text
main:
sub rsp, 30h ;20h (Home space) + 10h (params)
;Get STDOUT handler (Handler are 32-bit values)
mov ecx, STD_OUTPUT_HANDLE
call GetStdHandle
mov DWORD [hOut], eax ;Useless as now, for future reuse
;Write strHelloWorld to STDOUT
mov ecx, eax
lea rdx, [strHelloWorld]
mov r8d, DWORD [lenHelloWorld]
xor r9, r9
mov QWORD [rsp+20h], r9
call WriteFile
add rsp, 30h
ret
Run Code Online (Sandbox Code Playgroud)
要从此源创建可执行文件,我们首先将其组装成 64 位目标文件:
nasm -fwin64 hello.asm -o hello.obj
Run Code Online (Sandbox Code Playgroud)
然后我们将它链接到kernel32库(我们唯一需要的库):
link /MACHINE:X64 /SUBSYSTEM:CONSOLE /OUT:hello.exe /NODEFAULTLIB /ENTRY:main kernel32.lib hello.obj
Run Code Online (Sandbox Code Playgroud)
CLI 开关非常简单,NODEFAULTLIB避免与Microsoft CRT MSVCVRXX.lib链接。在本例中,这些是构建可执行文件所需的最小开关。
我假设您足够聪明,可以在发出上述命令时解决路径问题,特别是您可以告诉链接在哪里可以找到 lib 文件。
对于这个例子,我只是从 SDK 安装文件夹中复制了它们。
正如其他答案中所建议的,您可以使用链接器附带的其他汇编程序。
另一种可能的开发环境是使用gcc(在cygwin 内或作为mingw)来执行链接器步骤。
1在这种情况下,Windows 会自动为应用程序创建一个控制台并适当地设置标准处理程序。GUI 应用程序也可以重新创建控制台(或多个),因此IMAGE_SUBSYSTEM_WINDOWS_GUI必须是“默认无控制台”。
2链接的版本是第一个谷歌结果,花更多时间寻找合适的版本。另外,我不确定 Windows SDK 中是否有链接器,或者您需要下载 Visual Studio。