Rubberduccky
Rubberduccky

Reputation: 117

How to link 32-bit Nasm assembly object code on a 64-bit windows computer

I found the following code from http://www.dreamincode.net/forums/topic/328714-my-program-keeps-crashing/.

            global  start

            ;~ msvcrt.dll
            extern  _printf
            %define printf _printf

            ;~ kernel32.dll
            extern ExitProcess, GetCommandLineW, LocalFree
            %define GetCommandLine GetCommandLineW

            ;~ shell32.dll
            extern CommandLineToArgvW
            %define CommandLineToArgv CommandLineToArgvW

            SECTION .data
            message     db      'Hello, World', 13, 10, 0
            fmtstr      db      "%s", 0
            fmtstrCL    db      "Arg","%d", " = ", "%S", 13, 10, 0

            section .bss
            pNumArgs    resd    1

            section .text
            start:

                call    GetCommandLine

                push    pNumArgs
                push    eax
                call    CommandLineToArgv
                mov     esi, eax

                mov     ebx, [pNumArgs]
            DisplayArgs:
                dec     ebx
                push    dword[esi + 4 * ebx]
                inc     ebx
                push    ebx
                push    fmtstrCL
                call    printf
                add     esp, 4 * 3
                dec     ebx
                jnz     DisplayArgs

                push    esi
                call    LocalFree   

                push    message                         ; Push address of "Hello, world!" onto the stack
                push    fmtstr                          ; push address of formatter onto the stack
                call    printf                          ; Print the message
                add     esp, 4 * 2                      ; adjust stack pointer

                push    0
                call    ExitProcess

My goal is to learn assembly language by reading other people's code and eventually write my own. I cannot figure out how to link 32-bit assembly programs on my 64-bit windows computer.

To assemble the program I use the command:

nasm -f win32 hello32.asm -o hello32.o

To link the object file I use:

gcc hello32.o -o hello32.exe

After I issue the link command I get the following error:

C:/Program Files/mingw-w64/x86_64-5.2.0-posix-seh-rt_v4-rev0/mingw64/bin/../lib/
gcc/x86_64-w64-mingw32/5.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: i386 arc
hitecture of input file `hello32.o' is incompatible with i386:x86-64 output
hello32.o:hello32.asm:(.text+0x24): undefined reference to `_printf'
hello32.o:hello32.asm:(.text+0x3f): undefined reference to `_printf'
C:/Program Files/mingw-w64/x86_64-5.2.0-posix-seh-rt_v4-rev0/mingw64/bin/../lib/
gcc/x86_64-w64-mingw32/5.2.0/../../../../x86_64-w64-mingw32/lib/../lib/libmingw3
2.a(lib64_libmingw32_a-crt0_c.o):crt0_c.c:(.text.startup+0x2e): undefined refere
nce to `WinMain'
collect2.exe: error: ld returned 1 exit status

I am using 64-bit mingw binaries that are supposed to be compatible with making 32-bit programs. I have tried switching to 32-bit mingw binaries and I get a massive amount of undefined reference errors. I can link simple skeleton files without any problems using the above commands. I have no idea what I am doing wrong and I would appreciate any guidance someone could give me.

Upvotes: 2

Views: 4293

Answers (2)

Chameera Dedduwage
Chameera Dedduwage

Reputation: 537

Two issues:

  1. You're using the option -f win32 but asking for the object file in *.o extension. The two formats, .o and .obj are not compatible. But of course, you're free to specify your own extension, and so nasm will obediently assemble your code into a file with i386 arc format .o file.
  2. Next, you're asking gcc to build that hello32.exe, using the file hello32.o. Effectively, you gave gcc an arc format .o file, and asked to build a 64-bit PE format executable out of it. And then (naturally) gcc complains:

    i386 architecture of input file `hello32.o' is incompatible with i386:x86-64 output

which is correct.

Two ways you can fix this:

  1. Assemble with: nasm -fwin32 hello32.asm and then, link with gcc -m32 hello32.obj -o hello32.exe
  2. Assemble with: nasm -fobj hello32.asm and then link with alink -subsys console -oPE hello32.o. You can get alink from here.

Let me know which worked for you.

P.S. I have outlined the problems I have faced myself in this blog, hope that helps.

Upvotes: 0

Andreas Fester
Andreas Fester

Reputation: 36630

i386 architecture of input file `hello32.o' is incompatible with i386:x86-64 output

NASM has created a 32 bit object file, but you are trying to link a 64 bit executable. You could try to use the -m32 switch to create a 32 bit executable, but you already found out that this causes another bunch of errors. I do not have a solution for that either.

To link your executable, use a 32 bit MingW environment. I tried MinGW4.6.2 32 bit which worked well. Alternatively, you can use the linker (link.exe) from a Microsoft Visual Studio installation.

https://github.com/afester/CodeSamples/tree/master/Asm/nasm_win32 shows a hello world example together with a Makefile which uses the Visual Studio linker. Alternatively, using gcc helloworld.obj -o hello32.exe from a MingW32 installation works also.

Upvotes: 1

Related Questions