Compiling 32 Bit Assembler on 64 Bit Ubuntu

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.

  1. Make sure all the 32-bit gcc 4.8 development tools are completely installed:

    sudo apt-get install lib32gcc-4.8-dev

  2. 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 and r9 for integer types.
  • Memory address types are all QWORD so if you're using full registers (r10 etc) with AT&T syntax you'll need movq, 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



Leave a reply



Submit