Assembly application doesn't work when assembled on NASM

244 views Asked by At

i'm currently studying x86 assembly and i developed a simple assembly application for MASM that calls the function MessageBoxA and ExitProcess, this is the source code:

.386
.model flat, stdcall
option casemap:none

includelib C:\masm\masm32\lib\kernel32.lib
includelib C:\masm\masm32\lib\user32.lib

ExitProcess PROTO :DWORD
MessageBoxA PROTO :DWORD,:DWORD,:DWORD,:DWORD

.data

msg db "Hello There!!", 0
cpt db "My First Programm!!", 0

.code

start:
    push 0   ; MB_OK
    push OFFSET cpt  ; title
    push OFFSET msg  ; msg
    push 0    ; HWND
    call MessageBoxA

    push 0
    call ExitProcess

end start 

The above code works fine on MASM, but now i'm trying to make a equivalent code for NASM, this is what i wrote:

; test.asm
SECTION .DATA
MsgTitle: db "Message", 10, 0
Message: db "Hello There!", 10, 0

SECTION .TEXT

EXTERN __imp__MessageBoxA@16
EXTERN __imp__ExitProcess@4
GLOBAL _main

_main: ; int main()
    push ebp
    mov ebp, esp
    ;;; Function Main Content
    ; MessageBoxA(NULL, "Hello There!", "Message", MB_OK);
    push 0 ; MB_OK
    push DWORD [MsgTitle]
    push DWORD [Message]
    push 0
    call __imp__MessageBoxA@16
    ; ExitProcess(0)
    push DWORD 0
    call __imp__ExitProcess@4
    ;;;
    mov esp, ebp
    pop ebp
    ;;
    mov eax, 0
    ret

i'm using the Microsoft Incremental Linker for link the libraries User32.lib and kernel32.lib, this the command line:

nasm -f win32 test.asm -o test.obj
link /SUBSYSTEM:CONSOLE /Entry:main test.obj lib\User32.lib lib\kernel32.lib 

The problem is after assemble the code and link the obj, the generated .exe file don't work, it show the error message "test.exe has stopped working", what's wrong?

1

There are 1 answers

0
Michael On BEST ANSWER

push DWORD [MsgTitle] pushes the first 4 bytes located at MsgTitle. What you want is to push the address of MsgTitle, which in NASM syntax would be push DWORD MsgTtitle. So the argument pushing would become:

push DWORD 0 ; MB_OK
push DWORD MsgTitle
push DWORD Message
push DWORD 0

Also, your calls are incorrect. __imp__MessageBoxA@16 is not itself the address of the MessageBoxA function, so you need one level of indirection:

call [__imp__MessageBoxA@16]

The same goes for the call to ExitProcess.

Alternatively, if I change __imp__MessageBoxA@16 to _MessageBoxA@16 it seems like I can use call _MessageBoxA@16.