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>
- Explain the parameters of
write(0, NULL, 12)
system call in the output of strace? - What exactly is happening? I want to know the reason why exactly its exiting with exitstatus=1?
- Can some one please show me how to debug this program using gdb?
- Why did they change the system call numbers?
- 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
I agree with him that these should be ELF 32-bit relocatable & executable. But that doesn't answer my my questions. All of my questions still questions. What exactly is happening in this case? Can someone please answer my questions and provide an x86-64 version of this code?