Compiling 32 bit Assembler on 64 bit ubuntu
First change _printf
to printf
and the _start
symbol to main
, then use gcc
to link the object file, which will automatically link it to libc
, you need to do that because AFAIK you can't link to libc without a main
. Also you should use elf32 not elf64 when assembling because the code has 32 bits instructions :
bits 32
extern printf
global main
section .data
message db "Hello world!!", 10, 0
section .text
main:
pushad
push dword message
call printf
add esp, 4
popad
ret
And build with:
nasm -f elf32 vaja4.asm
gcc -m32 vaja4.o -o vaja4
$./test
$Hello world!!
Edit:
Since you're now compiling 32-bit code on a 64-bit system, you will need to install the 32-bit version of the libraries
apt-get install ia32-libs
Compiling 32 bit assembly on 64bit system (Ubuntu)
When your assembler and linker are x86_64 versions, the options to produce i386 (32-bit) output are
as --32
ld -m elf_i386
You don't have to use as
and ld
just because you're working with assembly code. gcc
can be used, and in that case you would use -m32
.
gcc -m32 -nostdlib myprog.s -o myprog
How to Compile 32-bit Apps on 64-bit Ubuntu?
To get Ubuntu Server 12.04 LTS 64-bit to compile gcc 4.8 32-bit programs, you'll need to do two things.
Make sure all the 32-bit gcc 4.8 development tools are completely installed:
sudo apt-get install lib32gcc-4.8-dev
Compile programs using the -m32 flag
gcc pgm.c -m32 -o pgm
Compile 32 bit at&t assembly program on 64 bit linux not working
Moving the comment to an 'answer' (since apparently I guessed correctly):
Depending on the assembler, it may be necessary to prefix register names with a % sign (ie %esp
).
Running 32 bit assembly code on a 64 bit Linux & 64 bit Processor : Explain the anomaly
Remember that everything by default on a 64-bit OS tends to assume 64-bit. You need to make sure that you are (a) using the 32-bit versions of your #includes where appropriate (b) linking with 32-bit libraries and (c) building a 32-bit executable. It would probably help if you showed the contents of your makefile if you have one, or else the commands that you are using to build this example.
FWIW I changed your code slightly (_start -> main):
#include <asm/unistd.h>
#include <syscall.h>
#define STDOUT 1
.data
hellostr:
.ascii "hello wolrd\n" ;
helloend:
.text
.globl main
main:
movl $(SYS_write) , %eax //ssize_t write(int fd, const void *buf, size_t count);
movl $(STDOUT) , %ebx
movl $hellostr , %ecx
movl $(helloend-hellostr) , %edx
int $0x80
movl $(SYS_exit), %eax //void _exit(int status);
xorl %ebx, %ebx
int $0x80
ret
and built it like this:
$ gcc -Wall test.S -m32 -o test
verfied that we have a 32-bit executable:
$ file test
test: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.4, dynamically linked (uses shared libs), not stripped
and it appears to run OK:
$ ./test
hello wolrd
32-bit assembly code running on 64-bit platform
Linux uses the x86_64 ABI specified here. The best thing you can do is take a read through the bits of the ABI most relevant to your area. Here's a few that come to mind:
- Unlike x86 there is only one calling convention on x86_64; two if you count the fact that Microsoft Windows is totally different again.
- In x86, arguments to functions are commonly passed on the stack. in x86_64, the first few are in registers
rdi
,rsi
,rdx
,rcx
,r8
andr9
for integer types. - Memory address types are all
QWORD
so if you're using full registers (r10
etc) with AT&T syntax you'll needmovq
,addq
etc.
Now, part of the design of x86_64
was that it be backwards-compatible with x86
i.e. able to execute x86
code if the operating system is set up correctly. So, there is nothing wrong with for example doing this:
nasm -felf32 myprog.asm
gcc -o myprog -m32 myprog.o
However, be aware; the more you start to rely on other code being available, the more you need 32-bit copies of everything. Note that this is basically using code in 32-bit mode entirely, complete with calling convention and everything. In short, it should execute on a 32-bit machine too. As Jerry says (+1), you cannot compile 32-bit assembly using 32-bit conventions in 64-bit mode. You have to comply with the 64-bit ABI.
Of course, beyond that, you are free inside your routines to use registers like eax
, just be aware it affects the whole of rax
or rather the half that is `eax.
Related Topics
Error While Using a Newer Version of Glibc
/Usr/Bin/Ld: Skipping Incompatible Foo.So When Searching for Foo
Detecting a Change of Ip Address in Linux
Where Does Output of Print in Kernel Go
Linux: Run Cron Job in Foreground
Deceive the Jvm About the Number of Available Cores (On Linux)
Linux/Ubuntu Set: Illegal Option -O Pipefail
How to Create an Rs256 Jwt Assertion with Bash/Shell Scripting
Awk and Special Brackets Delimiters
Difference Between Bash Pid and $$
Find String Inside a Gzipped File in a Folder
Microsecond Accurate (Or Better) Process Timing in Linux
D-Bus Tutorial in C to Communicate with Wpa_Supplicant
Can Gdb Change the Assembly Code of a Running Program