From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 18130 invoked by alias); 20 Mar 2008 02:00:16 -0000 Received: (qmail 17926 invoked by uid 22791); 20 Mar 2008 02:00:15 -0000 X-Spam-Check-By: sourceware.org Received: from dessent.net (HELO dessent.net) (69.60.119.225) by sourceware.org (qpsmtpd/0.31) with ESMTP; Thu, 20 Mar 2008 01:59:57 +0000 Received: from localhost ([127.0.0.1] helo=dessent.net) by dessent.net with esmtp (Exim 4.50) id 1JcA4P-0005p6-55; Thu, 20 Mar 2008 01:59:53 +0000 Message-ID: <47E1C519.1ACB5CCB@dessent.net> Date: Thu, 20 Mar 2008 02:00:00 -0000 From: Brian Dessent Reply-To: gcc-help X-Mailer: Mozilla 4.79 [en] (Windows NT 5.0; U) MIME-Version: 1.0 To: Bob Plantz CC: gcc-help Subject: Re: 64-bit write() system call References: <1205972338.6330.9.camel@localhost> Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-IsSubscribed: yes Mailing-List: contact gcc-help-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-help-owner@gcc.gnu.org X-SW-Source: 2008-03/txt/msg00188.txt.bz2 Bob Plantz wrote: > The default address size is 64 bits in 64-bit mode. But when I look at > the assembly language for the write() syscall, gcc uses only 32 bits of > the address: The design of the x86_64 instruction set made some compromises for speed and for keeping the size of the instructions down, namely that there are very few instructions that take a full 64 bit operand... in fact 'movabs' is the only one. All the rest all take 32 bit operands and the address is calculated through either sign extension or as %rip-relative. This is actually not a big deal because these days most linking is done with shared libraries, and so you already have a level of indirection there with the PLT/GOT so it doesn't matter that much that it's awkward to refer to an absolute 64 bit address -- turns out this isn't a very common thing to need to do. If you read the x86_64 ELF document there are a number of different code models defined: small, medium, large, and kernel, corresponding to the gcc switch "-mcmodel=". The small model is the default and to quote the ELF document: > The virtual address of code executed is known at link time. Additionally > all symbols are known to be located in the virtual addresses in the > range from 0 to 2**31 - 2**24 - 1 or from 0x00000000 to 0x7effffff. > This allows the compiler to encode symbolic references with offsets in > the range from -(2**31) to 2**24 or from 0x80000000 to 0x01000000 > directly in the sign extended immediate operands, with offsets in the > range from 0 to 2**31 - 2**24 or from 0x00000000 to 0x7f000000 in the > zero extended immediate operands and use instruction pointer relative > addressing for the symbols with offsets in the range -(2**24) to 2**24 > or 0xff000000 to 0x01000000. This is the fastest code model and we > expect it to be suitable for the vast majority of programs. Because of these assumptions, the reference to your aLetter symbol can be handled with a simple 32 bit reloc (R_X86_64_32) which is defined as truncating the address into 32 bits. This combines with the fact that the processor zero extends 32 bit operations with register destinations, so when the value of that reloc is loaded into %esi the upper 32 bits of %rsi are implicitly set to zero. This also has an advantage for library calls like your call to write(), since %rip-relative addressing mode can cover the whole available address space -- the call will be be resolved with a R_X86_64_PLT32 reloc. The end result is 64 bit addressing without paying the price of wider opcodes or more complicated relocs, it's really a win-win. Of course for those apps that really need more arbitrary addressing, it's available in the other models, but this way the common case doesn't have to pay the price. Brian