14

I'm using nasm to compile the following assembly. However the code crashes in the console under Windows.

C:\>nasm -f win32 test.asm -o test.o

C:\>ld test.o -o test.exe

section .data
  msg   db    'Hello world!', 0AH
  len   equ   $-msg

section .text
  global _WinMain@16

_WinMain@16:
  mov   edx, len
  mov   ecx, msg
  mov   ebx, 1
  mov   eax, 4
  int   80h

  mov   ebx, 0
  mov   eax, 1
  int   80h

According to this post. The main function is not available under Windows and must be replaced by WinMain.

So if your entry point is _start or main, it should be changed to _WinMain@16 and change the ret at the end of the procedure to ret 16:

My working example:

section .text       
 global _WinMain@16       

_WinMain@16:       
 mov eax, 0       
 ret 16 
Community
  • 1
  • 1
gotnull
  • 26,454
  • 22
  • 137
  • 203

2 Answers2

37

The biggest problem is that you are trying to use Linux interupts on windows! int 80 will NOT work on windows.

We are using Assembly, so your entry point can be ANY label you want. The standard entry point that ld looks for is _start, if you want to use another label, you need to tell ld with the -e option So if you want your start label to be main, then you need

global main
ld -e main test.o -o test.exe

If you are going to use NASM on Windows, I will recommend using GoLink as your linker. Here is a simple windows console app:

STD_OUTPUT_HANDLE   equ -11
NULL                equ 0

global GobleyGook
extern ExitProcess, GetStdHandle, WriteConsoleA

section .data
msg                 db "Hello World!", 13, 10, 0
msg.len             equ $ - msg

section .bss
dummy               resd 1

section .text
GobleyGook:
    push    STD_OUTPUT_HANDLE
    call    GetStdHandle

    push    NULL
    push    dummy
    push    msg.len
    push    msg
    push    eax
    call    WriteConsoleA 

    push    NULL
    call    ExitProcess

makefile:

hello: hello.obj
    GoLink.exe  /console /entry GobleyGook hello.obj kernel32.dll  

hello.obj: hello.asm
    nasm -f win32 hello.asm -o hello.obj
Gunner
  • 5,780
  • 2
  • 25
  • 40
  • 1
    @Gunner thank you. One question though - what is the reason you recommend GoLink over other linkers? – Boris Milner Sep 25 '15 at 14:54
  • @Boris Personal preference I guess. Found it easier to work with than other linkers on Windows. – Gunner Sep 25 '15 at 17:55
  • The zero byte at the end of the message string should not be there. It's not required by WriteConsoleA which uses the supplied string length and in fact ends up getting written to the console, showing up as a space when I tried it. Removing the zero byte fixed the problem. – Phil Dennis Aug 19 '16 at 15:38
  • Instead of `call ExitProcess` and `call WriteConsoleA `, does Windows have the equivalent of simply doing `syscall`? – Pacerier Apr 28 '17 at 17:48
  • Is there an equivalent of this for 64 bit windows? If I try to do `-f win64` I get `error: instruction not supported in 64-bit mode` at the `push eax` line. – kepe Mar 09 '19 at 14:32
9

Although, this same program probably will run in WINE on Linux like a charm. :)

WINE doesn't prevent using Linux system calls from inside Windows PE binaries; the machine instructions run natively and WINE only provides DLL functions.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
johnfound
  • 6,857
  • 4
  • 31
  • 60
  • 4
    @JayBlanchard This is an answer, because it points the OS, where the program will work properly, without mentioned in the question crash. – johnfound May 29 '14 at 08:31
  • Oh, you mean on a Linux machine, where the system calls run natively and WINE has nothing to do with them. I thought at first that you meant that WINE went both ways, and that it could emulate the Linux `int 0x80` ABI on a Windows machine! – Peter Cordes Oct 24 '17 at 07:24
  • @PeterCordes WINE runs only on Unix machines and emulates the Windows API. But as long as the programs run not in VM, but native in the memory of the Linux OS, they can use int 0x80 system calls. Of course, such program will crash on real Windows. But the program can detect the OS and to use such calls only when running on Linux. – johnfound Oct 24 '17 at 12:47
  • Yeah, I know all that. I was trying to say that your answer misled me for a minute. Note that WINE runs on some non-Linux OSes (*BSD, including OS X), where native Linux system calls wouldn't work. – Peter Cordes Oct 24 '17 at 23:10