Search code examples
windowsnasmwinmain

programming with NASM in Windows XP


I have the following code which assembles and runs fine on Windows XP 32 bit, 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 $

According to many tutorials on NASM the asm file needs the following in it:

global _WinMain@16
_WinMain@16:
...

As you can see my asm file doesn't have that in it. (it's commented out, All it has is _start). So what is with all of these tutorials mentioning the need for the global _WinMain@16 stuff when my assembly program doesn't have that and works?

this is the command to assemble: nasm -f elf test.asm
this is the command to link: ld -o test.exe test.o


Solution

  • There are several types of application on Windows with different entry points depending on which type they are. By link.exe option:

    • /SUBSYSTEM:CONSOLE - requires main and linking with msvcrXX.dll. These applications run in console windows; if you aren't running an instance of cmd.exe, one will be opened.
    • /SUBSYSTEM:WINDOWS - WinMain is the starting point. See here. Usually in C, these #include <windows.h> and are linked directly to kernel32.dll. These a gui apps and are almost definitely linked with user32.dll and possibly advapi32.dll as well.
    • /SUBSYSTEM:NATIVE - there are two types of application here; drivers and applications. Native NT apps run during windows startup and require NtProcessSStartup as an entry point. There is no libc in native applications. Drivers are different again.

    A full list of supported windows subsystems by link.exe is available here.

    _start is the symbol windows will actually start your code running at. Normally, libc or the like actually handles _start and does some initial setup, so your program doesn't actually quite start at _main. If you wanted to link with libc you would have problems, since you'd have conflicting symbols with the libc library. If however you never intend to call any functions that are part of the C or C++ standard libraries, you are ok using _start.

    Edit yikes I've just noticed this:

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

    I assume you're not using the -f elf one. ELF (executable and linkable format) is the linux format for executables; Windows requires Portable Executable (PE) images. The nasm option is -f win32, or for dos nasm -f coff.

    Edit 2 just to check, I assembled the code and disassembled it again. I also used mingw. Anyway, I got:

    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
    

    The rest of the header appears to be a valid PE format executable with no Entry point specification. I believe therefore that the code is simply "falling through" to the first piece of assembly code to start. I wouldn't advise this behaviour, especially when linking multiple objects as I've no idea what would happen. Do use -entry.

    Disassembling the elf object file I get this:

    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     
    

    In other words, there aren't any specific ELF-format headers in it. I believe you're getting lucky on this one; start importing or trying to link with other code modules and things will start to get more tricky.

    For Windows / mingw, you want:

    nasm -f win32 file.asm 
    

    for each file you want to assemble. Substitute win32 for win64 when needed. ld will do fine for linking.

    Just a thought - I never explained the @16 part. The functions are 16-byte aligned on Windows, whereas, as you can see, the data is only four-byte aligned. See this explanation for the why.