30

I'm using ubuntu 64-bit and trying to run a .asm file on NASM. But it returns this error when I try to run the following code. What Iḿ trying to do is build an executable by compiling (or assembling) object file from the source $ nasm -f elf hello.asm, and then after created the file hello.o is producing executable file itself from the object file by invoking linker

$ ld -s -o hello hello.o

This will finally build hello executable.

I'm following this tutorial http://www.faqs.org/docs/Linux-HOWTO/Assembly-HOWTO.html

Error:

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

Code:

     section .data              ;section declaration

 msg     db      "Hello, world!",0xa    ;our dear string
 len     equ     $ - msg                 ;length of our dear string

 section .text              ;section declaration

             ;we must export the entry point to the ELF linker or
     global _start       ;loader. They conventionally recognize _start as their
             ;entry point. Use ld -e foo to override the default.

 _start:

 ;write our string to stdout

         mov     edx,len ;third argument: message length
         mov     ecx,msg ;second argument: pointer to message to write
         mov     ebx,1   ;first argument: file handle (stdout)
         mov     eax,4   ;system call number (sys_write)
         int     0x80   ;call kernel

  ;and exit

     mov    ebx,0   ;first syscall argument: exit code
         mov     eax,1   ;system call number (sys_exit)
         int     0x80   ;call kernel
starblue
  • 55,348
  • 14
  • 97
  • 151
rogcg
  • 10,451
  • 20
  • 91
  • 133

3 Answers3

45

This looks like it may be a simple mismatch between what's produced by nasm and what ld is trying to make:

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

In other words, nasm has produced a 32-bit object file hello.o and ld wants to take that and make a 64-bit executable file.

The nasm -hf command should give you the available output formats:

valid output formats for -f are (`*' denotes default):
  * bin       flat-form binary files (e.g. DOS .COM, .SYS)
    ith       Intel hex
    srec      Motorola S-records
    aout      Linux a.out object files
    aoutb     NetBSD/FreeBSD a.out object files
    coff      COFF (i386) object files (e.g. DJGPP for DOS)
    elf32     ELF32 (i386) object files (e.g. Linux)
    elf       ELF (short name for ELF32) 
    elf64     ELF64 (x86_64) object files (e.g. Linux)
    as86      Linux as86 (bin86 version 0.3) object files
    obj       MS-DOS 16-bit/32-bit OMF object files
    win32     Microsoft Win32 (i386) object files
    win64     Microsoft Win64 (x86-64) object files
    rdf       Relocatable Dynamic Object File Format v2.0
    ieee      IEEE-695 (LADsoft variant) object file format
    macho32   NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (i386) object files
    macho     MACHO (short name for MACHO32)
    macho64   NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (x86_64) object files
    dbg       Trace of all info passed to output stage

I see that your linked tutorial asks you to run:

nasm -f elf hello.asm

Try using:

nasm -f elf64 hello.asm

instead, and you may find ld stops complaining about the input file.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • This is not really the right approach, because the assembly that the OP is writing would also have to be modified (for example, the upper 32 bits of `%rax`, `%rbx` etc. need to be cleared before the system call). – caf Nov 23 '10 at 07:16
  • Yes, @caf, you're probably right about that. Myself, I'd prefer the change-the-code approach since I'm running 64-bit but I can see creating a 32-bit executable would be preferable in some circumstances. Your answer probably provides the minimal-effort version of getting the stuff working so that's probably the best way to go for a tutorial. So +1 for that. – paxdiablo Nov 23 '10 at 07:44
  • 1
    I did as @paxdiablo said, and it worked fine. So is this the right way to do? Because for me worked fine! thanks. – rogcg Nov 23 '10 at 11:43
  • thank you, I was using Sasm as the ide, and it had options like -m64 at the linker and also -g that was giving me troubles... BTW clean answer.... – Mauricio Jan 09 '16 at 17:53
14

You need to tell the linker to produce an i386 output file, since you're writing i386 assembly:

ld -m elf_i386 -s -o hello hello.o
caf
  • 233,326
  • 40
  • 323
  • 462
  • when i use this command it returns the same error: ld: i386:x86-64 architecture of input file `hello.o' is incompatible with i386 output – rogcg Nov 23 '10 at 11:44
  • 2
    @psyhclo: No, that is *not* the same error, that is the opposite error, because you also told `nasm` to create x86-64 output. Do one *or* the other, not both! (I highly suggest creating `i386` output, which means invoking `nasm` as you originally did, and invoking `ld` in this way, since you are actually writing i386 assembler and not x86-64). – caf Nov 23 '10 at 21:33
4

How to compile, link, and run a nasm app on Ubuntu 64 bit.

Install nasm:

sudo apt-get install nasm

Save a file with filename hello.asm:

section .data
  hello:     db 'Hello world!',10    ; 'Hello world!' plus a linefeed character
  helloLen:  equ $-hello             ; Length of the 'Hello world!' string
                                     ; (I'll explain soon)

section .text
  global _start

_start:
  mov eax,4            ; The system call for write (sys_write)
  mov ebx,1            ; File descriptor 1 - standard output
  mov ecx,hello        ; Put the offset of hello in ecx
  mov edx,helloLen     ; helloLen is a constant, so we don't need to say
                       ;  mov edx,[helloLen] to get it's actual value
  int 80h              ; Call the kernel

  mov eax,1            ; The system call for exit (sys_exit)
  mov ebx,0            ; Exit with return code of 0 (no error)
  int 80h

Compile it:

nasm -f elf64 hello.asm

Link it:

ld -s -o hello hello.o

Run it

el@apollo:~$ ./hello
Hello world!

It works! What now? Request that your favorite compiler generate the assembly code that it would have been normally passed on to be converted to machine code. Google search: "convert php/java/python/c++ program to assembly"

Perspective: With all the people today attempting to tear down and get rid of general purpose computing for the general public, it's imperative that we teach the new students the concepts of how to build a general purpose turing machine from core principles, on up through the bare metal, then finally assemblers and programming languages.

How does learning assembly aid in programming? 99% of computer programs out there are 10 to 100 times slower than they could optimized to be only because programmers don't know what delays are being forced on them by their favorite high level compiler or interpreter.

A thorough understanding of the full stack here means you can coerce your programs to have that coveted property of only taking nanoseconds to do the job at hand. Time == money. So this knowledge of how to shun anything that takes longer than a few nanoseconds to complete saves time, and therefore money.

https://softwareengineering.stackexchange.com/questions/156722/how-does-learning-assembly-aid-in-programming

Community
  • 1
  • 1
Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
  • thank you, I was using Sasm as the ide, and it had options like -m64 at the linker and also -g that was giving me troubles... BTW clean answer.... – Mauricio Jan 09 '16 at 19:07