Create an exe file in assembly with NASM on 32-bit Windows

21,305

Solution 1

Download and install Mingw. Then put nasm in the Mingw bin folder. Create a folder in the bin folder named Hello. In this folder, create a file named main.asm with the following code:

extern _printf
global _main

section .data
msg: db "Hello, world!",10,0

section .text
_main:
    push msg
    call _printf
    add esp,4   
    ret

Open the terminal from inside the folder and compile, first, to object code with nasm:

D:\MinGW\bin\Hello> ..\nasm -fwin32 main.asm

Second, call gcc to link:

D:\MinGW\bin\Hello> ..\gcc main.obj -o main.exe

Finally, test it:

D:\MinGW\bin\Hello> main.exe
Hello, world!

Solution 2

It's an old question but i wonder why no one has mentioned the solution with the standard windows link /subsystem:console /entry:_main main.obj

Solution 3

The OP gave some code that he got from a tutorial, and he assembled it with NASM. When he went to link the output into a Windows executable, he couldn't get it to work.

@Michael Petch noted in the comments on the question (top) that the tutorial source was designed for Linux - the code as given could never work for Windows. He went on to mention that the linker isn't provided by NASM: the OP needed to get it from Microsoft.

Share:
21,305
Mohit Swami
Author by

Mohit Swami

Updated on July 09, 2022

Comments

  • Mohit Swami
    Mohit Swami almost 2 years

    I'm making a hello world program in assembly language with NASM on 32-bit Windows 7. My code is:

    section .text 
    global main ;must be declared for linker (ld) 
    main: ;tells linker entry point 
        mov edx,len ;message length 
        mov ecx,msg ;message to write 
        mov ebx,1 ;file descriptor (stdout) 
        mov eax,4 ;system call number (sys_write) 
        int 0x80 ;call kernel 
        mov eax,1 ;system call number (sys_exit) 
        int 0x80 ;call kernel 
    
    section .data 
        msg db 'Hello, world!', 0xa ;our dear string 
        len equ $ - msg ;length of our dear string
    

    I save this program as hello.asm. Next, I created hello.o with:

    nasm -f elf hello.asm 
    

    Now I'm trying to create the exe file with this command:

    ld -s -o hello hello.o 
    

    But now I receive this error:

    ld is not recognized as an internal or external command, operable program or batch

    Why am I getting this error, and how can I fix it?

  • Peter Cordes
    Peter Cordes about 6 years
    Seems like a bad idea to call your process entry point main: normally that symbol marks a function that's called by CRT startup code. I'd recommend _start or something, like Linux uses by default, unless your command line does link in the CRT code.
  • Peter Cordes
    Peter Cordes about 6 years
    Anyway, yes this is a good answer to the title question; people's search results might bring them here when they have asm source code that will work on Windows, unlike the OP's usage of the 32-bit Linux int 0x80 ABI (which isn't available on Windows, not via cygwin and not even on the Linux on Windows subsystem; it's pure x86-64 without the IA32 compat ABI.)
  • Aritro Shome
    Aritro Shome over 2 years
    why did you append 0 ? 10 was sufficient for newline AFAIK.
  • Cadoiz
    Cadoiz over 2 years
    You can consider the standard windows link /subsystem:console /entry:_main main.obj as mentioned in this answer.
  • ecm
    ecm over 2 years
    @Aritro Shome: printf expects a zero terminated string so you should include an explicit zero-value byte.
  • Aritro Shome
    Aritro Shome over 2 years
    @ecm but when we use printf with C or C++ we don't explicitly include a zero value byte. Is it done by the compiler then ?
  • ecm
    ecm over 2 years
    @Aritro Shome: Yes, It is done by the compiler. The assembler does not automatically add it though. You should explicitly add it. (In practice, it may happen that the next byte in the data section is a zero anyway, but it is better to explicitly include it.)