System call numbers in 64 bit are different when compared to the 32 bit versions. They are obtained by adding the 32 bit system call number to 0x2000000 (see SYSCALL_CONSTRUCT_UNIX in syscall_hw.h).
Other 64 bit particularities are instruction pointer (%rip) relative data references.
If you try to assemble:
you get:
This is explained in the x86-64 Code Model:
Our hello world assembler program becomes:
Other 64 bit particularities are instruction pointer (%rip) relative data references.
If you try to assemble:
.data
msg:
.ascii "Hello, world!\n"
len:
.long . - msg
.text # text section
.globl _start # declare _start as global symbol for the linker to find
_start:
movq len, %rdx # length of string
you get:
cristi:64bit diciu$ as -arch x86_64 rdf.s -o rdf.o
rdf.s:14:32-bit absolute addressing is not supported for x86-64
rdf.s:14:cannot do signed 4 byte relocation
This is explained in the x86-64 Code Model:
All local and small data is accessed directly using addressing that’s relative to the instruction pointer (RIP-relative addressing). All large or possibly nonlocal data is accessed indirectly through a global offset table (GOT) entry. The GOT entry is accessed directly using RIP-relative addressing.
Our hello world assembler program becomes:
============= hello64bit.s ===================
#as -arch x86_64 hello64bit.s -o hello64bit.o
#ld -e _start -arch x86_64 hello64bit.o -o hello64bit
.data # data section
msg:
.ascii "Hello, world!\n" # ascii string to be printed
len:
.long . - msg # string length
.text # text section
.globl _start # declare _start as global symbol for the linker to find
_start:
movq $0x2000004, %rax # write call (see SYSCALL_CONSTRUCT_UNIX)
movq $1, %rdi # file descriptior (stdout)
movq msg@GOTPCREL(%rip), %rsi # string to print
movq len(%rip), %rdx # length of string
syscall # call write
movq $0x2000001, %rax # exit call
movq $0, %rdi # return code
syscall # call exit