14
votes

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 
2
Please edit the title so it will be useful to future visitors. Otherwise it may get closed as too localized.Raymond Chen
@RaymondChen to what?fulvio

2 Answers

35
votes

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
9
votes

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.