在64位Windows上设置汇编程序

时间:2016-12-16 08:25:28

标签: windows assembly x86-64

我真的需要一些帮助。我现在已经在网上搜索了大约2天,似乎找不到我遇到的问题的答案。

  1. 我下载了nasm并安装它似乎工作但我似乎无法找到适用于Windows 64bit的任何示例代码(如果你能为我做一个简单的hello world示例,那将会很棒或者其他的东西)。 (以及如何编译它)

  2. 如何将.o文件转换为.exe?

  3. 我如何访问屏幕或gpu内存(我认为)在屏幕上打印内容(比如某种控制台应用程序)?

2 个答案:

答案 0 :(得分:4)

在Windows下使用NASM进行汇编编程时需要考虑以下几点:

  1. NASM只是一个汇编程序
    需要链接器来创建可执行文件。

  2. Windows API实现为用户空间库 库不是完全在用户空间,有些函数跨越边界,但应用程序的接口是一组DLL,最值得注意的是:kernel32.dll,user32.dll等。

  3. Windows'可执行文件可以有不同的子系统 其中 IMAGE_SUBSYSTEM_WINDOWS_GUI IMAGE_SUBSYSTEM_WINDOWS_CUI 是最常用的,前者由创建窗口的应用程序使用,后者由使用控制台 1的应用程序

  4. 链接器获取汇编程序生成的 COFF 对象(.obj)文件,获取一组库定义(.lib)并执行以下重要步骤:

    1. 它解析对目标文件中找到的外部函数的调用。
      标记为 external 的函数意味着在其中一个库定义中找到,然后链接器将调用指令固定为指向将在运行时找到函数地址的位置。

    2. 它将依赖库添加到最终的可执行文件中。
      这是在PE file format的帮助下完成的,基本上如果 F ,如果在库 L 上找到,那么 L 被添加到依赖项列表以及写入 F 地址的位置 装载机将完成其余工作。

    3. 链接实际上比这更复杂 它还负责设置各种PE标志和设置,包括子系统和入口点。

      使用需要的NASM编写可执行文件:

      1. 链接器。
      2. 库定义集。
      3. 这些可以在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  
        

        要从此源创建可执行文件,我们首先将其组装到64位目标文件中:

        nasm -fwin64 hello.asm -o hello.obj
        

        然后我们将它与 kernel32 库(我们唯一需要的)链接起来:

        link /MACHINE:X64 /SUBSYSTEM:CONSOLE /OUT:hello.exe /NODEFAULTLIB /ENTRY:main kernel32.lib hello.obj
        

        CLI开关非常简单, NODEFAULTLIB 避免与 MSVCVRXX.lib (Microsoft CRT)链接。 这些是在此示例中构建可执行文件所需的最小开关。

        我认为您在发布上述命令时足够聪明,可以解决路径问题,尤其是您可以告诉 link 在哪里找到lib文件。
        对于此示例,我只是从SDK安装文件夹中复制它们。

        正如其他答案中所提出的,您可以使用链接器附带的其他汇编程序 另一种可能的开发环境是使用 gcc (在 cygwin 内部或作为 mingw )来执行链接器步骤。

        1 在这种情况下,Windows会自动为应用程序创建一个控制台并相应地设置标准处理程序。 GUI应用程序也可以重新创建控制台(或多个),因此 IMAGE_SUBSYSTEM_WINDOWS_GUI 必须打算为“默认情况下没有控制台”。

        2 链接的版本是Google的第一个结果,投入更多时间寻找合适的版本。另外,我不确定Windows SDK中是否有链接器,或者您需要下载Visual Studio。

答案 1 :(得分:1)

下载Flat Assembler。(下载 - >用于Windows的平面汇编程序)

http://flatassembler.net/

提取拉链。

转到'examples / win64 / pe64demo /'

打开'pe64demo.exe'

(源代码在'pe64demo.asm')