8

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?

Michael Petch
  • 46,082
  • 8
  • 107
  • 198
Mohit Swami
  • 125
  • 1
  • 1
  • 11
  • _LD_ isn't a part of _NASM_. If you wish to use _LD_ you can download a GNU tool chain that includes binutils (_LD_ is part of Binutils). The TDM-GCC product (open source) has an installer with a complete GCC/Binutils tool chain: https://sourceforge.net/projects/tdm-gcc/ – Michael Petch May 24 '16 at 11:13
  • I want to make a exe file with nasm in windows 32bit – Mohit Swami May 24 '16 at 12:32
  • Which command I have to use. – Mohit Swami May 24 '16 at 12:33
  • It will be pretty important for you to understand that Windows doesn't use ELF. – David Hoelzer May 24 '16 at 14:18
  • But i read about this in a tutorial and in nasm PDF which is provided by nasm when we install it ...and if I'm wrong so give right way to make hello world program with nasm in windows 32bit – Mohit Swami May 24 '16 at 14:26
  • On Windows, you have to use [`MASM link`](https://msdn.microsoft.com/en-us/library/hx5b050y.aspx) or some MASM compatible linker like [`JWASM JLink`](https://sourceforge.net/projects/jwlink/). Their output format must **NOT** be ELF. – zx485 May 24 '16 at 15:34
  • @zx485 : The TDM-GCC GNU tool chain link I gave in my first comment produces Windows PE executables. That version of _LD_ is limited to producing PE binaries. – Michael Petch May 24 '16 at 15:43
  • @Michael Petch: You may be right, but the question was to make a `hello world` on a 32-bit Windows 7. Using `MASM` or `JWASM` would be far more native than using the *nix GNU toolchain... – zx485 May 24 '16 at 15:49
  • 2
    Of course it would be interesting to see the NASM code you are using. If you happen to be following a Linux tutorial don't expect the program to run properly. Can you provide a link to the tutorial you are using? – Michael Petch May 24 '16 at 15:51
  • 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 – Mohit Swami May 24 '16 at 17:10
  • 2
    I've placed your code into your question as an edit for you. As I suspected you are using a Linux tutorial on Windows. Linux isn't Windows unfortunately. Even if you linked this to an executable called `hello.exe`, and ran it, it would fail. `int 0x80` doesn't apply to Windows, it is a 32-bit system call for Linux. You are going to have to find a tutorial on writing Windows programs in assembler. – Michael Petch May 24 '16 at 18:26
  • Besides the toolchain problems, you are invoking Linux syscalls, this won't work at all on Windows. – Matteo Italia May 24 '16 at 18:26
  • 1
    If you were to install [TDM-GCC](https://sourceforge.net/projects/tdm-gcc/) (there is a link in my first comment) that installed GCC and LD (part of the GNU tool chain) and then followed the first part of this [Stackoverflow answer](http://stackoverflow.com/a/1023600/3857942) you may be able to print `Hello World`. The method in that example uses the _C_ library function `printf` from assembler code to do the printing. – Michael Petch May 24 '16 at 18:29
  • 1
    Possible duplicate of [x86 assembly create Win32 executable NASM](http://stackoverflow.com/questions/18770828/x86-assembly-create-win32-executable-nasm) – Peter Cordes May 24 '16 at 18:51
  • The question title is a duplicate of that, but of course the OP is trying to do something that won't work (Linux tutorial on Windows), so maybe there's a better duplicate. 2 seconds with google turned up the above question, so downvoting for lack of research effort. – Peter Cordes May 24 '16 at 18:53
  • 1
    Possible duplicate of [How to write hello world in assembler under Windows?](http://stackoverflow.com/questions/1023593/how-to-write-hello-world-in-assembler-under-windows) – Michael Petch May 24 '16 at 19:06
  • This is not duplicate because this problem is related to nasm commands. – Mohit Swami May 24 '16 at 19:06
  • @MohitSwami : The duplicate I directed you to was specifically for _NASM_, and there are some answers in there that would work (there is a 32 and 64-bit example among the answers). You just need to get ahold of a linker. I've shown you where you can get _LD_ since it isn't installed with _NASM_ on Windows. But you could also use the Microsoft linker or a variety of other ones, but again you'd have to install it from Microsoft - The one in Visual Studio Express editions would work fine. – Michael Petch May 24 '16 at 19:08
  • _LD_ isn't a NASM command by the way. It is separate. _LD_ is installed by default on Linux so it is always available. On Windows you have to install it. It is neither supplied by Windows, nor supplied by NASM. – Michael Petch May 24 '16 at 23:18

3 Answers3

13

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!
Yun
  • 3,056
  • 6
  • 9
  • 28
Henri Latreille
  • 263
  • 1
  • 11
  • why did you append 0 ? 10 was sufficient for newline AFAIK. – Aritro Shome Aug 29 '21 at 12:14
  • @Aritro Shome: `printf` expects a zero terminated string so you should include an explicit zero-value byte. – ecm Oct 06 '21 at 10:01
  • @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 ? – Aritro Shome Oct 06 '21 at 15:18
  • @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.) – ecm Oct 06 '21 at 16:31
8

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

0x3h
  • 452
  • 9
  • 22
  • 2
    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 Feb 14 '18 at 08:06
  • 2
    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.) – Peter Cordes Feb 14 '18 at 08:08
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.

Cadoiz
  • 1,446
  • 21
  • 31
John Burger
  • 3,662
  • 1
  • 13
  • 23
  • You can consider the standard windows `link /subsystem:console /entry:_main main.obj` as mentioned in [this answer](https://stackoverflow.com/a/48781796/4575793). – Cadoiz Oct 06 '21 at 08:43