I am new to assembly language programming. I am trying to follow the steps outlined here to get a better understanding of assembly and optimization. My operating system is Linux Mint, and I am trying to use the NASM assembler, albeit unsuccessfully.
As in the walkthrough, the code is:
BITS 32
GLOBAL main
SECTION .text
main:
mov eax, 42
ret
It compiles successfully with nasm using the command: nasm -f elf tiny.asm
But if I try to use gcc to link with the command: gcc -Wall -s tiny.o
I get the following error: /usr/bin/ld: i386 architecture of input file `tiny.o' is incompatible with i386:x86-64 output
A quick search told me that I should link using this ld command: ld -m elf_i386 -s -o tiny tiny.o
However, doing this gives me the following warning: ld: warning: cannot find entry symbol _start; defaulting to 0000000008048060
And if I ./tiny
I get a Segmentation Fault. And ./tiny ; echo $?
also returns the number '139' which is... unexpected.
Browsing around, I see that the problem is solved for some by passing 1 to the eax register and 0 to ebx, and using an int command I'm unfamiliar with to end the program... But considering my objective is to make the program as small as possible, I would rather not add additional lines of code.
I should add that compiling and linking this similar code (GAS):
.global main
.text
main:
mov $32, %eax
Using the gcc compiler seems to run flawlessly. I'm at a loss here. Any point in the right direction would be greatly appreciated.
This applies to Linux Mint, Ubuntu, Xubuntu and other modern Ubuntu based distributions. For other Debian systems the information is the same, but you can remove the sudo
command from the installation command and run the command as the root
user.
By default files needed for GCC to create 32-bit program are not installed on 64-bit Linux Mint. This command will install the required files:
sudo apt-get install gcc-multilib g++-multilib
To assemble asa 32-bit object, and then link to a 32-bit executable you can do this:
nasm -f elf32 tiny.asm -o tiny.o
gcc -m32 -Wall -s tiny.o -o tiny
Since you had BITS 32
at the top of the assembler file you want to compile that to a 32-bit ELF object which is what the -f elf32
option on the NASM command line does.
GCC is used to link objects to a final executable. The addition of -m32
tells GCC to link the objects to a 32-bit executable. The -m32
option overrides the normal default behavior of generating 64-bit executables on a 64-bit Linux distribution.
By using GCC to link the executable, the generated program actually supplies a _start
that does C runtime initialization and then calls the label called main
as if it was a C function.
When you do the ret
in your main
function it returns back to the C runtime code and exits the program cleanly for you.
Using GCC is the easier and safer method for new assembly language developers. It also allows you to add code that calls the C runtime functions like printf
, scanf
, atoi
and most of the other standard C library functions.