【问题标题】:programming with NASM in Windows XP在 Windows XP 中使用 NASM 进行编程
【发布时间】:2011-09-21 15:14:23
【问题描述】:

我有以下代码可以在 Windows XP 32 位 2.09.08 NASM 上正常组装和运行:

; how to compile: nasm -f elf test.asm
; how to link: ld -o test.exe test.o

section .data

section .text

;global _WinMain@16
;_WinMain@16:

;global _start
_start:
    mov ax,4           

    jmp $

根据许多关于 NASM 的教程,asm 文件中需要以下内容:

global _WinMain@16
_WinMain@16:
...

如您所见,我的 asm 文件中没有它。 (它被注释掉了,它只有_start)。那么,当我的汇编程序没有全局 _WinMain@16 并且可以工作时,所有这些教程都提到了对全局 _WinMain@16 的需求,这是怎么回事?

这是汇编命令:nasm -f elf test.asm
这是链接的命令:ld -o test.exe test.o

【问题讨论】:

    标签: windows nasm winmain


    【解决方案1】:

    Windows 上有几种类型的应用程序,根据它们的类型,它们具有不同的入口点。通过link.exe选项:

    • /SUBSYSTEM:CONSOLE - 需要 main 并与 msvcrXX.dll 链接。这些应用程序在控制台窗口中运行;如果您没有运行 cmd.exe 实例,则会打开一个。
    • /SUBSYSTEM:WINDOWS - WinMain 是起点。见here。通常在 C 中,这些#include <windows.h> 直接链接到kernel32.dll。这些 gui 应用程序几乎肯定与user32.dll 相关联,也可能与advapi32.dll 相关联。
    • /SUBSYSTEM:NATIVE - 这里有两种类型的应用程序;驱动程序和应用程序。本机 NT 应用程序在 Windows 启动期间运行,并且需要 NtProcessSStartup 作为入口点。本机应用程序中没有 libc。驱动程序又不同了。

    link.exe 支持的 Windows 子系统的完整列表可在 here 获得。

    _start 是窗口实际开始运行代码的符号。通常,libc 等实际上处理_start 并进行一些初始设置,因此您的程序实际上并没有完全从_main 开始。如果您想与 libc 链接,您会遇到问题,因为您的符号与 libc 库有冲突。但是,如果您从不打算调用属于 C 或 C++ 标准库的任何函数,则可以使用 _start

    编辑 哎呀我刚刚注意到这一点:

    ; how to compile: nasm -f elf test.asm
    ; how to link: ld -o test.exe test.o
    

    我假设您没有使用-f elf 之一。 ELF(executable and linkable format)是linux的可执行文件格式; Windows 需要可移植可执行 (PE) 映像。 nasm 选项是-f win32,或者对于dos 是nasm -f coff

    Edit 2只是为了检查,我组装了代码并再次反汇编了它。我也用过mingw。无论如何,我得到了:

    SECTION .text   align=16 execute                        ; section number 1, code
    Entry_point:; Function begin
    ; Note: Length-changing prefix causes delay on Intel processors
            mov     ax, 4                                   ; 00401000 _ 66: B8, 0004
    ?_001:  jmp     ?_001                                   ; 00401004 _ EB, FE
    ; Entry_point End of function
    ; Note: Length-changing prefix causes delay on Intel processors
            mov     ax, 4                                   ; 00401006 _ 66: B8, 0004
    ?_002:  jmp     ?_002                                   ; 0040100A _ EB, FE
    

    标头的其余部分似乎是有效的 PE 格式可执行文件,没有入口点规范。因此,我相信代码只是“落入”第一段汇编代码开始。我不建议这种行为,尤其是在链接多个对象时,因为我不知道会发生什么。请使用-entry

    反汇编精灵目标文件我得到这个:

    SECTION .data   align=4 noexecute                       ; section number 1, data
    SECTION .text   align=16 execute                        ; section number 2, code
    _start_here:; Local function
    ; Note: Length-changing prefix causes delay on Intel processors
            mov     ax, 4                                   ; 0000 _ 66: B8, 0004
    ?_001:  jmp     ?_001                                   ; 0004 _ EB, FE
    _another_symbol:; Local function 
    ; Note: Length-changing prefix causes delay on Intel processors
            mov     ax, 4                                   ; 0006 _ 66: B8, 0004
    ?_002:  jmp     ?_002     
    

    换句话说,其中没有任何特定的 ELF 格式标头。我相信您对此很幸运;开始导入或尝试与其他代码模块链接,事情将开始变得更加棘手。

    对于 Windows / mingw,你想要:

    nasm -f win32 file.asm 
    

    对于您要组装的每个文件。需要时将win32 替换为win64ld 可以很好地进行链接。

    只是一个想法 - 我从未解释过 @16 部分。这些函数在 Windows 上是 16 字节对齐的,而如您所见,数据仅是 4 字节对齐的。请参阅this explanation 了解原因。

    【讨论】:

    • 我没有使用 link.exe 来链接我的程序。我正在使用ld。我测试了一个新的起点:_startHerePlease: ... 它也可以毫无问题地组装和链接并执行。如果我使用的是裸机程序集(没有 C、C++ 或其他库),那么我可以将起始符号设为任何东西吗?
    • 不,我一直在使用该命令来组装它:nasm -f elf test.asm。也一直在使用链接命令:ld -o test.exe test.o。它适用于我的 windows 框
    • @TheFuzz 是的,您可以使用ld --entry=_startHerePlease
    • @Ninefingers 使用 ld 时没有指定入口点,也没有问题。
    • 我应该只在与微软的链接器链接时使用 -f win32 选项正确吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-04
    • 2016-01-19
    • 2010-09-16
    • 2012-12-15
    • 2017-08-10
    • 1970-01-01
    相关资源
    最近更新 更多