Running 32 bit assembly code on a 64 bit Linux & 64 bit Processor : Explain the anomaly.

Posted by claws on Stack Overflow See other posts from Stack Overflow or by claws
Published on 2010-03-23T13:48:20Z Indexed on 2010/03/24 3:53 UTC
Read the original article Hit count: 444

Filed under:
|
|
|
|

Hello,

I'm in an interesting problem.I forgot I'm using 64bit machine & OS and wrote a 32 bit assembly code. I don't know how to write 64 bit code.

This is the x86 32-bit assembly code for Gnu Assembler (AT&T syntax) on Linux.

//hello.S
#include <asm/unistd.h>
#include <syscall.h>
#define STDOUT 1

.data
hellostr:
    .ascii "hello wolrd\n";
helloend:

.text
.globl _start

_start:
    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

Now, This code should run fine on a 32bit processor & 32 bit OS right? As we know 64 bit processors are backward compatible with 32 bit processors. So, that also wouldn't be a problem. The problem arises because of differences in system calls & call mechanism in 64-bit OS & 32-bit OS. I don't know why but they changed the system call numbers between 32-bit linux & 64-bit linux.

asm/unistd_32.h defines:

#define __NR_write        4
#define __NR_exit         1

asm/unistd_64.h defines:

#define __NR_write              1
#define __NR_exit               60

Anyway using Macros instead of direct numbers is paid off. Its ensuring correct system call numbers.

when I assemble & link & run the program.

$cpp hello.S hello.s //pre-processor
$as hello.s -o hello.o //assemble
$ld hello.o // linker : converting relocatable to executable

Its not printing helloworld.

In gdb its showing:

  • Program exited with code 01.

I don't know how to debug in gdb. using tutorial I tried to debug it and execute instruction by instruction checking registers at each step. its always showing me "program exited with 01". It would be great if some on could show me how to debug this.

(gdb) break _start
Note: breakpoint -10 also set at pc 0x4000b0.
Breakpoint 8 at 0x4000b0
(gdb) start
Function "main" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Temporary breakpoint 9 (main) pending.
Starting program: /home/claws/helloworld 

Program exited with code 01.
(gdb) info breakpoints 
Num     Type           Disp Enb Address            What
8       breakpoint     keep y   0x00000000004000b0 <_start>
9       breakpoint     del  y   <PENDING>          main

I tried running strace. This is its output:

execve("./helloworld", ["./helloworld"], [/* 39 vars */]) = 0
write(0, NULL, 12 <unfinished ... exit status 1>
  1. Explain the parameters of write(0, NULL, 12) system call in the output of strace?
  2. What exactly is happening? I want to know the reason why exactly its exiting with exitstatus=1?
  3. Can some one please show me how to debug this program using gdb?
  4. Why did they change the system call numbers?
  5. Kindly change this program appropriately so that it can run correctly on this machine.

EDIT:

After reading Paul R's answer. I checked my files

claws@claws-desktop:~$ file ./hello.o 
./hello.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped

claws@claws-desktop:~$ file ./hello
./hello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped

All of my questions still hold true. What exactly is happening in this case? Can someone please answer my questions and provide an x86-64 version of this code?

© Stack Overflow or respective owner

Related posts about assembly

Related posts about x86