From owner-freebsd-hackers Fri Aug 24 11:36:53 2001 Delivered-To: freebsd-hackers@freebsd.org Received: from mail.wrs.com (unknown-1-11.windriver.com [147.11.1.11]) by hub.freebsd.org (Postfix) with ESMTP id 8AF0637B412; Fri, 24 Aug 2001 11:36:41 -0700 (PDT) (envelope-from jhb@FreeBSD.org) Received: from laptop.baldwin.cx (john@[147.11.46.201]) by mail.wrs.com (8.9.3/8.9.1) with ESMTP id LAA12322; Fri, 24 Aug 2001 11:36:39 -0700 (PDT) Message-ID: X-Mailer: XFMail 1.4.0 on FreeBSD X-Priority: 3 (Normal) Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 8bit MIME-Version: 1.0 In-Reply-To: <20010824110805.C88259@dragon.nuxi.com> Date: Fri, 24 Aug 2001 11:36:45 -0700 (PDT) From: John Baldwin To: "David O'Brien" Subject: Re: function calls/rets in assembly Cc: freebsd-hackers@FreeBSD.org, Steve Roome Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG On 24-Aug-01 David O'Brien wrote: > On Fri, Aug 24, 2001 at 01:01:39AM +0100, Steve Roome wrote: >> How exactly should functions work in assembly, afaict, the >> following C : >> >> void printasint(int p) { printf ("print this %d\n", (int)p);} > > Why not just ask the compiler?? > > $ cc -S -O0 printasint.c > $ cat printasint.s > > > .file "foo.c" > .version "01.01" > gcc2_compiled.: > .section .rodata > .LC0: > .byte 0x70,0x72,0x69,0x6e,0x74,0x20,0x74,0x68,0x69,0x73 > .byte 0x20,0x25,0x64,0xa,0x0 > .text > .p2align 2,0x90 > .globl printasint > .type printasint,@function > printasint: > pushl %ebp > movl %esp,%ebp > subl $8,%esp > addl $-8,%esp > movl 8(%ebp),%eax > pushl %eax > pushl $.LC0 > call printf > addl $16,%esp > .L2: > leave > ret > .Lfe1: Because this code is broken and obfuscated? :) We save %esp in %ebp (the only thing that keeps it from breaking) then for some reason allocate two quadwords on the stack unnecessarily, one using an add instruction, one using a sub. Then we push the two dword args on the stack and call the function. After the call, we adjust the stack by 16, even though we only used 8 bytes of arguments! Thus, it seems to be reclaiming one of the 2 quadwords it allocated on the stack in addition to the arguments passed to the function. At this point if we did a 'pop %ebp' instead of leave, things would break since we have a misaligned stack, but the leave restores the %esp from %ebp, before pop'ing %ebp thus working around the bogus stack handling. A better version would be this: printasint: pushl %ebp movl %ebp, %esp pushl 8(%ebp) pushl $.LC0 call printf addl $8,%esp leave ret Note that with hand optimizing, you could axe the addl after the call since leave will clean up after that anyways. Also, you don't really need a frame here anyways. In that case, you could just push 8(%esp) as your first instruction and axe the leave (but leave the addl). -- John Baldwin -- http://www.FreeBSD.org/~jhb/ PGP Key: http://www.baldwin.cx/~john/pgpkey.asc "Power Users Use the Power to Serve!" - http://www.FreeBSD.org/ To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message